diff options
author | Jeff Sharkey <jsharkey@android.com> | 2014-07-04 20:18:13 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2014-07-04 21:00:33 -0700 |
commit | 73767b9d607d99b3a027619b5c6b7f1a09b7673d (patch) | |
tree | 4906ccdb54022a1a0b47950c5cb0546c585c75c0 | |
parent | 9810f39717f3625222af9d710f7d8f5acca28449 (diff) | |
download | frameworks_base-73767b9d607d99b3a027619b5c6b7f1a09b7673d.zip frameworks_base-73767b9d607d99b3a027619b5c6b7f1a09b7673d.tar.gz frameworks_base-73767b9d607d99b3a027619b5c6b7f1a09b7673d.tar.bz2 |
Extract native code from split APKs.
In the new split APK world, multiple APKs work together to define a
single package. This means that native code may be split among those
APKs. To handle this, extend NativeLibraryHelper to examine all
APKs in a package ordered by splitName.
A package has valid native code as long as one matching ABI is found
inside. The "best" ABI found across all APKs is picked for the
entire package. No attempt is made to ensure that every native
library defined is available for the picked ABI; that's the
responsibility of the installer.
Re-introduce PackageLite to represent a lightweight parsing of an
entire package, which may be a single monolithic APK or a cluster
of one or more APKs.
Remove native code extraction from InstallerSession, since it'll be
handled inside PMS for this release.
Bug: 14975160
Change-Id: I4f4db0f82e88a46101c7777499ebc0a11fd911f9
6 files changed, 256 insertions, 160 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 319559a..a5290aa 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -227,6 +227,48 @@ public class PackageParser { } /** + * Lightweight parsed details about a single package. + */ + public static class PackageLite { + public final String packageName; + public final int versionCode; + + /** Names of any split APKs, ordered by parsed splitName */ + public final String[] splitNames; + + /** + * Path where this package was found on disk. For monolithic packages + * this is path to single base APK file; for cluster packages this is + * path to the cluster directory. + */ + public final String codePath; + + /** Path of base APK */ + public final String baseCodePath; + /** Paths of any split APKs, ordered by parsed splitName */ + public final String[] splitCodePaths; + + private PackageLite(String packageName, int versionCode, String[] splitNames, + String codePath, String baseCodePath, String[] splitCodePaths) { + this.packageName = packageName; + this.versionCode = versionCode; + this.splitNames = splitNames; + this.codePath = codePath; + this.baseCodePath = baseCodePath; + this.splitCodePaths = splitCodePaths; + } + + public List<String> getAllCodePaths() { + ArrayList<String> paths = new ArrayList<>(); + paths.add(baseCodePath); + if (!ArrayUtils.isEmpty(splitCodePaths)) { + Collections.addAll(paths, splitCodePaths); + } + return paths; + } + } + + /** * Lightweight parsed details about a single APK file. */ public static class ApkLite { @@ -279,12 +321,8 @@ public class PackageParser { mMetrics = metrics; } - public static final boolean isPackageFilename(File file) { - return isPackageFilename(file.getName()); - } - - public static final boolean isPackageFilename(String name) { - return name.endsWith(".apk"); + public static final boolean isApkFile(File file) { + return file.isFile() && file.getName().endsWith(".apk"); } /* @@ -543,17 +581,26 @@ public class PackageParser { } } - /** - * Parse all APKs contained in the given directory, treating them as a - * single package. This also performs sanity checking, such as requiring - * identical package name and version codes, a single base APK, and unique - * split names. - * <p> - * Note that this <em>does not</em> perform signature verification; that - * must be done separately in {@link #collectCertificates(Package, int)}. - */ - public Package parseClusterPackage(File apkDir, int flags) throws PackageParserException { - final File[] files = apkDir.listFiles(); + public static PackageLite parsePackageLite(File packageFile, int flags) + throws PackageParserException { + if (packageFile.isDirectory()) { + return parseClusterPackageLite(packageFile, flags); + } else { + return parseMonolithicPackageLite(packageFile, flags); + } + } + + private static PackageLite parseMonolithicPackageLite(File packageFile, int flags) + throws PackageParserException { + final ApkLite lite = parseApkLite(packageFile, flags); + final String packagePath = packageFile.getAbsolutePath(); + return new PackageLite(lite.packageName, lite.versionCode, null, + packagePath, packagePath, null); + } + + private static PackageLite parseClusterPackageLite(File packageDir, int flags) + throws PackageParserException { + final File[] files = packageDir.listFiles(); if (ArrayUtils.isEmpty(files)) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); @@ -564,8 +611,8 @@ public class PackageParser { final ArrayMap<String, File> apks = new ArrayMap<>(); for (File file : files) { - if (file.isFile() && isPackageFilename(file)) { - final ApkLite lite = parseApkLite(file, 0); + if (isApkFile(file)) { + final ApkLite lite = parseApkLite(file, flags); // Assert that all package names and version codes are // consistent with the first one we encounter. @@ -594,29 +641,73 @@ public class PackageParser { } } - final File baseFile = apks.remove(null); - if (baseFile == null) { + final File baseApk = apks.remove(null); + if (baseApk == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, - "Missing base APK in " + apkDir); + "Missing base APK in " + packageDir); + } + + // Always apply deterministic ordering based on splitName + final int size = apks.size(); + + String[] splitNames = null; + String[] splitCodePaths = null; + if (size > 0) { + splitNames = new String[size]; + splitCodePaths = new String[size]; + + splitNames = apks.keySet().toArray(splitNames); + Arrays.sort(splitNames, sSplitNameComparator); + + for (int i = 0; i < size; i++) { + splitCodePaths[i] = apks.get(splitNames[i]).getAbsolutePath(); + } } - final Package pkg = parseBaseApk(baseFile, flags); + final String codePath = packageDir.getAbsolutePath(); + final String baseCodePath = baseApk.getAbsolutePath(); + return new PackageLite(packageName, versionCode, splitNames, codePath, baseCodePath, + splitCodePaths); + } + + public Package parsePackage(File packageFile, int flags) throws PackageParserException { + if (packageFile.isDirectory()) { + return parseClusterPackage(packageFile, flags); + } else { + return parseMonolithicPackage(packageFile, flags); + } + } + + /** + * Parse all APKs contained in the given directory, treating them as a + * single package. This also performs sanity checking, such as requiring + * identical package name and version codes, a single base APK, and unique + * split names. + * <p> + * Note that this <em>does not</em> perform signature verification; that + * must be done separately in {@link #collectCertificates(Package, int)}. + */ + private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { + final PackageLite lite = parseClusterPackageLite(packageDir, 0); + + final File baseApk = new File(lite.baseCodePath); + final Package pkg = parseBaseApk(baseApk, flags); if (pkg == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, - "Failed to parse base APK: " + baseFile); + "Failed to parse base APK: " + baseApk); } - // Always apply deterministic ordering based on splitName - final int size = apks.size(); - final String[] splitNames = apks.keySet().toArray(new String[size]); - Arrays.sort(splitNames, sSplitNameComparator); + if (!ArrayUtils.isEmpty(lite.splitNames)) { + pkg.splitNames = lite.splitNames; + pkg.splitCodePaths = lite.splitCodePaths; - for (String splitName : splitNames) { - final File splitFile = apks.get(splitName); - parseSplitApk(pkg, splitFile, splitName, flags); + for (String splitCodePath : lite.splitCodePaths) { + final File splitApk = new File(splitCodePath); + parseSplitApk(pkg, splitApk, flags); + } } - pkg.codePath = apkDir.getAbsolutePath(); + pkg.codePath = packageDir.getAbsolutePath(); return pkg; } @@ -648,8 +739,7 @@ public class PackageParser { mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; return null; } - if (!isPackageFilename(apkFile.getName()) - && (flags&PARSE_MUST_BE_APK) != 0) { + if (!isApkFile(apkFile) && (flags & PARSE_MUST_BE_APK) != 0) { if ((flags&PARSE_IS_SYSTEM) == 0) { // We expect to have non-.apk files in the system dir, // so don't warn about them. @@ -732,16 +822,11 @@ public class PackageParser { return pkg; } - private void parseSplitApk(Package pkg, File apkFile, String splitName, int flags) - throws PackageParserException { + private void parseSplitApk(Package pkg, File apkFile, int flags) throws PackageParserException { final String splitCodePath = apkFile.getAbsolutePath(); mArchiveSourcePath = apkFile.getAbsolutePath(); // TODO: expand split APK parsing - // TODO: extract splitName during parse - pkg.splitNames = ArrayUtils.appendElement(String.class, pkg.splitNames, splitName); - pkg.splitCodePaths = ArrayUtils.appendElement(String.class, pkg.splitCodePaths, - splitCodePath); } /** diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index d5d5eb8..4c34d46 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -392,7 +392,10 @@ public class FileUtils { if (file.isDirectory()) { success &= deleteContents(file); } - success &= file.delete(); + if (!file.delete()) { + Log.w(TAG, "Failed to delete " + file); + success = false; + } } } return success; diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java index 832829d..af0068e 100644 --- a/core/java/com/android/internal/content/NativeLibraryHelper.java +++ b/core/java/com/android/internal/content/NativeLibraryHelper.java @@ -16,12 +16,22 @@ package com.android.internal.content; +import static android.content.pm.PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS; +import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; +import static android.content.pm.PackageManager.NO_NATIVE_LIBRARIES; + import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.content.pm.PackageParser.PackageLite; +import android.content.pm.PackageParser.PackageParserException; import android.util.Slog; +import dalvik.system.CloseGuard; + import java.io.Closeable; import java.io.File; import java.io.IOException; +import java.util.List; /** * Native libraries helper. @@ -34,40 +44,72 @@ public class NativeLibraryHelper { private static final boolean DEBUG_NATIVE = false; /** - * A handle to an opened APK. Used as input to the various NativeLibraryHelper - * methods. Allows us to scan and parse the APK exactly once instead of doing - * it multiple times. + * A handle to an opened package, consisting of one or more APKs. Used as + * input to the various NativeLibraryHelper methods. Allows us to scan and + * parse the APKs exactly once instead of doing it multiple times. * * @hide */ - public static class ApkHandle implements Closeable { - final String apkPath; - final long apkHandle; - - public static ApkHandle create(String path) throws IOException { - final long handle = nativeOpenApk(path); - if (handle == 0) { - throw new IOException("Unable to open APK: " + path); + public static class Handle implements Closeable { + private final CloseGuard mGuard = CloseGuard.get(); + private volatile boolean mClosed; + + final long[] apkHandles; + + public static Handle create(File packageFile) throws IOException { + final PackageLite lite; + try { + lite = PackageParser.parsePackageLite(packageFile, 0); + } catch (PackageParserException e) { + throw new IOException("Failed to parse package: " + packageFile, e); } - return new ApkHandle(path, handle); - } + final List<String> codePaths = lite.getAllCodePaths(); + final int size = codePaths.size(); + final long[] apkHandles = new long[size]; + for (int i = 0; i < size; i++) { + final String path = codePaths.get(i); + apkHandles[i] = nativeOpenApk(path); + if (apkHandles[i] == 0) { + // Unwind everything we've opened so far + for (int j = 0; j < i; j++) { + nativeClose(apkHandles[j]); + } + throw new IOException("Unable to open APK: " + path); + } + } - public static ApkHandle create(File path) throws IOException { - return create(path.getAbsolutePath()); + return new Handle(apkHandles); } - private ApkHandle(String apkPath, long apkHandle) { - this.apkPath = apkPath; - this.apkHandle = apkHandle; + Handle(long[] apkHandles) { + this.apkHandles = apkHandles; + mGuard.open("close"); } @Override public void close() { - nativeClose(apkHandle); + for (long apkHandle : apkHandles) { + nativeClose(apkHandle); + } + mGuard.close(); + mClosed = true; } - } + @Override + protected void finalize() throws Throwable { + if (mGuard != null) { + mGuard.warnIfOpen(); + } + try { + if (!mClosed) { + close(); + } + } finally { + super.finalize(); + } + } + } private static native long nativeOpenApk(String path); private static native void nativeClose(long handle); @@ -79,8 +121,12 @@ public class NativeLibraryHelper { * * @return size of all native binary files in bytes */ - public static long sumNativeBinariesLI(ApkHandle handle, String abi) { - return nativeSumNativeBinaries(handle.apkHandle, abi); + public static long sumNativeBinariesLI(Handle handle, String abi) { + long sum = 0; + for (long apkHandle : handle.apkHandles) { + sum += nativeSumNativeBinaries(apkHandle, abi); + } + return sum; } private native static int nativeCopyNativeBinaries(long handle, @@ -94,9 +140,15 @@ public class NativeLibraryHelper { * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another * error code from that class if not */ - public static int copyNativeBinariesIfNeededLI(ApkHandle handle, File sharedLibraryDir, + public static int copyNativeBinariesIfNeededLI(Handle handle, File sharedLibraryDir, String abi) { - return nativeCopyNativeBinaries(handle.apkHandle, sharedLibraryDir.getPath(), abi); + for (long apkHandle : handle.apkHandles) { + int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi); + if (res != INSTALL_SUCCEEDED) { + return res; + } + } + return INSTALL_SUCCEEDED; } /** @@ -106,8 +158,29 @@ public class NativeLibraryHelper { * APK doesn't contain any native code, and * {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match. */ - public static int findSupportedAbi(ApkHandle handle, String[] supportedAbis) { - return nativeFindSupportedAbi(handle.apkHandle, supportedAbis); + public static int findSupportedAbi(Handle handle, String[] supportedAbis) { + int finalRes = NO_NATIVE_LIBRARIES; + for (long apkHandle : handle.apkHandles) { + final int res = nativeFindSupportedAbi(apkHandle, supportedAbis); + if (res == NO_NATIVE_LIBRARIES) { + // No native code, keep looking through all APKs. + } else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) { + // Found some native code, but no ABI match; update our final + // result if we haven't found other valid code. + if (finalRes < 0) { + finalRes = INSTALL_FAILED_NO_MATCHING_ABIS; + } + } else if (res >= 0) { + // Found valid native code, track the best ABI match + if (finalRes < 0 || res < finalRes) { + finalRes = res; + } + } else { + // Unexpected error; bail + return res; + } + } + return finalRes; } private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis); @@ -156,13 +229,16 @@ public class NativeLibraryHelper { // We don't care about the other return values for now. private static final int BITCODE_PRESENT = 1; - public static boolean hasRenderscriptBitcode(ApkHandle handle) throws IOException { - final int returnVal = hasRenderscriptBitcode(handle.apkHandle); - if (returnVal < 0) { - throw new IOException("Error scanning APK, code: " + returnVal); + public static boolean hasRenderscriptBitcode(Handle handle) throws IOException { + for (long apkHandle : handle.apkHandles) { + final int res = hasRenderscriptBitcode(apkHandle); + if (res < 0) { + throw new IOException("Error scanning APK, code: " + res); + } else if (res == BITCODE_PRESENT) { + return true; + } } - - return (returnVal == BITCODE_PRESENT); + return false; } private static native int hasRenderscriptBitcode(long apkHandle); diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 74ff3b1..4a61f1f 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -48,7 +48,7 @@ import android.util.Slog; import com.android.internal.app.IMediaContainerService; import com.android.internal.content.NativeLibraryHelper; -import com.android.internal.content.NativeLibraryHelper.ApkHandle; +import com.android.internal.content.NativeLibraryHelper.Handle; import com.android.internal.content.PackageHelper; import libcore.io.IoUtils; @@ -116,9 +116,9 @@ public class DefaultContainerService extends IntentService { } } - ApkHandle handle = null; + Handle handle = null; try { - handle = ApkHandle.create(packagePath); + handle = Handle.create(new File(packagePath)); return copyResourceInner(packagePath, cid, key, resFileName, publicResFileName, isExternal, isForwardLocked, handle, abiOverride); } catch (IOException ioe) { @@ -349,7 +349,7 @@ public class DefaultContainerService extends IntentService { private String copyResourceInner(String packagePath, String newCid, String key, String resFileName, String publicResFileName, boolean isExternal, boolean isForwardLocked, - ApkHandle handle, String abiOverride) { + Handle handle, String abiOverride) { // The .apk file String codePath = packagePath; File codeFile = new File(codePath); @@ -834,9 +834,9 @@ public class DefaultContainerService extends IntentService { private int calculateContainerSize(File apkFile, boolean forwardLocked, String abiOverride) throws IOException { - ApkHandle handle = null; + Handle handle = null; try { - handle = ApkHandle.create(apkFile); + handle = Handle.create(apkFile); final int abi = NativeLibraryHelper.findSupportedAbi(handle, (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS); return calculateContainerSize(handle, apkFile, abi, forwardLocked); @@ -852,7 +852,7 @@ public class DefaultContainerService extends IntentService { * @return size in megabytes (2^20 bytes) * @throws IOException when there is a problem reading the file */ - private int calculateContainerSize(NativeLibraryHelper.ApkHandle apkHandle, + private int calculateContainerSize(NativeLibraryHelper.Handle handle, File apkFile, int abiIndex, boolean forwardLocked) throws IOException { // Calculate size of container needed to hold base APK. long sizeBytes = apkFile.length(); @@ -863,7 +863,7 @@ 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(apkHandle, + sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle, Build.SUPPORTED_ABIS[abiIndex]); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 11e546f..c011cf9 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -20,7 +20,6 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS; import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED; -import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageInstallObserver2; @@ -31,7 +30,6 @@ import android.content.pm.PackageParser; import android.content.pm.PackageParser.ApkLite; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.Signature; -import android.os.Build; import android.os.Bundle; import android.os.FileBridge; import android.os.FileUtils; @@ -40,7 +38,6 @@ import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -import android.os.SELinux; import android.os.UserHandle; import android.system.ErrnoException; import android.system.OsConstants; @@ -48,11 +45,9 @@ import android.system.StructStat; import android.util.ArraySet; import android.util.Slog; -import com.android.internal.content.NativeLibraryHelper; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; -import libcore.io.IoUtils; import libcore.io.Libcore; import java.io.File; @@ -110,7 +105,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private Signature[] mSignatures; private boolean mMutationsAllowed; - private boolean mVerifierConfirmed; private boolean mPermissionsConfirmed; private boolean mInvalid; @@ -238,21 +232,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { Preconditions.checkNotNull(mPackageName); Preconditions.checkNotNull(mSignatures); - if (!mVerifierConfirmed) { - // TODO: async communication with verifier - // when they confirm, we'll kick off another install() pass - mVerifierConfirmed = true; - } - if (!mPermissionsConfirmed) { // TODO: async confirm permissions with user // when they confirm, we'll kick off another install() pass mPermissionsConfirmed = true; } - // Unpack any native libraries contained in this session - unpackNativeLibraries(); - // Inherit any packages and native libraries from existing install that // haven't been overridden. if (!params.fullInstall) { @@ -425,58 +410,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - private void unpackNativeLibraries() throws InstallFailedException { - final File libDir = new File(sessionDir, "lib"); - - if (!libDir.mkdir()) { - throw new InstallFailedException(INSTALL_FAILED_INTERNAL_ERROR, - "Failed to create " + libDir); - } - - try { - Libcore.os.chmod(libDir.getAbsolutePath(), 0755); - } catch (ErrnoException e) { - throw new InstallFailedException(INSTALL_FAILED_INTERNAL_ERROR, - "Failed to prepare " + libDir + ": " + e); - } - - if (!SELinux.restorecon(libDir)) { - throw new InstallFailedException(INSTALL_FAILED_INTERNAL_ERROR, - "Failed to set context on " + libDir); - } - - // Unpack all native libraries under stage - final File[] files = sessionDir.listFiles(); - if (ArrayUtils.isEmpty(files)) { - throw new InstallFailedException(INSTALL_FAILED_INVALID_APK, "No packages staged"); - } - - for (File file : files) { - NativeLibraryHelper.ApkHandle handle = null; - try { - handle = NativeLibraryHelper.ApkHandle.create(file); - final int abiIndex = NativeLibraryHelper.findSupportedAbi(handle, - Build.SUPPORTED_ABIS); - if (abiIndex >= 0) { - int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libDir, - Build.SUPPORTED_ABIS[abiIndex]); - if (copyRet != INSTALL_SUCCEEDED) { - throw new InstallFailedException(copyRet, - "Failed to copy native libraries for " + file); - } - } else if (abiIndex != PackageManager.NO_NATIVE_LIBRARIES) { - throw new InstallFailedException(abiIndex, - "Failed to copy native libraries for " + file); - } - } catch (IOException ioe) { - throw new InstallFailedException(INSTALL_FAILED_INTERNAL_ERROR, - "Failed to create handle for " + file); - } finally { - IoUtils.closeQuietly(handle); - } - } - } - @Override public void destroy() { try { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 91f119d..27b4843 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -24,7 +24,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; -import static android.content.pm.PackageParser.isPackageFilename; +import static android.content.pm.PackageParser.isApkFile; import static android.os.Process.PACKAGE_INFO_GID; import static android.os.Process.SYSTEM_UID; import static android.system.OsConstants.S_IRGRP; @@ -42,7 +42,6 @@ import com.android.internal.R; import com.android.internal.app.IMediaContainerService; import com.android.internal.app.ResolverActivity; import com.android.internal.content.NativeLibraryHelper; -import com.android.internal.content.NativeLibraryHelper.ApkHandle; import com.android.internal.content.PackageHelper; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; @@ -4096,7 +4095,7 @@ public class PackageManagerService extends IPackageManager.Stub { } for (File file : files) { - if (!isPackageFilename(file)) { + if (!isApkFile(file)) { // Ignore entries which are not apk's continue; } @@ -5358,10 +5357,9 @@ public class PackageManagerService extends IPackageManager.Stub { * only for non-system apps and system app upgrades. */ if (pkg.applicationInfo.nativeLibraryDir != null) { - // TODO: extend to extract native code from split APKs - ApkHandle handle = null; + NativeLibraryHelper.Handle handle = null; try { - handle = ApkHandle.create(scanFile.getPath()); + handle = NativeLibraryHelper.Handle.create(scanFile); // Enable gross and lame hacks for apps that are built with old // SDK tools. We must scan their APKs for renderscript bitcode and // not launch them if it's present. Don't bother checking on devices @@ -6178,7 +6176,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private static int copyNativeLibrariesForInternalApp(ApkHandle handle, + private static int copyNativeLibrariesForInternalApp(NativeLibraryHelper.Handle handle, final File nativeLibraryDir, String[] abiList) throws IOException { if (!nativeLibraryDir.isDirectory()) { nativeLibraryDir.delete(); @@ -7486,7 +7484,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (DEBUG_APP_DIR_OBSERVER) Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event)); - if (!isPackageFilename(path)) { + if (!isApkFile(fullPath)) { if (DEBUG_APP_DIR_OBSERVER) Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr); return; @@ -9211,9 +9209,9 @@ public class PackageManagerService extends IPackageManager.Stub { String[] abiList = (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS; - ApkHandle handle = null; + NativeLibraryHelper.Handle handle = null; try { - handle = ApkHandle.create(codeFile); + handle = NativeLibraryHelper.Handle.create(codeFile); if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && abiOverride == null && NativeLibraryHelper.hasRenderscriptBitcode(handle)) { @@ -12955,9 +12953,10 @@ public class PackageManagerService extends IPackageManager.Stub { final File newNativeDir = new File(newNativePath); if (!isForwardLocked(pkg) && !isExternal(pkg)) { - ApkHandle handle = null; + NativeLibraryHelper.Handle handle = null; try { - handle = ApkHandle.create(newCodePath); + handle = NativeLibraryHelper.Handle.create( + new File(newCodePath)); final int abi = NativeLibraryHelper.findSupportedAbi( handle, Build.SUPPORTED_ABIS); if (abi >= 0) { |