diff options
| author | 2010-01-21 15:15:23 -0800 | |
|---|---|---|
| committer | 2010-01-25 11:27:08 -0800 | |
| commit | 1edab2b551995a8df25f4b533405d6003b8b8b66 (patch) | |
| tree | 5d6f545170ac5820c19b03e1aea6fd3332084c3d | |
| parent | 8fdd45e1aa26e62fe02b053683624ac2b28bce93 (diff) | |
Make PackageManager unpack gdbserver binaries at installation time.
Native-debuggable packages contain a lib/<abi>/gdbserver executable.
This patch ensures that the package manager will copy it to the
proper location (/data/data/<appname>/lib) at installation time.
Note that such packages are marked with a new ApplicationInfo flag
named FLAG_NATIVE_DEBUGGABLE, to be used later by the Activity
Manager.
| -rw-r--r-- | core/java/android/content/pm/ApplicationInfo.java | 8 | ||||
| -rw-r--r-- | services/java/com/android/server/PackageManagerService.java | 90 |
2 files changed, 84 insertions, 14 deletions
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index a7ea507b7c19..808c839bc6b4 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -234,6 +234,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final int FLAG_ON_SDCARD = 1<<19; /** + * Value for {@link #flags}: Set to true if the application is + * native-debuggable, i.e. embeds a gdbserver binary in its .apk + * + * {@hide} + */ + public static final int FLAG_NATIVE_DEBUGGABLE = 1<<20; + + /** * Flags associated with the application. Any combination of * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE}, * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index cafc80462eee..13079728d504 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -2855,9 +2855,8 @@ class PackageManagerService extends IPackageManager.Stub { // room left on the data partition, or a ZipException if the package // file is malformed. // - private int cachePackageSharedLibsForAbiLI( PackageParser.Package pkg, - File dataPath, File scanFile, String cpuAbi) - throws IOException, ZipException { + private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg, + File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException { File sharedLibraryDir = new File(dataPath.getPath() + "/lib"); final String apkLib = "lib/"; final int apkLibLen = apkLib.length(); @@ -2935,7 +2934,7 @@ class PackageManagerService extends IPackageManager.Stub { if (mInstaller == null) { sharedLibraryDir.mkdir(); } - cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir, + cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir, sharedLibraryFile); } } @@ -2948,6 +2947,54 @@ class PackageManagerService extends IPackageManager.Stub { return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES; } + // Find the gdbserver executable program in a package at + // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver + // + // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success, + // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise. + // + private int cachePackageGdbServerLI(PackageParser.Package pkg, + File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException { + File installGdbServerDir = new File(dataPath.getPath() + "/lib"); + final String GDBSERVER = "gdbserver"; + final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER; + + ZipFile zipFile = new ZipFile(scanFile); + Enumeration<ZipEntry> entries = + (Enumeration<ZipEntry>) zipFile.entries(); + + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + // skip directories + if (entry.isDirectory()) { + continue; + } + String entryName = entry.getName(); + + if (!entryName.equals(apkGdbServerPath)) { + continue; + } + + String installGdbServerPath = installGdbServerDir.getPath() + + "/" + GDBSERVER; + File installGdbServerFile = new File(installGdbServerPath); + if (! installGdbServerFile.exists() || + installGdbServerFile.length() != entry.getSize() || + installGdbServerFile.lastModified() != entry.getTime()) { + if (Config.LOGD) { + Log.d(TAG, "Caching gdbserver " + entry.getName()); + } + if (mInstaller == null) { + installGdbServerDir.mkdir(); + } + cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir, + installGdbServerFile); + } + return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES; + } + return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES; + } + // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so // and copy them to /data/data/<appname>/lib. // @@ -2957,7 +3004,7 @@ class PackageManagerService extends IPackageManager.Stub { // private int cachePackageSharedLibsLI(PackageParser.Package pkg, File dataPath, File scanFile) { - final String cpuAbi = Build.CPU_ABI; + String cpuAbi = Build.CPU_ABI; try { int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi); @@ -2968,7 +3015,7 @@ class PackageManagerService extends IPackageManager.Stub { // // only scan the package twice in case of ABI mismatch if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) { - String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null); + final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null); if (cpuAbi2 != null) { result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2); } @@ -2977,6 +3024,20 @@ class PackageManagerService extends IPackageManager.Stub { Log.w(TAG,"Native ABI mismatch from package file"); return PackageManager.INSTALL_FAILED_INVALID_APK; } + + if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) { + cpuAbi = cpuAbi2; + } + } + + // for debuggable packages, also extract gdbserver from lib/<abi> + // into /data/data/<appname>/lib too. + if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES && + (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi); + if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE; + } } } catch (ZipException e) { Log.w(TAG, "Failed to extract data from package file", e); @@ -2988,26 +3049,27 @@ class PackageManagerService extends IPackageManager.Stub { return PackageManager.INSTALL_SUCCEEDED; } - private void cacheSharedLibLI(PackageParser.Package pkg, + private void cacheNativeBinaryLI(PackageParser.Package pkg, ZipFile zipFile, ZipEntry entry, - File sharedLibraryDir, - File sharedLibraryFile) throws IOException { + File binaryDir, + File binaryFile) throws IOException { InputStream inputStream = zipFile.getInputStream(entry); try { - File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir); + File tempFile = File.createTempFile("tmp", "tmp", binaryDir); String tempFilePath = tempFile.getPath(); - // XXX package manager can't change owner, so the lib files for + // XXX package manager can't change owner, so the executable files for // now need to be left as world readable and owned by the system. if (! FileUtils.copyToFile(inputStream, tempFile) || ! tempFile.setLastModified(entry.getTime()) || FileUtils.setPermissions(tempFilePath, FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP + |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH |FileUtils.S_IROTH, -1, -1) != 0 || - ! tempFile.renameTo(sharedLibraryFile)) { + ! tempFile.renameTo(binaryFile)) { // Failed to properly write file. tempFile.delete(); - throw new IOException("Couldn't create cached shared lib " - + sharedLibraryFile + " in " + sharedLibraryDir); + throw new IOException("Couldn't create cached binary " + + binaryFile + " in " + binaryDir); } } finally { inputStream.close(); |