diff options
| author | 2014-04-10 09:26:44 +0000 | |
|---|---|---|
| committer | 2014-04-10 09:26:44 +0000 | |
| commit | 286a247e4c8fcecb59636f668678d24e33142744 (patch) | |
| tree | 4c2ce4981a5e2e2bcc4badd1b537781c6ecc7f37 | |
| parent | 544991946287bdd3a9e6a71855642e378594bf73 (diff) | |
| parent | 0fd40cb100bccbd5d9ad6109ca39c818a857f889 (diff) | |
am 0fd40cb1: am 80413c9f: Merge "Re-implement native library search and copies."
* commit '0fd40cb100bccbd5d9ad6109ca39c818a857f889':
  Re-implement native library search and copies.
6 files changed, 352 insertions, 112 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 34a6f1d0d726..e002c8798521 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -675,6 +675,25 @@ public abstract class PackageManager {      public static final int INSTALL_FAILED_USER_RESTRICTED = -111;      /** +     * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by +     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} +     * if the system failed to install the package because its packaged native code did not +     * match any of the ABIs supported by the system. +     * +     * @hide +     */ +    public static final int INSTALL_FAILED_NO_MATCHING_ABIS = -112; + +    /** +     * Internal return code for NativeLibraryHelper methods to indicate that the package +     * being processed did not contain any native code. This is placed here only so that +     * it can belong to the same value space as the other install failure codes. +     * +     * @hide +     */ +    public static final int NO_NATIVE_LIBRARIES = -113; + +    /**       * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the       * package's data directory.       * diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 22e1476183a4..b2e0b29c644e 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -74,7 +74,14 @@ public class Build {      /** A hardware serial number, if available.  Alphanumeric only, case-insensitive. */       public static final String SERIAL = getString("ro.serialno"); -   + +    /** +     * A list of ABIs (in priority) order supported by this device. +     * +     * @hide +     */ +    public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").split(","); +      /** Various version strings. */      public static class VERSION {          /** diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java index 6d657829c8fa..ba419f9bf1ab 100644 --- a/core/java/com/android/internal/content/NativeLibraryHelper.java +++ b/core/java/com/android/internal/content/NativeLibraryHelper.java @@ -16,7 +16,7 @@  package com.android.internal.content; -import android.os.Build; +import android.content.pm.PackageManager;  import android.util.Slog;  import java.io.File; @@ -31,38 +31,76 @@ public class NativeLibraryHelper {      private static final boolean DEBUG_NATIVE = false; -    private static native long nativeSumNativeBinaries(String file, String cpuAbi, String cpuAbi2); +    /** +     * 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. +     * +     * @hide +     */ +    public static class ApkHandle { +        final String apkPath; +        final long apkHandle; + +        public ApkHandle(String path) { +            apkPath = path; +            apkHandle = nativeOpenApk(apkPath); +        } + +        public ApkHandle(File apkFile) { +            apkPath = apkFile.getPath(); +            apkHandle = nativeOpenApk(apkPath); +        } + +        public void close() { +            nativeClose(apkHandle); +        } +    } + + +    private static native long nativeOpenApk(String path); +    private static native void nativeClose(long handle); + +    private static native long nativeSumNativeBinaries(long handle, String cpuAbi);      /** -     * Sums the size of native binaries in an APK. +     * Sums the size of native binaries in an APK for a given ABI.       * -     * @param apkFile APK file to scan for native libraries       * @return size of all native binary files in bytes       */ -    public static long sumNativeBinariesLI(File apkFile) { -        final String cpuAbi = Build.CPU_ABI; -        final String cpuAbi2 = Build.CPU_ABI2; -        return nativeSumNativeBinaries(apkFile.getPath(), cpuAbi, cpuAbi2); +    public static long sumNativeBinariesLI(ApkHandle handle, String abi) { +        return nativeSumNativeBinaries(handle.apkHandle, abi);      } -    private native static int nativeCopyNativeBinaries(String filePath, String sharedLibraryPath, -            String cpuAbi, String cpuAbi2); +    private native static int nativeCopyNativeBinaries(long handle, +            String sharedLibraryPath, String abiToCopy);      /**       * Copies native binaries to a shared library directory.       * -     * @param apkFile APK file to scan for native libraries +     * @param handle APK file to scan for native libraries       * @param sharedLibraryDir directory for libraries to be copied to       * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another       *         error code from that class if not       */ -    public static int copyNativeBinariesIfNeededLI(File apkFile, File sharedLibraryDir) { -        final String cpuAbi = Build.CPU_ABI; -        final String cpuAbi2 = Build.CPU_ABI2; -        return nativeCopyNativeBinaries(apkFile.getPath(), sharedLibraryDir.getPath(), cpuAbi, -                cpuAbi2); +    public static int copyNativeBinariesIfNeededLI(ApkHandle handle, File sharedLibraryDir, +            String abi) { +        return nativeCopyNativeBinaries(handle.apkHandle, sharedLibraryDir.getPath(), abi);      } +    /** +     * Checks if a given APK contains native code for any of the provided +     * {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching +     * ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the +     * 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); +    } + +    private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis); +      // Convenience method to call removeNativeBinariesFromDirLI(File)      public static boolean removeNativeBinariesLI(String nativeLibraryPath) {          return removeNativeBinariesFromDirLI(new File(nativeLibraryPath)); diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp index a86091851aba..200457696d72 100644 --- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp +++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp @@ -19,11 +19,12 @@  #include <android_runtime/AndroidRuntime.h> -#include <utils/Log.h> -#include <androidfw/ZipFileRO.h> -#include <androidfw/ZipUtils.h>  #include <ScopedUtfChars.h>  #include <UniquePtr.h> +#include <androidfw/ZipFileRO.h> +#include <androidfw/ZipUtils.h> +#include <utils/Log.h> +#include <utils/Vector.h>  #include <zlib.h> @@ -54,17 +55,19 @@  namespace android {  // These match PackageManager.java install codes -typedef enum { +enum install_status_t {      INSTALL_SUCCEEDED = 1,      INSTALL_FAILED_INVALID_APK = -2,      INSTALL_FAILED_INSUFFICIENT_STORAGE = -4,      INSTALL_FAILED_CONTAINER_ERROR = -18,      INSTALL_FAILED_INTERNAL_ERROR = -110, -} install_status_t; +    INSTALL_FAILED_NO_MATCHING_ABIS = -112, +    NO_NATIVE_LIBRARIES = -113 +};  typedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*); -// Equivalent to isFilenameSafe +// Equivalent to android.os.FileUtils.isFilenameSafe  static bool  isFilenameSafe(const char* filename)  { @@ -268,126 +271,252 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr      return INSTALL_SUCCEEDED;  } -static install_status_t -iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2, -        iterFunc callFunc, void* callArg) { -    ScopedUtfChars filePath(env, javaFilePath); -    ScopedUtfChars cpuAbi(env, javaCpuAbi); -    ScopedUtfChars cpuAbi2(env, javaCpuAbi2); - -    UniquePtr<ZipFileRO> zipFile(ZipFileRO::open(filePath.c_str())); -    if (zipFile.get() == NULL) { -        ALOGI("Couldn't open APK %s\n", filePath.c_str()); -        return INSTALL_FAILED_INVALID_APK; +/* + * An iterator over all shared libraries in a zip file. An entry is + * considered to be a shared library if all of the conditions below are + * satisfied : + * + * - The entry is under the lib/ directory. + * - The entry name ends with ".so" and the entry name starts with "lib", + *   an exception is made for entries whose name is "gdbserver". + * - The entry filename is "safe" (as determined by isFilenameSafe). + * + */ +class NativeLibrariesIterator { +private: +    NativeLibrariesIterator(ZipFileRO* zipFile, void* cookie) +        : mZipFile(zipFile), mCookie(cookie), mLastSlash(NULL) { +        fileName[0] = '\0';      } -    char fileName[PATH_MAX]; -    bool hasPrimaryAbi = false; +public: +    static NativeLibrariesIterator* create(ZipFileRO* zipFile) { +        void* cookie = NULL; +        if (!zipFile->startIteration(&cookie)) { +            return NULL; +        } -    void* cookie = NULL; -    if (!zipFile->startIteration(&cookie)) { -        ALOGI("Couldn't iterate over APK%s\n", filePath.c_str()); -        return INSTALL_FAILED_INVALID_APK; +        return new NativeLibrariesIterator(zipFile, cookie);      } -    ZipEntryRO entry = NULL; -    while ((entry = zipFile->nextEntry(cookie)) != NULL) { -        // Make sure this entry has a filename. -        if (zipFile->getEntryFileName(entry, fileName, sizeof(fileName))) { -            continue; -        } +    ZipEntryRO next() { +        ZipEntryRO next = NULL; +        while ((next = mZipFile->nextEntry(mCookie)) != NULL) { +            // Make sure this entry has a filename. +            if (mZipFile->getEntryFileName(next, fileName, sizeof(fileName))) { +                continue; +            } -        // Make sure we're in the lib directory of the ZIP. -        if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) { -            continue; -        } +            // Make sure we're in the lib directory of the ZIP. +            if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) { +                continue; +            } -        // Make sure the filename is at least to the minimum library name size. -        const size_t fileNameLen = strlen(fileName); -        static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN; -        if (fileNameLen < minLength) { -            continue; -        } +            // Make sure the filename is at least to the minimum library name size. +            const size_t fileNameLen = strlen(fileName); +            static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN; +            if (fileNameLen < minLength) { +                continue; +            } -        const char* lastSlash = strrchr(fileName, '/'); -        ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName); +            const char* lastSlash = strrchr(fileName, '/'); +            ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName); -        // Check to make sure the CPU ABI of this file is one we support. -        const char* cpuAbiOffset = fileName + APK_LIB_LEN; -        const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset; +            // Exception: If we find the gdbserver binary, return it. +            if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) { +                break; +            } -        ALOGV("Comparing ABIs %s and %s versus %s\n", cpuAbi.c_str(), cpuAbi2.c_str(), cpuAbiOffset); -        if (cpuAbi.size() == cpuAbiRegionSize -                && *(cpuAbiOffset + cpuAbi.size()) == '/' -                && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) { -            ALOGV("Using primary ABI %s\n", cpuAbi.c_str()); -            hasPrimaryAbi = true; -        } else if (cpuAbi2.size() == cpuAbiRegionSize -                && *(cpuAbiOffset + cpuAbi2.size()) == '/' -                && !strncmp(cpuAbiOffset, cpuAbi2.c_str(), cpuAbiRegionSize)) { - -            /* -             * If this library matches both the primary and secondary ABIs, -             * only use the primary ABI. -             */ -            if (hasPrimaryAbi) { -                ALOGV("Already saw primary ABI, skipping secondary ABI %s\n", cpuAbi2.c_str()); +            // Make sure the filename starts with lib and ends with ".so". +            if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN) +                || strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)) {                  continue; -            } else { -                ALOGV("Using secondary ABI %s\n", cpuAbi2.c_str());              } -        } else { -            ALOGV("abi didn't match anything: %s (end at %zd)\n", cpuAbiOffset, cpuAbiRegionSize); -            continue; + +            // Make sure the filename is safe. +            if (!isFilenameSafe(lastSlash + 1)) { +                continue; +            } + +            mLastSlash = lastSlash; +            break;          } -        // If this is a .so file, check to see if we need to copy it. -        if ((!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN) -                    && !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN) -                    && isFilenameSafe(lastSlash + 1)) -                || !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) { +        return next; +    } + +    inline const char* currentEntry() const { +        return fileName; +    } + +    inline const char* lastSlash() const { +        return mLastSlash; +    } + +    virtual ~NativeLibrariesIterator() { +        mZipFile->endIteration(mCookie); +    } +private: + +    char fileName[PATH_MAX]; +    ZipFileRO* const mZipFile; +    void* mCookie; +    const char* mLastSlash; +}; -            install_status_t ret = callFunc(env, callArg, zipFile.get(), entry, lastSlash + 1); +static install_status_t +iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi, +                       iterFunc callFunc, void* callArg) { +    ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); +    if (zipFile == NULL) { +        return INSTALL_FAILED_INVALID_APK; +    } + +    UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile)); +    if (it.get() == NULL) { +        return INSTALL_FAILED_INVALID_APK; +    } + +    const ScopedUtfChars cpuAbi(env, javaCpuAbi); +    if (cpuAbi.c_str() == NULL) { +        // This would've thrown, so this return code isn't observable by +        // Java. +        return INSTALL_FAILED_INVALID_APK; +    } +    ZipEntryRO entry = NULL; +    while ((entry = it->next()) != NULL) { +        const char* fileName = it->currentEntry(); +        const char* lastSlash = it->lastSlash(); + +        // Check to make sure the CPU ABI of this file is one we support. +        const char* cpuAbiOffset = fileName + APK_LIB_LEN; +        const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset; + +        if (cpuAbi.size() == cpuAbiRegionSize && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) { +            install_status_t ret = callFunc(env, callArg, zipFile, entry, lastSlash + 1);              if (ret != INSTALL_SUCCEEDED) {                  ALOGV("Failure for entry %s", lastSlash + 1); -                zipFile->endIteration(cookie);                  return ret;              }          }      } -    zipFile->endIteration(cookie); -      return INSTALL_SUCCEEDED;  } + +static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray) { +    const int numAbis = env->GetArrayLength(supportedAbisArray); +    Vector<ScopedUtfChars*> supportedAbis; + +    for (int i = 0; i < numAbis; ++i) { +        supportedAbis.add(new ScopedUtfChars(env, +            (jstring) env->GetObjectArrayElement(supportedAbisArray, i))); +    } + +    ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); +    if (zipFile == NULL) { +        return INSTALL_FAILED_INVALID_APK; +    } + +    UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile)); +    if (it.get() == NULL) { +        return INSTALL_FAILED_INVALID_APK; +    } + +    ZipEntryRO entry = NULL; +    char fileName[PATH_MAX]; +    int status = NO_NATIVE_LIBRARIES; +    while ((entry = it->next()) != NULL) { +        // We're currently in the lib/ directory of the APK, so it does have some native +        // code. We should return INSTALL_FAILED_NO_MATCHING_ABIS if none of the +        // libraries match. +        if (status == NO_NATIVE_LIBRARIES) { +            status = INSTALL_FAILED_NO_MATCHING_ABIS; +        } + +        const char* fileName = it->currentEntry(); +        const char* lastSlash = it->lastSlash(); + +        // Check to see if this CPU ABI matches what we are looking for. +        const char* abiOffset = fileName + APK_LIB_LEN; +        const size_t abiSize = lastSlash - abiOffset; +        for (int i = 0; i < numAbis; i++) { +            const ScopedUtfChars* abi = supportedAbis[i]; +            if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) { +                // The entry that comes in first (i.e. with a lower index) has the higher priority. +                if (((i < status) && (status >= 0)) || (status < 0) ) { +                    status = i; +                } +            } +        } +    } + +    for (int i = 0; i < numAbis; ++i) { +        delete supportedAbis[i]; +    } + +    return status; +} +  static jint  com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz, -        jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2) +        jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi)  { -    return (jint) iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, +    return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi,              copyFileIfChanged, &javaNativeLibPath);  }  static jlong  com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz, -        jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2) +        jlong apkHandle, jstring javaCpuAbi)  {      size_t totalSize = 0; -    iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, sumFiles, &totalSize); +    iterateOverNativeFiles(env, apkHandle, javaCpuAbi, sumFiles, &totalSize);      return totalSize;  } +static jint +com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz, +        jlong apkHandle, jobjectArray javaCpuAbisToSearch) +{ +    return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch); +} + +static jlong +com_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath) +{ +    ScopedUtfChars filePath(env, apkPath); +    ZipFileRO* zipFile = ZipFileRO::open(filePath.c_str()); + +    return reinterpret_cast<jlong>(zipFile); +} + +static void +com_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlong apkHandle) +{ +    delete reinterpret_cast<ZipFileRO*>(apkHandle); +} +  static JNINativeMethod gMethods[] = { +    {"nativeOpenApk", +            "(Ljava/lang/String;)J", +            (void *)com_android_internal_content_NativeLibraryHelper_openApk}, +    {"nativeClose", +            "(J)V", +            (void *)com_android_internal_content_NativeLibraryHelper_close},      {"nativeCopyNativeBinaries", -            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", +            "(JLjava/lang/String;Ljava/lang/String;)I",              (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},      {"nativeSumNativeBinaries", -            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J", +            "(JLjava/lang/String;)J",              (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries}, +    {"nativeFindSupportedAbi", +            "(J[Ljava/lang/String;)I", +            (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},  }; diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 6e34bbb08a39..48ef9dbe61e5 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -30,6 +30,7 @@ import android.content.pm.PackageParser;  import android.content.res.ObbInfo;  import android.content.res.ObbScanner;  import android.net.Uri; +import android.os.Build;  import android.os.Environment;  import android.os.Environment.UserEnvironment;  import android.os.FileUtils; @@ -39,10 +40,8 @@ import android.os.Process;  import android.os.RemoteException;  import android.os.ServiceManager;  import android.os.StatFs; -import android.os.SystemClock;  import android.provider.Settings;  import android.util.DisplayMetrics; -import android.util.Log;  import android.util.Slog;  import com.android.internal.app.IMediaContainerService; @@ -343,11 +342,13 @@ public class DefaultContainerService extends IntentService {          // The .apk file          String codePath = packageURI.getPath();          File codeFile = new File(codePath); +        NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codePath); +        final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);          // Calculate size of container needed to hold base APK.          final int sizeMb;          try { -            sizeMb = calculateContainerSize(codeFile, isForwardLocked); +            sizeMb = calculateContainerSize(handle, codeFile, abi, isForwardLocked);          } catch (IOException e) {              Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath());              return null; @@ -410,7 +411,14 @@ public class DefaultContainerService extends IntentService {          final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);          if (sharedLibraryDir.mkdir()) { -            int ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(codeFile, sharedLibraryDir); +            int ret = PackageManager.INSTALL_SUCCEEDED; +            if (abi >= 0) { +                ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, +                        sharedLibraryDir, Build.SUPPORTED_ABIS[abi]); +            } else if (abi != PackageManager.NO_NATIVE_LIBRARIES) { +                ret = abi; +            } +              if (ret != PackageManager.INSTALL_SUCCEEDED) {                  Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());                  PackageHelper.destroySdDir(newCid); @@ -824,6 +832,17 @@ public class DefaultContainerService extends IntentService {          return availSdMb > sizeMb;      } +    private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException { +        NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(apkFile); +        final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS); + +        try { +            return calculateContainerSize(handle, apkFile, abi, forwardLocked); +        } finally { +            handle.close(); +        } +    } +      /**       * Calculate the container size for an APK. Takes into account the       *  @@ -831,7 +850,8 @@ 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(File apkFile, boolean forwardLocked) throws IOException { +    private int calculateContainerSize(NativeLibraryHelper.ApkHandle apkHandle, +            File apkFile, int abiIndex, boolean forwardLocked) throws IOException {          // Calculate size of container needed to hold base APK.          long sizeBytes = apkFile.length();          if (sizeBytes == 0 && !apkFile.exists()) { @@ -840,7 +860,10 @@ public class DefaultContainerService extends IntentService {          // Check all the native files that need to be copied and add that to the          // container size. -        sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkFile); +        if (abiIndex >= 0) { +            sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkHandle, +                    Build.SUPPORTED_ABIS[abiIndex]); +        }          if (forwardLocked) {              sizeBytes += PackageHelper.extractPublicFiles(apkFile.getPath(), null); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index fc24b5f909c1..d637556751ff 100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -60,8 +60,8 @@ import android.content.IIntentReceiver;  import android.content.Intent;  import android.content.IntentFilter;  import android.content.IntentSender; -import android.content.ServiceConnection;  import android.content.IntentSender.SendIntentException; +import android.content.ServiceConnection;  import android.content.pm.ActivityInfo;  import android.content.pm.ApplicationInfo;  import android.content.pm.ContainerEncryptionParams; @@ -73,14 +73,15 @@ import android.content.pm.IPackageManager;  import android.content.pm.IPackageMoveObserver;  import android.content.pm.IPackageStatsObserver;  import android.content.pm.InstrumentationInfo; +import android.content.pm.ManifestDigest;  import android.content.pm.PackageCleanItem;  import android.content.pm.PackageInfo;  import android.content.pm.PackageInfoLite;  import android.content.pm.PackageManager;  import android.content.pm.PackageParser; -import android.content.pm.PackageUserState;  import android.content.pm.PackageParser.ActivityIntentInfo;  import android.content.pm.PackageStats; +import android.content.pm.PackageUserState;  import android.content.pm.ParceledListSlice;  import android.content.pm.PermissionGroupInfo;  import android.content.pm.PermissionInfo; @@ -88,7 +89,6 @@ import android.content.pm.ProviderInfo;  import android.content.pm.ResolveInfo;  import android.content.pm.ServiceInfo;  import android.content.pm.Signature; -import android.content.pm.ManifestDigest;  import android.content.pm.VerificationParams;  import android.content.pm.VerifierDeviceIdentity;  import android.content.pm.VerifierInfo; @@ -99,6 +99,7 @@ import android.os.Binder;  import android.os.Build;  import android.os.Bundle;  import android.os.Environment; +import android.os.Environment.UserEnvironment;  import android.os.FileObserver;  import android.os.FileUtils;  import android.os.Handler; @@ -115,7 +116,6 @@ import android.os.ServiceManager;  import android.os.SystemClock;  import android.os.SystemProperties;  import android.os.UserHandle; -import android.os.Environment.UserEnvironment;  import android.os.UserManager;  import android.security.KeyStore;  import android.security.SystemKeyStore; @@ -4732,7 +4732,8 @@ public class PackageManagerService extends IPackageManager.Stub {                          }                          try { -                            if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) { +                            int copyRet = copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir); +                            if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {                                  Slog.e(TAG, "Unable to copy native libraries");                                  mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;                                  return null; @@ -5291,7 +5292,21 @@ public class PackageManagerService extends IPackageManager.Stub {           * If this is an internal application or our nativeLibraryPath points to           * the app-lib directory, unpack the libraries if necessary.           */ -        return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir); +        final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile); +        try { +            int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS); +            if (abi >= 0) { +                int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, +                        nativeLibraryDir, Build.SUPPORTED_ABIS[abi]); +                if (copyRet != PackageManager.INSTALL_SUCCEEDED) { +                    return copyRet; +                } +            } + +            return abi; +        } finally { +            handle.close(); +        }      }      private void killApplication(String pkgName, int appId, String reason) { @@ -8180,7 +8195,7 @@ public class PackageManagerService extends IPackageManager.Stub {              }              try {                  int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile); -                if (copyRet != PackageManager.INSTALL_SUCCEEDED) { +                if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {                      return copyRet;                  }              } catch (IOException e) { @@ -11590,8 +11605,17 @@ public class PackageManagerService extends IPackageManager.Stub {                                      final File newNativeDir = new File(newNativePath);                                      if (!isForwardLocked(pkg) && !isExternal(pkg)) { -                                        NativeLibraryHelper.copyNativeBinariesIfNeededLI( -                                                new File(newCodePath), newNativeDir); +                                        // NOTE: We do not report any errors from the APK scan and library +                                        // copy at this point. +                                        NativeLibraryHelper.ApkHandle handle = +                                                new NativeLibraryHelper.ApkHandle(newCodePath); +                                        final int abi = NativeLibraryHelper.findSupportedAbi( +                                                handle, Build.SUPPORTED_ABIS); +                                        if (abi >= 0) { +                                            NativeLibraryHelper.copyNativeBinariesIfNeededLI( +                                                    handle, newNativeDir, Build.SUPPORTED_ABIS[abi]); +                                        } +                                        handle.close();                                      }                                      final int[] users = sUserManager.getUserIds();                                      for (int user : users) {  |