Loading core/java/android/content/pm/ApplicationInfo.java +56 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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(); Loading core/java/android/content/pm/PackageInfoLite.java +7 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,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 Loading core/java/android/content/pm/PackageParser.java +13 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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() { Loading @@ -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; Loading @@ -292,6 +297,7 @@ public class PackageParser { this.installLocation = installLocation; this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); this.signatures = signatures; this.multiArch = multiArch; } } Loading Loading @@ -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")) { Loading @@ -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; } } Loading @@ -1149,7 +1159,7 @@ public class PackageParser { } return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode, installLocation, verifiers, signatures); installLocation, verifiers, signatures, multiArch); } /** Loading core/java/com/android/internal/content/NativeLibraryHelper.java +31 −24 Original line number Diff line number Diff line Loading @@ -131,11 +131,16 @@ 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) { // 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; } Loading Loading @@ -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. Loading packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +71 −35 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.internal.content.PackageHelper; import com.android.internal.os.IParcelFileDescriptorFactory; import com.android.internal.util.ArrayUtils; import dalvik.system.VMRuntime; import libcore.io.IoUtils; import libcore.io.Streams; Loading Loading @@ -186,6 +187,7 @@ public class DefaultContainerService extends IntentService { ret.verifiers = pkg.verifiers; ret.recommendedInstallLocation = recommendAppInstallLocation(pkg, flags, threshold, abiOverride); ret.multiArch = pkg.multiArch; return ret; } Loading Loading @@ -363,31 +365,26 @@ public class DefaultContainerService extends IntentService { final String resFileName = "pkg.apk"; final String publicResFileName = "res.zip"; // The .apk file String codePath = pkg.baseCodePath; File codeFile = new File(codePath); if (pkg.multiArch) { // TODO: Support multiArch installs on ASEC. throw new IllegalArgumentException("multiArch not supported on ASEC installs."); } String[] abiList = Build.SUPPORTED_ABIS; if (abiOverride != null) { abiList = new String[] { abiOverride }; } else { // The .apk file final String codePath = pkg.baseCodePath; final File codeFile = new File(codePath); final String[] abis; try { if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && NativeLibraryHelper.hasRenderscriptBitcode(handle)) { abiList = Build.SUPPORTED_32_BIT_ABIS; } abis = calculateAbiList(handle, abiOverride, pkg.multiArch); } catch (IOException ioe) { Slog.w(TAG, "Problem determining ABI for: " + codeFile.getPath()); Slog.w(TAG, "Problem determining app ABIS: " + ioe); return null; } } final int abiIndex = NativeLibraryHelper.findSupportedAbi(handle, abiList); // Calculate size of container needed to hold base APK. final int sizeMb; try { sizeMb = calculateContainerSize(pkg, handle, isForwardLocked, abiIndex); sizeMb = calculateContainerSize(pkg, handle, isForwardLocked, abis); } catch (IOException e) { Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath()); return null; Loading Loading @@ -451,18 +448,19 @@ public class DefaultContainerService extends IntentService { final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME); if (sharedLibraryDir.mkdir()) { int ret = PackageManager.INSTALL_SUCCEEDED; if (abiIndex >= 0) { if (abis != null) { // TODO(multiArch): Support multi-arch installs on asecs. Note that we are NOT // using an ISA specific subdir here for now. final String abi = abis[0]; ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, sharedLibraryDir, abiList[abiIndex]); } else if (abiIndex != PackageManager.NO_NATIVE_LIBRARIES) { ret = abiIndex; } sharedLibraryDir, abi); if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath()); PackageHelper.destroySdDir(newCid); return null; } } } else { Slog.e(TAG, "Could not create native lib directory: " + sharedLibraryDir.getPath()); PackageHelper.destroySdDir(newCid); Loading Loading @@ -687,14 +685,53 @@ public class DefaultContainerService extends IntentService { NativeLibraryHelper.Handle handle = null; try { handle = NativeLibraryHelper.Handle.create(pkg); final int abi = NativeLibraryHelper.findSupportedAbi(handle, (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS); return calculateContainerSize(pkg, handle, isForwardLocked, abi); return calculateContainerSize(pkg, handle, isForwardLocked, calculateAbiList(handle, abiOverride, pkg.multiArch)); } finally { IoUtils.closeQuietly(handle); } } private String[] calculateAbiList(NativeLibraryHelper.Handle handle, String abiOverride, boolean isMultiArch) throws IOException { if (isMultiArch) { final int abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS); final int abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS); if (abi32 >= 0 && abi64 >= 0) { return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64], Build.SUPPORTED_32_BIT_ABIS[abi32] }; } else if (abi64 >= 0) { return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64] }; } else if (abi32 >= 0) { return new String[] { Build.SUPPORTED_32_BIT_ABIS[abi32] }; } if (abi64 != PackageManager.NO_NATIVE_LIBRARIES || abi32 != PackageManager.NO_NATIVE_LIBRARIES) { throw new IOException("Error determining ABI list: errorCode=[" + abi32 + "," + abi64 + "]"); } } else { String[] abiList = Build.SUPPORTED_ABIS; if (abiOverride != null) { abiList = new String[] { abiOverride }; } else if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && NativeLibraryHelper.hasRenderscriptBitcode(handle)) { abiList = Build.SUPPORTED_32_BIT_ABIS; } final int abi = NativeLibraryHelper.findSupportedAbi(handle,abiList); if (abi >= 0) { return new String[]{Build.SUPPORTED_ABIS[abi]}; } if (abi != PackageManager.NO_NATIVE_LIBRARIES) { throw new IOException("Error determining ABI list: errorCode=" + abi); } } return null; } /** * Calculate the container size for a package. * Loading @@ -702,7 +739,7 @@ public class DefaultContainerService extends IntentService { * @throws IOException when there is a problem reading the file */ private int calculateContainerSize(PackageLite pkg, NativeLibraryHelper.Handle handle, boolean isForwardLocked, int abiIndex) throws IOException { boolean isForwardLocked, String[] abis) throws IOException { // Calculate size of container needed to hold APKs. long sizeBytes = 0; for (String codePath : pkg.getAllCodePaths()) { Loading @@ -715,9 +752,8 @@ public class DefaultContainerService extends IntentService { // Check all the native files that need to be copied and add that to the // container size. if (abiIndex >= 0) { sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle, Build.SUPPORTED_ABIS[abiIndex]); if (abis != null) { sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle, abis); } int sizeMb = (int) (sizeBytes >> 20); Loading Loading
core/java/android/content/pm/ApplicationInfo.java +56 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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(); Loading
core/java/android/content/pm/PackageInfoLite.java +7 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,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 Loading
core/java/android/content/pm/PackageParser.java +13 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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() { Loading @@ -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; Loading @@ -292,6 +297,7 @@ public class PackageParser { this.installLocation = installLocation; this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); this.signatures = signatures; this.multiArch = multiArch; } } Loading Loading @@ -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")) { Loading @@ -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; } } Loading @@ -1149,7 +1159,7 @@ public class PackageParser { } return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode, installLocation, verifiers, signatures); installLocation, verifiers, signatures, multiArch); } /** Loading
core/java/com/android/internal/content/NativeLibraryHelper.java +31 −24 Original line number Diff line number Diff line Loading @@ -131,11 +131,16 @@ 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) { // 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; } Loading Loading @@ -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. Loading
packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +71 −35 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.internal.content.PackageHelper; import com.android.internal.os.IParcelFileDescriptorFactory; import com.android.internal.util.ArrayUtils; import dalvik.system.VMRuntime; import libcore.io.IoUtils; import libcore.io.Streams; Loading Loading @@ -186,6 +187,7 @@ public class DefaultContainerService extends IntentService { ret.verifiers = pkg.verifiers; ret.recommendedInstallLocation = recommendAppInstallLocation(pkg, flags, threshold, abiOverride); ret.multiArch = pkg.multiArch; return ret; } Loading Loading @@ -363,31 +365,26 @@ public class DefaultContainerService extends IntentService { final String resFileName = "pkg.apk"; final String publicResFileName = "res.zip"; // The .apk file String codePath = pkg.baseCodePath; File codeFile = new File(codePath); if (pkg.multiArch) { // TODO: Support multiArch installs on ASEC. throw new IllegalArgumentException("multiArch not supported on ASEC installs."); } String[] abiList = Build.SUPPORTED_ABIS; if (abiOverride != null) { abiList = new String[] { abiOverride }; } else { // The .apk file final String codePath = pkg.baseCodePath; final File codeFile = new File(codePath); final String[] abis; try { if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && NativeLibraryHelper.hasRenderscriptBitcode(handle)) { abiList = Build.SUPPORTED_32_BIT_ABIS; } abis = calculateAbiList(handle, abiOverride, pkg.multiArch); } catch (IOException ioe) { Slog.w(TAG, "Problem determining ABI for: " + codeFile.getPath()); Slog.w(TAG, "Problem determining app ABIS: " + ioe); return null; } } final int abiIndex = NativeLibraryHelper.findSupportedAbi(handle, abiList); // Calculate size of container needed to hold base APK. final int sizeMb; try { sizeMb = calculateContainerSize(pkg, handle, isForwardLocked, abiIndex); sizeMb = calculateContainerSize(pkg, handle, isForwardLocked, abis); } catch (IOException e) { Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath()); return null; Loading Loading @@ -451,18 +448,19 @@ public class DefaultContainerService extends IntentService { final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME); if (sharedLibraryDir.mkdir()) { int ret = PackageManager.INSTALL_SUCCEEDED; if (abiIndex >= 0) { if (abis != null) { // TODO(multiArch): Support multi-arch installs on asecs. Note that we are NOT // using an ISA specific subdir here for now. final String abi = abis[0]; ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, sharedLibraryDir, abiList[abiIndex]); } else if (abiIndex != PackageManager.NO_NATIVE_LIBRARIES) { ret = abiIndex; } sharedLibraryDir, abi); if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath()); PackageHelper.destroySdDir(newCid); return null; } } } else { Slog.e(TAG, "Could not create native lib directory: " + sharedLibraryDir.getPath()); PackageHelper.destroySdDir(newCid); Loading Loading @@ -687,14 +685,53 @@ public class DefaultContainerService extends IntentService { NativeLibraryHelper.Handle handle = null; try { handle = NativeLibraryHelper.Handle.create(pkg); final int abi = NativeLibraryHelper.findSupportedAbi(handle, (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS); return calculateContainerSize(pkg, handle, isForwardLocked, abi); return calculateContainerSize(pkg, handle, isForwardLocked, calculateAbiList(handle, abiOverride, pkg.multiArch)); } finally { IoUtils.closeQuietly(handle); } } private String[] calculateAbiList(NativeLibraryHelper.Handle handle, String abiOverride, boolean isMultiArch) throws IOException { if (isMultiArch) { final int abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS); final int abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS); if (abi32 >= 0 && abi64 >= 0) { return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64], Build.SUPPORTED_32_BIT_ABIS[abi32] }; } else if (abi64 >= 0) { return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64] }; } else if (abi32 >= 0) { return new String[] { Build.SUPPORTED_32_BIT_ABIS[abi32] }; } if (abi64 != PackageManager.NO_NATIVE_LIBRARIES || abi32 != PackageManager.NO_NATIVE_LIBRARIES) { throw new IOException("Error determining ABI list: errorCode=[" + abi32 + "," + abi64 + "]"); } } else { String[] abiList = Build.SUPPORTED_ABIS; if (abiOverride != null) { abiList = new String[] { abiOverride }; } else if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && NativeLibraryHelper.hasRenderscriptBitcode(handle)) { abiList = Build.SUPPORTED_32_BIT_ABIS; } final int abi = NativeLibraryHelper.findSupportedAbi(handle,abiList); if (abi >= 0) { return new String[]{Build.SUPPORTED_ABIS[abi]}; } if (abi != PackageManager.NO_NATIVE_LIBRARIES) { throw new IOException("Error determining ABI list: errorCode=" + abi); } } return null; } /** * Calculate the container size for a package. * Loading @@ -702,7 +739,7 @@ public class DefaultContainerService extends IntentService { * @throws IOException when there is a problem reading the file */ private int calculateContainerSize(PackageLite pkg, NativeLibraryHelper.Handle handle, boolean isForwardLocked, int abiIndex) throws IOException { boolean isForwardLocked, String[] abis) throws IOException { // Calculate size of container needed to hold APKs. long sizeBytes = 0; for (String codePath : pkg.getAllCodePaths()) { Loading @@ -715,9 +752,8 @@ public class DefaultContainerService extends IntentService { // Check all the native files that need to be copied and add that to the // container size. if (abiIndex >= 0) { sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle, Build.SUPPORTED_ABIS[abiIndex]); if (abis != null) { sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle, abis); } int sizeMb = (int) (sizeBytes >> 20); Loading