Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3178e9f6 authored by Narayan Kamath's avatar Narayan Kamath Committed by Gerrit Code Review
Browse files

Merge "Scan package to derive ABIs before optimizing."

parents 2e06258c 2b6d792a
Loading
Loading
Loading
Loading
+176 −118
Original line number Original line Diff line number Diff line
@@ -5494,7 +5494,6 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
        }
        final String path = scanFile.getPath();
        final String path = scanFile.getPath();
        final String codePath = pkg.applicationInfo.getCodePath();
        final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
        final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
        if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
        if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
            setBundledAppAbisAndRoots(pkg, pkgSetting);
            setBundledAppAbisAndRoots(pkg, pkgSetting);
@@ -5520,128 +5519,28 @@ public class PackageManagerService extends IPackageManager.Stub {
            setNativeLibraryPaths(pkg);
            setNativeLibraryPaths(pkg);
        } else {
        } else {
            // TODO: We can probably be smarter about this stuff. For installed apps,
            if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
            // we can calculate this information at install time once and for all. For
                deriveNonSystemPackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);
            // system apps, we can probably assume that this information doesn't change
            // after the first boot scan. As things stand, we do lots of unnecessary work.
            // Give ourselves some initial paths; we'll come back for another
            // pass once we've determined ABI below.
            setNativeLibraryPaths(pkg);
            final boolean isAsec = pkg.isForwardLocked() || isExternal(pkg);
            final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir;
            final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa;
            NativeLibraryHelper.Handle handle = null;
            try {
                handle = NativeLibraryHelper.Handle.create(scanFile);
                // TODO(multiArch): This can be null for apps that didn't go through the
                // usual installation process. We can calculate it again, like we
                // do during install time.
                //
                // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally
                // unnecessary.
                final File nativeLibraryRoot = new File(nativeLibraryRootStr);
                // Null out the abis so that they can be recalculated.
                pkg.applicationInfo.primaryCpuAbi = null;
                pkg.applicationInfo.secondaryCpuAbi = null;
                if (isMultiArch(pkg.applicationInfo)) {
                    // Warn if we've set an abiOverride for multi-lib packages..
                    // By definition, we need to copy both 32 and 64 bit libraries for
                    // such packages.
                    if (pkg.cpuAbiOverride != null
                            && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
                        Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
                    }
                    int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
                    int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
                    if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
                        if (isAsec) {
                            abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
                        } else {
                            abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
                                    nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
                                    useIsaSpecificSubdirs);
                        }
                    }
                    maybeThrowExceptionForMultiArchCopy(
                            "Error unpackaging 32 bit native libs for multiarch app.", abi32);
                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
                        if (isAsec) {
                            abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
                        } else {
                            abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
                                    nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
                                    useIsaSpecificSubdirs);
                        }
                    }
                    maybeThrowExceptionForMultiArchCopy(
                            "Error unpackaging 64 bit native libs for multiarch app.", abi64);
                    if (abi64 >= 0) {
                        pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
                    }
                    if (abi32 >= 0) {
                        final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
                        if (abi64 >= 0) {
                            pkg.applicationInfo.secondaryCpuAbi = abi;
            } else {
            } else {
                            pkg.applicationInfo.primaryCpuAbi = abi;
                // Verify the ABIs haven't changed since we last deduced them.
                        }
                String oldPrimaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
                    }
                String oldSecondaryCpuAbi = pkg.applicationInfo.secondaryCpuAbi;
                } else {
                    String[] abiList = (cpuAbiOverride != null) ?
                            new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
                    // Enable gross and lame hacks for apps that are built with old
                // TODO: The only purpose of this code is to update the native library paths
                    // SDK tools. We must scan their APKs for renderscript bitcode and
                // based on the final install location. We can simplify this and avoid having
                    // not launch them if it's present. Don't bother checking on devices
                // to scan the package again.
                    // that don't have 64 bit support.
                deriveNonSystemPackageAbi(pkg, scanFile, cpuAbiOverride, false /* extract libs */);
                    boolean needsRenderScriptOverride = false;
                if (!TextUtils.equals(oldPrimaryCpuAbi, pkg.applicationInfo.primaryCpuAbi)) {
                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
                    throw new IllegalStateException("unexpected abi change for " + pkg.packageName + " ("
                            NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
                            + oldPrimaryCpuAbi + "-> " + pkg.applicationInfo.primaryCpuAbi);
                        abiList = Build.SUPPORTED_32_BIT_ABIS;
                        needsRenderScriptOverride = true;
                }
                }
                    final int copyRet;
                if (!TextUtils.equals(oldSecondaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi)) {
                    if (isAsec) {
                    throw new IllegalStateException("unexpected abi change for " + pkg.packageName + " ("
                        copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
                            + oldSecondaryCpuAbi + "-> " + pkg.applicationInfo.secondaryCpuAbi);
                    } else {
                        copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
                                nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
                }
                }
                    if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
                        throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                                "Error unpackaging native libs for app, errorCode=" + copyRet);
                    }
                    if (copyRet >= 0) {
                        pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
                    } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
                        pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
                    } else if (needsRenderScriptOverride) {
                        pkg.applicationInfo.primaryCpuAbi = abiList[0];
                    }
                }
            } catch (IOException ioe) {
                Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
            } finally {
                IoUtils.closeQuietly(handle);
            }
            }
            // Now that we've calculated the ABIs and determined if it's an internal app,
            // we will go ahead and populate the nativeLibraryPath.
            setNativeLibraryPaths(pkg);
            if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
            if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
            final int[] userIds = sUserManager.getUserIds();
            final int[] userIds = sUserManager.getUserIds();
            synchronized (mInstallLock) {
            synchronized (mInstallLock) {
@@ -5670,9 +5569,21 @@ public class PackageManagerService extends IPackageManager.Stub {
                    Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
                    Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
        }
        }
        // If there's a mismatch between the abi-override in the package setting
        // and the abiOverride specified for the install. Warn about this because we
        // would've already compiled the app without taking the package setting into
        // account.
        if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) {
            if (cpuAbiOverride == null && pkgSetting.cpuAbiOverrideString != null) {
                Slog.w(TAG, "Ignoring persisted ABI override " + cpuAbiOverride +
                        " for package: " + pkg.packageName);
            }
        }
        pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
        pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
        pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
        pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
        pkgSetting.cpuAbiOverrideString = cpuAbiOverride;
        pkgSetting.cpuAbiOverrideString = cpuAbiOverride;
        // Copy the derived override back to the parsed package, so that we can
        // Copy the derived override back to the parsed package, so that we can
        // update the package settings accordingly.
        // update the package settings accordingly.
        pkg.cpuAbiOverride = cpuAbiOverride;
        pkg.cpuAbiOverride = cpuAbiOverride;
