diff options
Diffstat (limited to 'core')
4 files changed, 107 insertions, 32 deletions
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 1e93d92..4939fb6 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -491,13 +491,55 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public String nativeLibraryDir; /** - * The ABI that this application requires, This is inferred from the ABIs + * The path under the apps data directory we store unpacked libraries. For + * new installs, we create subdirectories under legacyNativeLibraryDir that are + * architecture specific. For legacy installs, the shared libraries are + * placed directly under this path. + * + * For "legacy" installs {@code nativeLibraryDir} will be equal to this path. + * For newer installs, it will be derived based on the codePath and the primary + * cpu abi. + * + * @hide. + */ + public String legacyNativeLibraryDir; + + /** + * The primary ABI that this application requires, This is inferred from the ABIs * of the native JNI libraries the application bundles. Will be {@code null} * if this application does not require any particular ABI. * + * If non-null, the application will always be launched with this ABI. + * + * {@hide} + */ + public String primaryCpuAbi; + + /** + * The secondary ABI for this application. Might be non-null for multi-arch + * installs. The application itself never uses this ABI, but other applications that + * use its code might. + * + * {@hide} + */ + public String secondaryCpuAbi; + + /** + * The derived APK "root" for the given package. Will be non-null for bundled and + * updated system apps. This will be a top level path under which apks and libraries + * are installed, for eg. {@code /system}, {@code /oem} or {@code /vendor}. This is + * used to calculate the location of native code for a given package, for e.g + * {@code /vendor/lib} or {@code /vendor/lib64}. + * + * For app updates or fresh app installs, this will be {@code null} and we will use + * {@code legacyNativeLibraryDir} + * + * NOTE: This can be removed if we have a unified layout for bundled and installed + * apps. + * * {@hide} */ - public String cpuAbi; + public String apkRoot; /** * The kernel user-ID that has been assigned to this application; @@ -641,7 +683,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { splitSourceDirs = orig.splitSourceDirs; splitPublicSourceDirs = orig.splitPublicSourceDirs; nativeLibraryDir = orig.nativeLibraryDir; - cpuAbi = orig.cpuAbi; + legacyNativeLibraryDir = orig.legacyNativeLibraryDir; + primaryCpuAbi = orig.primaryCpuAbi; + secondaryCpuAbi = orig.secondaryCpuAbi; + apkRoot = orig.apkRoot; resourceDirs = orig.resourceDirs; seinfo = orig.seinfo; sharedLibraryFiles = orig.sharedLibraryFiles; @@ -685,7 +730,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeStringArray(splitSourceDirs); dest.writeStringArray(splitPublicSourceDirs); dest.writeString(nativeLibraryDir); - dest.writeString(cpuAbi); + dest.writeString(legacyNativeLibraryDir); + dest.writeString(primaryCpuAbi); + dest.writeString(secondaryCpuAbi); + dest.writeString(apkRoot); dest.writeStringArray(resourceDirs); dest.writeString(seinfo); dest.writeStringArray(sharedLibraryFiles); @@ -728,7 +776,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { splitSourceDirs = source.readStringArray(); splitPublicSourceDirs = source.readStringArray(); nativeLibraryDir = source.readString(); - cpuAbi = source.readString(); + legacyNativeLibraryDir = source.readString(); + primaryCpuAbi = source.readString(); + secondaryCpuAbi = source.readString(); + apkRoot = source.readString(); resourceDirs = source.readStringArray(); seinfo = source.readString(); sharedLibraryFiles = source.readStringArray(); diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java index a1566da..50a0483 100644 --- a/core/java/android/content/pm/PackageInfoLite.java +++ b/core/java/android/content/pm/PackageInfoLite.java @@ -37,6 +37,13 @@ public class PackageInfoLite implements Parcelable { public int versionCode; /** + * The android:multiArch flag from the package manifest. If set, + * we will extract all native libraries for the given app, not just those + * from the preferred ABI. + */ + public boolean multiArch; + + /** * Specifies the recommended install location. Can be one of * {@link #PackageHelper.RECOMMEND_INSTALL_INTERNAL} to install on internal storage * {@link #PackageHelper.RECOMMEND_INSTALL_EXTERNAL} to install on external media diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index ab0bf25..6e0ca50 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -249,6 +249,8 @@ public class PackageParser { /** Paths of any split APKs, ordered by parsed splitName */ public final String[] splitCodePaths; + public final boolean multiArch; + private PackageLite(String codePath, ApkLite baseApk, String[] splitNames, String[] splitCodePaths) { this.packageName = baseApk.packageName; @@ -259,6 +261,7 @@ public class PackageParser { this.codePath = codePath; this.baseCodePath = baseApk.codePath; this.splitCodePaths = splitCodePaths; + this.multiArch = baseApk.multiArch; } public List<String> getAllCodePaths() { @@ -282,9 +285,11 @@ public class PackageParser { public final int installLocation; public final VerifierInfo[] verifiers; public final Signature[] signatures; + public final boolean multiArch; public ApkLite(String codePath, String packageName, String splitName, int versionCode, - int installLocation, List<VerifierInfo> verifiers, Signature[] signatures) { + int installLocation, List<VerifierInfo> verifiers, Signature[] signatures, + boolean multiArch) { this.codePath = codePath; this.packageName = packageName; this.splitName = splitName; @@ -292,6 +297,7 @@ public class PackageParser { this.installLocation = installLocation; this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); this.signatures = signatures; + this.multiArch = multiArch; } } @@ -1114,6 +1120,7 @@ public class PackageParser { int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; int versionCode = 0; int numFound = 0; + boolean multiArch = false; for (int i = 0; i < attrs.getAttributeCount(); i++) { String attr = attrs.getAttributeName(i); if (attr.equals("installLocation")) { @@ -1123,8 +1130,11 @@ public class PackageParser { } else if (attr.equals("versionCode")) { versionCode = attrs.getAttributeIntValue(i, 0); numFound++; + } else if (attr.equals("multiArch")) { + multiArch = attrs.getAttributeBooleanValue(i, false); + numFound++; } - if (numFound >= 2) { + if (numFound >= 3) { break; } } @@ -1149,7 +1159,7 @@ public class PackageParser { } return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode, - installLocation, verifiers, signatures); + installLocation, verifiers, signatures, multiArch); } /** diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java index d66a7bb..d76d0d4 100644 --- a/core/java/com/android/internal/content/NativeLibraryHelper.java +++ b/core/java/com/android/internal/content/NativeLibraryHelper.java @@ -131,10 +131,15 @@ public class NativeLibraryHelper { * * @return size of all native binary files in bytes */ - public static long sumNativeBinariesLI(Handle handle, String abi) { + public static long sumNativeBinariesLI(Handle handle, String[] abis) { long sum = 0; for (long apkHandle : handle.apkHandles) { - sum += nativeSumNativeBinaries(apkHandle, abi); + // NOTE: For a given APK handle, we parse the central directory precisely + // once, but prefix matching of entries requires a CD traversal, which can + // take a while (even if it needs no additional I/O). + for (String abi : abis) { + sum += nativeSumNativeBinaries(apkHandle, abi); + } } return sum; } @@ -196,45 +201,47 @@ public class NativeLibraryHelper { private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis); // Convenience method to call removeNativeBinariesFromDirLI(File) - public static boolean removeNativeBinariesLI(String nativeLibraryPath) { - if (nativeLibraryPath == null) return false; - return removeNativeBinariesFromDirLI(new File(nativeLibraryPath)); + public static void removeNativeBinariesLI(String nativeLibraryPath) { + if (nativeLibraryPath == null) return; + removeNativeBinariesFromDirLI(new File(nativeLibraryPath), false /* delete root dir */); } - // Remove the native binaries of a given package. This simply - // gets rid of the files in the 'lib' sub-directory. - public static boolean removeNativeBinariesFromDirLI(File nativeLibraryDir) { + /** + * Remove the native binaries of a given package. This deletes the files + */ + public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot, boolean deleteRootDir) { if (DEBUG_NATIVE) { - Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryDir.getPath()); + Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath()); } - boolean deletedFiles = false; - /* * Just remove any file in the directory. Since the directory is owned * by the 'system' UID, the application is not supposed to have written * anything there. */ - if (nativeLibraryDir.exists()) { - final File[] binaries = nativeLibraryDir.listFiles(); - if (binaries != null) { - for (int nn = 0; nn < binaries.length; nn++) { + if (nativeLibraryRoot.exists()) { + final File[] files = nativeLibraryRoot.listFiles(); + if (files != null) { + for (int nn = 0; nn < files.length; nn++) { if (DEBUG_NATIVE) { - Slog.d(TAG, " Deleting " + binaries[nn].getName()); + Slog.d(TAG, " Deleting " + files[nn].getName()); } - if (!binaries[nn].delete()) { - Slog.w(TAG, "Could not delete native binary: " + binaries[nn].getPath()); - } else { - deletedFiles = true; + if (files[nn].isDirectory()) { + removeNativeBinariesFromDirLI(files[nn], true /* delete root dir */); + } else if (!files[nn].delete()) { + Slog.w(TAG, "Could not delete native binary: " + files[nn].getPath()); } } } - // Do not delete 'lib' directory itself, or this will prevent - // installation of future updates. + // Do not delete 'lib' directory itself, unless we're specifically + // asked to or this will prevent installation of future updates. + if (deleteRootDir) { + if (!nativeLibraryRoot.delete()) { + Slog.w(TAG, "Could not delete native binary directory: " + nativeLibraryRoot.getPath()); + } + } } - - return deletedFiles; } // We don't care about the other return values for now. |