diff options
author | Kenny Root <kroot@google.com> | 2012-05-07 19:42:35 -0700 |
---|---|---|
committer | Kenny Root <kroot@google.com> | 2012-05-08 15:57:44 -0700 |
commit | 208d341bbd61bf818ec0acddb6cad4e616239d50 (patch) | |
tree | 3bf8926c19015a53cc590ffa53de3d6ca79793e1 | |
parent | 59f3f5853cd05103b5a83f5ddbe584a5270a9c6b (diff) | |
download | frameworks_base-208d341bbd61bf818ec0acddb6cad4e616239d50.zip frameworks_base-208d341bbd61bf818ec0acddb6cad4e616239d50.tar.gz frameworks_base-208d341bbd61bf818ec0acddb6cad4e616239d50.tar.bz2 |
Handle addition of system apps during OTA
If there were apps already installed that were added in a later system
OTA, bad things would happen.
If the previously installed application is an older version, simply
delete the installed application. If the system app is older than the
previously installed one, mark it as a disabled system app and use the
previoulsy installed application.
Additionally, the application will now have the correct granted
permissions.
Bug: 6251602
Change-Id: Iea444b6acac460fca1e08d4e2cbf68a258214ca6
-rw-r--r-- | services/java/com/android/server/pm/PackageManagerService.java | 111 |
1 files changed, 103 insertions, 8 deletions
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 4ae3c57..7c14d49 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -1050,7 +1050,7 @@ public class PackageManagerService extends IPackageManager.Stub { mSystemInstallObserver.startWatching(); scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0); - + // Collect all vendor packages. mVendorAppDir = new File("/vendor/app"); mVendorInstallObserver = new AppDirObserver( @@ -1068,8 +1068,30 @@ public class PackageManagerService extends IPackageManager.Stub { Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator(); while (psit.hasNext()) { PackageSetting ps = psit.next(); - if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0 - || mPackages.containsKey(ps.name)) { + + /* + * If this is not a system app, it can't be a + * disable system app. + */ + if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { + continue; + } + + /* + * If the package is scanned, it's not erased. + */ + if (mPackages.containsKey(ps.name)) { + /* + * If the system app is both scanned and in the + * disabled packages list, then it must have been + * added via OTA. Remove it from the currently + * scanned package so the previously user-installed + * application can be scanned. + */ + if (mSettings.isDisabledSystemPackageLPr(ps.name)) { + mPackages.remove(ps.name); + } + continue; } @@ -3096,15 +3118,21 @@ public class PackageManagerService extends IPackageManager.Stub { + "reverting from " + ps.codePathString + ": new version " + pkg.mVersionCode + " better than installed " + ps.versionCode); - InstallArgs args = new FileInstallArgs(ps.codePathString, + InstallArgs args = createInstallArgs(ps.pkgFlags, ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); - args.cleanUpResourcesLI(); - mSettings.enableSystemPackageLPw(ps.name); + synchronized (mInstaller) { + args.cleanUpResourcesLI(); + } + synchronized (mPackages) { + mSettings.enableSystemPackageLPw(ps.name); + } } } } + if (updatedPkg != null) { - // An updated system app will not have the PARSE_IS_SYSTEM flag set initially + // An updated system app will not have the PARSE_IS_SYSTEM flag set + // initially parseFlags |= PackageParser.PARSE_IS_SYSTEM; } // Verify certificates against what was last scanned @@ -3112,6 +3140,49 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName); return null; } + + /* + * A new system app appeared, but we already had a non-system one of the + * same name installed earlier. + */ + boolean shouldHideSystemApp = false; + if (updatedPkg == null && ps != null + && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) { + /* + * Check to make sure the signatures match first. If they don't, + * wipe the installed application and its data. + */ + if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures) + != PackageManager.SIGNATURE_MATCH) { + deletePackageLI(pkg.packageName, true, 0, null, false); + ps = null; + } else { + /* + * If the newly-added system app is an older version than the + * already installed version, hide it. It will be scanned later + * and re-added like an update. + */ + if (pkg.mVersionCode < ps.versionCode) { + shouldHideSystemApp = true; + } else { + /* + * The newly found system app is a newer version that the + * one previously installed. Simply remove the + * already-installed application and replace it with our own + * while keeping the application data. + */ + Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from " + + ps.codePathString + ": new version " + pkg.mVersionCode + + " better than installed " + ps.versionCode); + InstallArgs args = createInstallArgs(ps.pkgFlags, ps.codePathString, + ps.resourcePathString, ps.nativeLibraryPathString); + synchronized (mInstaller) { + args.cleanUpResourcesLI(); + } + } + } + } + // The apk is forward locked (not public) if its code and resources // are kept in different files. // TODO grab this value from PackageSettings @@ -3135,7 +3206,27 @@ public class PackageManagerService extends IPackageManager.Stub { // Set application objects path explicitly. setApplicationInfoPaths(pkg, codePath, resPath); // Note that we invoke the following method only if we are about to unpack an application - return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime); + PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode + | SCAN_UPDATE_SIGNATURE, currentTime); + + /* + * If the system app should be overridden by a previously installed + * data, hide the system app now and let the /data/app scan pick it up + * again. + */ + if (shouldHideSystemApp) { + synchronized (mPackages) { + /* + * We have to grant systems permissions before we hide, because + * grantPermissions will assume the package update is trying to + * expand its permissions. + */ + grantPermissionsLPw(pkg, true); + mSettings.disableSystemPackageLPw(pkg.packageName); + } + } + + return scannedPkg; } private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath, @@ -7177,6 +7268,10 @@ public class PackageManagerService extends IPackageManager.Stub { return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } + private static boolean isSystemApp(PackageSetting ps) { + return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0; + } + private static boolean isUpdatedSystemApp(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; } |