diff options
| author | 2019-04-11 04:31:22 +0000 | |
|---|---|---|
| committer | 2019-04-11 04:31:22 +0000 | |
| commit | 6b1c8d681684a6283c0b89bad4fee0482414ca5e (patch) | |
| tree | 9125a5cd5fe631af7cff2aa5324540c405ef03b5 | |
| parent | b73580d2fa1404b592ac28c1601ade5089894323 (diff) | |
| parent | 6fa6a9f0e39370fa106a72bc953dc8552dccac5f (diff) | |
Merge "Fix compressed stubs" into qt-dev
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 283 |
1 files changed, 150 insertions, 133 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 898437ddae41..928b8f651fd8 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2967,7 +2967,7 @@ public class PackageManagerService extends IPackageManager.Stub // Uncompress and install any stubbed system applications. // This must be done last to ensure all stubs are replaced or disabled. - decompressSystemApplications(stubSystemApps, scanFlags); + installSystemStubPackages(stubSystemApps, scanFlags); final int cachedNonSystemApps = PackageParser.sCachedPackageReadCount.get() - cachedSystemApps; @@ -3278,49 +3278,37 @@ public class PackageManagerService extends IPackageManager.Stub * <p>In order to forcefully attempt an installation of a full application, go to app * settings and enable the application. */ - private void decompressSystemApplications(@NonNull List<String> stubSystemApps, int scanFlags) { - for (int i = stubSystemApps.size() - 1; i >= 0; --i) { - final String pkgName = stubSystemApps.get(i); + private void installSystemStubPackages(@NonNull List<String> systemStubPackageNames, + @ScanFlags int scanFlags) { + for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) { + final String packageName = systemStubPackageNames.get(i); // skip if the system package is already disabled - if (mSettings.isDisabledSystemPackageLPr(pkgName)) { - stubSystemApps.remove(i); + if (mSettings.isDisabledSystemPackageLPr(packageName)) { + systemStubPackageNames.remove(i); continue; } // skip if the package isn't installed (?!); this should never happen - final PackageParser.Package pkg = mPackages.get(pkgName); + final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null) { - stubSystemApps.remove(i); + systemStubPackageNames.remove(i); continue; } // skip if the package has been disabled by the user - final PackageSetting ps = mSettings.mPackages.get(pkgName); + final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { final int enabledState = ps.getEnabled(UserHandle.USER_SYSTEM); if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) { - stubSystemApps.remove(i); + systemStubPackageNames.remove(i); continue; } } - if (DEBUG_COMPRESSION) { - Slog.i(TAG, "Uncompressing system stub; pkg: " + pkgName); - } - - // uncompress the binary to its eventual destination on /data - final File scanFile = decompressPackage(pkg); - if (scanFile == null) { - continue; - } - // install the package to replace the stub on /system try { - mSettings.disableSystemPackageLPw(pkgName, true /*replaced*/); - removePackageLI(pkg, true /*chatty*/); - scanPackageTracedLI(scanFile, 0 /*reparseFlags*/, scanFlags, 0, null); + installStubPackageLI(pkg, 0, scanFlags); ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, UserHandle.USER_SYSTEM, "android"); - stubSystemApps.remove(i); - continue; + systemStubPackageNames.remove(i); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to parse uncompressed system package: " + e.getMessage()); } @@ -3329,8 +3317,8 @@ public class PackageManagerService extends IPackageManager.Stub } // disable any stub still left; these failed to install the full application - for (int i = stubSystemApps.size() - 1; i >= 0; --i) { - final String pkgName = stubSystemApps.get(i); + for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) { + final String pkgName = systemStubPackageNames.get(i); final PackageSetting ps = mSettings.mPackages.get(pkgName); ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DISABLED, UserHandle.USER_SYSTEM, "android"); @@ -3339,20 +3327,107 @@ public class PackageManagerService extends IPackageManager.Stub } /** + * Extract, install and enable a stub package. + * <p>If the compressed file can not be extracted / installed for any reason, the stub + * APK will be installed and the package will be disabled. To recover from this situation, + * the user will need to go into system settings and re-enable the package. + */ + private boolean enableCompressedPackage(PackageParser.Package stubPkg) { + final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY + | PackageParser.PARSE_ENFORCE_CODE; + synchronized (mInstallLock) { + final PackageParser.Package pkg; + try (PackageFreezer freezer = + freezePackage(stubPkg.packageName, "setEnabledSetting")) { + pkg = installStubPackageLI(stubPkg, parseFlags, 0 /*scanFlags*/); + synchronized (mPackages) { + prepareAppDataAfterInstallLIF(pkg); + try { + updateSharedLibrariesLocked(pkg, null, mPackages); + } catch (PackageManagerException e) { + Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e); + } + mPermissionManager.updatePermissions( + pkg.packageName, pkg, true, mPackages.values(), + mPermissionCallback); + mSettings.writeLPr(); + } + } catch (PackageManagerException e) { + // Whoops! Something went very wrong; roll back to the stub and disable the package + try (PackageFreezer freezer = + freezePackage(stubPkg.packageName, "setEnabledSetting")) { + synchronized (mPackages) { + // NOTE: Ensure the system package is enabled; even for a compressed stub. + // If we don't, installing the system package fails during scan + enableSystemPackageLPw(stubPkg); + } + installPackageFromSystemLIF(stubPkg.codePath, + null /*allUserHandles*/, null /*origUserHandles*/, + null /*origPermissionsState*/, true /*writeSettings*/); + } catch (PackageManagerException pme) { + // Serious WTF; we have to be able to install the stub + Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.packageName, pme); + } finally { + // Disable the package; the stub by itself is not runnable + synchronized (mPackages) { + final PackageSetting stubPs = mSettings.mPackages.get(stubPkg.packageName); + if (stubPs != null) { + stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, + UserHandle.USER_SYSTEM, "android"); + } + mSettings.writeLPr(); + } + } + return false; + } + clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE + | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + mDexManager.notifyPackageUpdated(pkg.packageName, + pkg.baseCodePath, pkg.splitCodePaths); + } + return true; + } + + private PackageParser.Package installStubPackageLI(PackageParser.Package stubPkg, + @ParseFlags int parseFlags, @ScanFlags int scanFlags) + throws PackageManagerException { + if (DEBUG_COMPRESSION) { + Slog.i(TAG, "Uncompressing system stub; pkg: " + stubPkg.packageName); + } + // uncompress the binary to its eventual destination on /data + final File scanFile = decompressPackage(stubPkg.packageName, stubPkg.codePath); + if (scanFile == null) { + throw new PackageManagerException("Unable to decompress stub at " + stubPkg.codePath); + } + synchronized (mPackages) { + mSettings.disableSystemPackageLPw(stubPkg.packageName, true /*replaced*/); + } + removePackageLI(stubPkg, true /*chatty*/); + try { + return scanPackageTracedLI(scanFile, parseFlags, scanFlags, 0, null); + } catch (PackageManagerException e) { + Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.packageName, e); + // Remove the failed install + removeCodePathLI(scanFile); + throw e; + } + } + + /** * Decompresses the given package on the system image onto * the /data partition. * @return The directory the package was decompressed into. Otherwise, {@code null}. */ - private File decompressPackage(PackageParser.Package pkg) { - final File[] compressedFiles = getCompressedFiles(pkg.codePath); + private File decompressPackage(String packageName, String codePath) { + final File[] compressedFiles = getCompressedFiles(codePath); if (compressedFiles == null || compressedFiles.length == 0) { if (DEBUG_COMPRESSION) { - Slog.i(TAG, "No files to decompress: " + pkg.baseCodePath); + Slog.i(TAG, "No files to decompress: " + codePath); } return null; } final File dstCodePath = - getNextCodePath(Environment.getDataAppDirectory(null), pkg.packageName); + getNextCodePath(Environment.getDataAppDirectory(null), packageName); int ret = PackageManager.INSTALL_SUCCEEDED; try { Os.mkdir(dstCodePath.getAbsolutePath(), 0755); @@ -3365,14 +3440,14 @@ public class PackageManagerService extends IPackageManager.Stub ret = decompressFile(srcFile, dstFile); if (ret != PackageManager.INSTALL_SUCCEEDED) { logCriticalInfo(Log.ERROR, "Failed to decompress" - + "; pkg: " + pkg.packageName + + "; pkg: " + packageName + ", file: " + dstFileName); break; } } } catch (ErrnoException e) { logCriticalInfo(Log.ERROR, "Failed to decompress" - + "; pkg: " + pkg.packageName + + "; pkg: " + packageName + ", err: " + e.errno); } if (ret == PackageManager.INSTALL_SUCCEEDED) { @@ -3384,7 +3459,7 @@ public class PackageManagerService extends IPackageManager.Stub null /*abiOverride*/); } catch (IOException e) { logCriticalInfo(Log.ERROR, "Failed to extract native libraries" - + "; pkg: " + pkg.packageName); + + "; pkg: " + packageName); ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } finally { IoUtils.closeQuietly(handle); @@ -18216,12 +18291,15 @@ public class PackageManagerService extends IPackageManager.Stub return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER; } - PackageSetting uninstalledPs; - PackageParser.Package pkg; + final PackageSetting uninstalledPs; + final PackageSetting disabledSystemPs; + final PackageParser.Package pkg; // for the uninstall-updates case and restricted profiles, remember the per- // user handle installed state int[] allUsers; + /** enabled state of the uninstalled application */ + final int origEnabledState; synchronized (mPackages) { uninstalledPs = mSettings.mPackages.get(packageName); if (uninstalledPs == null) { @@ -18236,6 +18314,11 @@ public class PackageManagerService extends IPackageManager.Stub return PackageManager.DELETE_FAILED_INTERNAL_ERROR; } + disabledSystemPs = mSettings.getDisabledSystemPkgLPr(packageName); + // Save this off before we delete the package. When deleting a stub application + // we always set the enabled state to 'disabled'. + origEnabledState = uninstalledPs == null + ? COMPONENT_ENABLED_STATE_DEFAULT : uninstalledPs.getEnabled(userId); // Static shared libs can be declared by any package, so let us not // allow removing a package if it provides a lib others depend on. pkg = mPackages.get(packageName); @@ -18304,10 +18387,30 @@ public class PackageManagerService extends IPackageManager.Stub Runtime.getRuntime().gc(); // Delete the resources here after sending the broadcast to let // other processes clean up before deleting resources. - if (info.args != null) { - synchronized (mInstallLock) { + synchronized (mInstallLock) { + if (info.args != null) { info.args.doPostDeleteLI(true); } + final PackageParser.Package stubPkg = + (disabledSystemPs == null) ? null : disabledSystemPs.pkg; + if (stubPkg != null && stubPkg.isStub) { + synchronized (mPackages) { + // restore the enabled state of the stub; the state is overwritten when + // the stub is uninstalled + final PackageSetting stubPs = mSettings.mPackages.get(stubPkg.packageName); + if (stubPs != null) { + stubPs.setEnabled(origEnabledState, userId, "android"); + } + } + if (origEnabledState == COMPONENT_ENABLED_STATE_DEFAULT + || origEnabledState == COMPONENT_ENABLED_STATE_ENABLED) { + if (DEBUG_COMPRESSION) { + Slog.i(TAG, "Enabling system stub after removal; pkg: " + + stubPkg.packageName); + } + enableCompressedPackage(stubPkg); + } + } } return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR; @@ -18713,7 +18816,14 @@ public class PackageManagerService extends IPackageManager.Stub throw new SystemDeleteException(e); } finally { if (disabledPs.pkg.isStub) { - mSettings.disableSystemPackageLPw(disabledPs.name, true /*replaced*/); + // We've re-installed the stub; make sure it's disabled here. If package was + // originally enabled, we'll install the compressed version of the application + // and re-enable it afterward. + final PackageSetting stubPs = mSettings.mPackages.get(deletedPkg.packageName); + if (stubPs != null) { + stubPs.setEnabled( + COMPONENT_ENABLED_STATE_DISABLED, UserHandle.USER_SYSTEM, "android"); + } } } } @@ -20798,102 +20908,9 @@ public class PackageManagerService extends IPackageManager.Stub if (isSystemStub && (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) { - final File codePath = decompressPackage(deletedPkg); - if (codePath == null) { - Slog.e(TAG, "couldn't decompress pkg: " + pkgSetting.name); - return; - } - // TODO remove direct parsing of the package object during internal cleanup - // of scan package - // We need to call parse directly here for no other reason than we need - // the new package in order to disable the old one [we use the information - // for some internal optimization to optionally create a new package setting - // object on replace]. However, we can't get the package from the scan - // because the scan modifies live structures and we need to remove the - // old [system] package from the system before a scan can be attempted. - // Once scan is indempotent we can remove this parse and use the package - // object we scanned, prior to adding it to package settings. - final PackageParser pp = new PackageParser(); - pp.setSeparateProcesses(mSeparateProcesses); - pp.setDisplayMetrics(mMetrics); - pp.setCallback(mPackageParserCallback); - final PackageParser.Package tmpPkg; - try { - final @ParseFlags int parseFlags = mDefParseFlags - | PackageParser.PARSE_MUST_BE_APK - | PackageParser.PARSE_IS_SYSTEM_DIR; - tmpPkg = pp.parsePackage(codePath, parseFlags); - } catch (PackageParserException e) { - Slog.w(TAG, "Failed to parse compressed system package:" + pkgSetting.name, e); + if (!enableCompressedPackage(deletedPkg)) { return; } - synchronized (mInstallLock) { - // Disable the stub and remove any package entries - removePackageLI(deletedPkg, true); - synchronized (mPackages) { - disableSystemPackageLPw(deletedPkg, tmpPkg); - } - final PackageParser.Package pkg; - try (PackageFreezer freezer = - freezePackage(deletedPkg.packageName, "setEnabledSetting")) { - final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY - | PackageParser.PARSE_ENFORCE_CODE; - pkg = scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/, - 0 /*currentTime*/, null /*user*/); - prepareAppDataAfterInstallLIF(pkg); - synchronized (mPackages) { - try { - updateSharedLibrariesLocked(pkg, null, mPackages); - } catch (PackageManagerException e) { - Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e); - } - mPermissionManager.updatePermissions( - pkg.packageName, pkg, true, mPackages.values(), - mPermissionCallback); - mSettings.writeLPr(); - } - } catch (PackageManagerException e) { - // Whoops! Something went wrong; try to roll back to the stub - Slog.w(TAG, "Failed to install compressed system package:" - + pkgSetting.name, e); - // Remove the failed install - removeCodePathLI(codePath); - - // Install the system package - try (PackageFreezer freezer = - freezePackage(deletedPkg.packageName, "setEnabledSetting")) { - synchronized (mPackages) { - // NOTE: The system package always needs to be enabled; even - // if it's for a compressed stub. If we don't, installing the - // system package fails during scan [scanning checks the disabled - // packages]. We will reverse this later, after we've "installed" - // the stub. - // This leaves us in a fragile state; the stub should never be - // enabled, so, cross your fingers and hope nothing goes wrong - // until we can disable the package later. - enableSystemPackageLPw(deletedPkg); - } - installPackageFromSystemLIF(deletedPkg.codePath, - /*isPrivileged*/ null /*allUserHandles*/, - null /*origUserHandles*/, null /*origPermissionsState*/, - true /*writeSettings*/); - } catch (PackageManagerException pme) { - Slog.w(TAG, "Failed to restore system package:" - + deletedPkg.packageName, pme); - } finally { - synchronized (mPackages) { - mSettings.disableSystemPackageLPw( - deletedPkg.packageName, true /*replaced*/); - mSettings.writeLPr(); - } - } - return; - } - clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE - | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); - mDexManager.notifyPackageUpdated(pkg.packageName, - pkg.baseCodePath, pkg.splitCodePaths); - } } if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { |