From c606627e6c931d4d1e60ce29f7802d7bd9f4403d Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Wed, 19 Jul 2017 09:47:55 -0700 Subject: [PATCH] Always populate the ApplicationInfo object While scanning system apps, we abort package/application info setup if an app on /system is not a higher version than an upgrade on /data. Instead, we need to still fully populate these objects because they can be retrievd using the MATCH_FACTORY_ONLY flag. Change-Id: I0262b46f446eace60ce94f1428f3fb15d785a89c Fixes: 62980149 Test: Manual Test: Create a sample application that dumps the contents of an ApplicationInfo object for a given package Test: Install the sample application on the /system partition and "upgrade" the sample application so it's also on the /data partition Test: Create a secondary user and disable the sample application Test: Reboot the device Test: Run the sample application as the primary user and see that the ApplicationInfo object is correctly populated --- .../android/server/pm/PackageManagerService.java | 74 ++++++++++++---------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 181017439b4e..32983ec3450d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -8918,9 +8918,12 @@ public class PackageManagerService extends IPackageManager.Stub } } - boolean updatedPkgBetter = false; + final boolean isUpdatedPkg = updatedPkg != null; + final boolean isUpdatedSystemPkg = isUpdatedPkg + && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0; + boolean isUpdatedPkgBetter = false; // First check if this is a system package that may involve an update - if (updatedPkg != null && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) { + if (isUpdatedSystemPkg) { // If new package is not located in "/system/priv-app" (e.g. due to an OTA), // it needs to drop FLAG_PRIVILEGED. if (locationIsPrivileged(scanFile)) { @@ -8964,10 +8967,6 @@ public class PackageManagerService extends IPackageManager.Stub updatedChildPkg.versionCode = pkg.mVersionCode; } } - - throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at " - + scanFile + " ignored: updated version " + ps.versionCode - + " better than this " + pkg.mVersionCode); } else { // The current app on the system partition is better than // what we have updated to on the data partition; switch @@ -8994,12 +8993,44 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mPackages) { mSettings.enableSystemPackageLPw(ps.name); } - updatedPkgBetter = true; + isUpdatedPkgBetter = true; } } } - if (updatedPkg != null) { + String resourcePath = null; + String baseResourcePath = null; + if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !isUpdatedPkgBetter) { + if (ps != null && ps.resourcePathString != null) { + resourcePath = ps.resourcePathString; + baseResourcePath = ps.resourcePathString; + } else { + // Should not happen at all. Just log an error. + Slog.e(TAG, "Resource path not set for package " + pkg.packageName); + } + } else { + resourcePath = pkg.codePath; + baseResourcePath = pkg.baseCodePath; + } + + // Set application objects path explicitly. + pkg.setApplicationVolumeUuid(pkg.volumeUuid); + pkg.setApplicationInfoCodePath(pkg.codePath); + pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath); + pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths); + pkg.setApplicationInfoResourcePath(resourcePath); + pkg.setApplicationInfoBaseResourcePath(baseResourcePath); + pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); + + // throw an exception if we have an update to a system application, but, it's not more + // recent than the package we've already scanned + if (isUpdatedSystemPkg && !isUpdatedPkgBetter) { + throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at " + + scanFile + " ignored: updated version " + ps.versionCode + + " better than this " + pkg.mVersionCode); + } + + if (isUpdatedPkg) { // An updated system app will not have the PARSE_IS_SYSTEM flag set // initially policyFlags |= PackageParser.PARSE_IS_SYSTEM; @@ -9019,7 +9050,7 @@ public class PackageManagerService extends IPackageManager.Stub * same name installed earlier. */ boolean shouldHideSystemApp = false; - if (updatedPkg == null && ps != null + if (!isUpdatedPkg && ps != null && (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) { /* * Check to make sure the signatures match first. If they don't, @@ -9074,31 +9105,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - // TODO: extend to support forward-locked splits - String resourcePath = null; - String baseResourcePath = null; - if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) { - if (ps != null && ps.resourcePathString != null) { - resourcePath = ps.resourcePathString; - baseResourcePath = ps.resourcePathString; - } else { - // Should not happen at all. Just log an error. - Slog.e(TAG, "Resource path not set for package " + pkg.packageName); - } - } else { - resourcePath = pkg.codePath; - baseResourcePath = pkg.baseCodePath; - } - - // Set application objects path explicitly. - pkg.setApplicationVolumeUuid(pkg.volumeUuid); - pkg.setApplicationInfoCodePath(pkg.codePath); - pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath); - pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths); - pkg.setApplicationInfoResourcePath(resourcePath); - pkg.setApplicationInfoBaseResourcePath(baseResourcePath); - pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); - final int userId = ((user == null) ? 0 : user.getIdentifier()); if (ps != null && ps.getInstantApp(userId)) { scanFlags |= SCAN_AS_INSTANT_APP; -- 2.11.0