public string[] CacheApplicationLibraries()
{
//
// Application binaries (those under /lib/ of an installed application).
// TODO: Consider improving this. Pulling libraries ensures consistency, but takes time (ADB is a slow protocol).
//
LoggingUtils.PrintFunction ();
try
{
List<string> additionalLibraries = new List<string> ();
foreach (string nativeLibraryAbiPath in Process.NativeLibraryAbiPaths)
{
string nativeOatLibraryPath = nativeLibraryAbiPath.Replace ("/lib", "/oat");
//
// On Android L, Google have broken pull permissions to 'app-lib' (and '/data/app/XXX/lib/') content so we use cp to avoid this.
//
bool pulledLibraries = false;
string libraryCachePath = Path.Combine (CacheSysRoot, nativeLibraryAbiPath.Substring (1));
Directory.CreateDirectory (libraryCachePath);
if (Process.HostDevice.SdkVersion >= AndroidSettings.VersionCode.LOLLIPOP)
{
string [] libraries = Process.HostDevice.Shell ("ls", nativeLibraryAbiPath).Replace ("\r", "").Split (new char [] { '\n', ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string file in libraries)
{
string remoteLib = nativeLibraryAbiPath + "/" + file;
string temporaryStorage = "/data/local/tmp/" + file;
try
{
Process.HostDevice.Shell ("cp", string.Format ("-fH {0} {1}", remoteLib, temporaryStorage));
Process.HostDevice.Pull (temporaryStorage, libraryCachePath);
Process.HostDevice.Shell ("rm", temporaryStorage);
LoggingUtils.Print (string.Format ("[GdbSetup] Pulled {0} from device/emulator.", remoteLib));
pulledLibraries = true;
}
catch (Exception e)
{
LoggingUtils.HandleException (string.Format ("[GdbSetup] Failed pulling {0} from device/emulator.", remoteLib), e);
}
}
}
//
// Also on Android L, Google's new oat format is an ELF which is readable by GDB. We want to include this in the sysroot.
//
bool pulledOatLibraries = false;
string libraryOatCachePath = Path.Combine (CacheSysRoot, nativeOatLibraryPath.Substring (1));
Directory.CreateDirectory (libraryOatCachePath);
if (Process.HostDevice.SdkVersion >= AndroidSettings.VersionCode.LOLLIPOP)
{
string [] oatLibraries = new string []
{
// Due to permissions these have to be directly referenced; ls won't work.
"base.odex"
};
foreach (string file in oatLibraries)
{
string remoteLib = nativeOatLibraryPath + "/" + file;
string temporaryStorage = "/data/local/tmp/" + file;
try
{
Process.HostDevice.Shell ("cp", string.Format ("-fH {0} {1}", remoteLib, temporaryStorage));
Process.HostDevice.Pull (temporaryStorage, libraryCachePath);
Process.HostDevice.Shell ("rm", temporaryStorage);
LoggingUtils.Print (string.Format ("[GdbSetup] Pulled {0} from device/emulator.", remoteLib));
pulledOatLibraries = true;
}
catch (Exception e)
{
LoggingUtils.HandleException (string.Format ("[GdbSetup] Failed pulling {0} from device/emulator.", remoteLib), e);
}
}
}
try
{
if (!pulledLibraries)
{
Process.HostDevice.Pull (nativeLibraryAbiPath, libraryCachePath);
LoggingUtils.Print (string.Format ("[GdbSetup] Pulled {0} from device/emulator.", nativeLibraryAbiPath));
pulledLibraries = true;
}
if (!pulledOatLibraries)
{
Process.HostDevice.Pull (nativeOatLibraryPath, libraryOatCachePath);
LoggingUtils.Print (string.Format ("[GdbSetup] Pulled {0} from device/emulator.", nativeOatLibraryPath));
pulledOatLibraries = true;
}
}
catch (Exception e)
{
LoggingUtils.HandleException (string.Format ("[GdbSetup] Failed pulling {0} from device/emulator.", nativeLibraryAbiPath), e);
}
additionalLibraries.AddRange (Directory.GetFiles (libraryCachePath, "lib*.so", SearchOption.AllDirectories));
additionalLibraries.AddRange (Directory.GetFiles (libraryOatCachePath, "*.odex", SearchOption.AllDirectories));
}
return additionalLibraries.ToArray ();
}
catch (Exception e)
{
LoggingUtils.HandleException (e);
}
return new string [] {};
}