@@ -6175,6 +6086,144 @@ public class PackageManagerService extends IPackageManager.Stub {
        return pkg;
        return pkg;
    }
    }
    /**
     * Derive the ABI of a non-system package located at {@code scanFile}. This information
     * is derived purely on the basis of the contents of {@code scanFile} and
     * {@code cpuAbiOverride}.
     *
     * If {@code extractLibs} is true, native libraries are extracted from the app if required.
     */
    public void deriveNonSystemPackageAbi(PackageParser.Package pkg, File scanFile,
                                          String cpuAbiOverride, boolean extractLibs)
            throws PackageManagerException {
        // TODO: We can probably be smarter about this stuff. For installed apps,
        // we can calculate this information at install time once and for all. For
        // system apps, we can probably assume that this information doesn't change
        // after the first boot scan. As things stand, we do lots of unnecessary work.
        // Give ourselves some initial paths; we'll come back for another
        // pass once we've determined ABI below.
        setNativeLibraryPaths(pkg);
        // We would never need to extract libs for forward-locked and external packages,
        // since the container service will do it for us.
        if (pkg.isForwardLocked() || isExternal(pkg)) {
            extractLibs = false;
        }
        final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir;
        final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa;
        NativeLibraryHelper.Handle handle = null;
        try {
            handle = NativeLibraryHelper.Handle.create(scanFile);
            // TODO(multiArch): This can be null for apps that didn't go through the
            // usual installation process. We can calculate it again, like we
            // do during install time.
            //
            // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally
            // unnecessary.
            final File nativeLibraryRoot = new File(nativeLibraryRootStr);
            // Null out the abis so that they can be recalculated.
            pkg.applicationInfo.primaryCpuAbi = null;
            pkg.applicationInfo.secondaryCpuAbi = null;
            if (isMultiArch(pkg.applicationInfo)) {
                // Warn if we've set an abiOverride for multi-lib packages..
                // By definition, we need to copy both 32 and 64 bit libraries for
                // such packages.
                if (pkg.cpuAbiOverride != null
                        && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
                    Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
                }
                int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
                int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
                if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
                    if (extractLibs) {
                        abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
                                nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
                                useIsaSpecificSubdirs);
                    } else {
                        abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
                    }
                }
                maybeThrowExceptionForMultiArchCopy(
                        "Error unpackaging 32 bit native libs for multiarch app.", abi32);
                if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
                    if (extractLibs) {
                        abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
                                nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
                                useIsaSpecificSubdirs);
                    } else {
                        abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
                    }
                }
                maybeThrowExceptionForMultiArchCopy(
                        "Error unpackaging 64 bit native libs for multiarch app.", abi64);
                if (abi64 >= 0) {
                    pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
                }
                if (abi32 >= 0) {
                    final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
                    if (abi64 >= 0) {
                        pkg.applicationInfo.secondaryCpuAbi = abi;
                    } else {
                        pkg.applicationInfo.primaryCpuAbi = abi;
                    }
                }
            } else {
                String[] abiList = (cpuAbiOverride != null) ?
                        new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
                // 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
                // that don't have 64 bit support.
                boolean needsRenderScriptOverride = false;
                if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
                        NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
                    abiList = Build.SUPPORTED_32_BIT_ABIS;
                    needsRenderScriptOverride = true;
                }
                final int copyRet;
                if (extractLibs) {
                    copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
                            nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
                } else {
                    copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
                }
                if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
                    throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                            "Error unpackaging native libs for app, errorCode=" + copyRet);
                }
                if (copyRet >= 0) {
                    pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
                } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
                    pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
                } else if (needsRenderScriptOverride) {
                    pkg.applicationInfo.primaryCpuAbi = abiList[0];
                }
            }
        } catch (IOException ioe) {
            Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
        } finally {
            IoUtils.closeQuietly(handle);
        }
        // Now that we've calculated the ABIs and determined if it's an internal app,
        // we will go ahead and populate the nativeLibraryPath.
        setNativeLibraryPaths(pkg);
    }
    /**
    /**
     * Adjusts ABIs for a set of packages belonging to a shared user so that they all match.
     * Adjusts ABIs for a set of packages belonging to a shared user so that they all match.
     * i.e, so that all packages can be run inside a single process if required.
     * i.e, so that all packages can be run inside a single process if required.
@@ -10425,6 +10474,15 @@ public class PackageManagerService extends IPackageManager.Stub {
        if (!forwardLocked && pkg.applicationInfo.isInternal()) {
        if (!forwardLocked && pkg.applicationInfo.isInternal()) {
            // Enable SCAN_NO_DEX flag to skip dexopt at a later stage
            // Enable SCAN_NO_DEX flag to skip dexopt at a later stage
            scanFlags |= SCAN_NO_DEX;
            scanFlags |= SCAN_NO_DEX;
            try {
                deriveNonSystemPackageAbi(pkg, new File(pkg.codePath), args.abiOverride,
                        true /* extract libs */);
            } catch (PackageManagerException pme) {
                Slog.e(TAG, "Error deriving application ABI", pme);
                res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error ");
                return;
            }
            // Run dexopt before old package gets removed, to minimize time when app is unavailable
            // Run dexopt before old package gets removed, to minimize time when app is unavailable
            int result = mPackageDexOptimizer
            int result = mPackageDexOptimizer
                    .performDexOpt(pkg, null /* instruction sets */, true /* forceDex */,
                    .performDexOpt(pkg, null /* instruction sets */, true /* forceDex */,