OSDN Git Service

Reset the profile when system application change version.
authorHyangseok Chae <neo.chae@lge.com>
Sun, 1 Apr 2018 23:23:31 +0000 (08:23 +0900)
committerCalin Juravle <calin@google.com>
Tue, 8 May 2018 00:14:23 +0000 (17:14 -0700)
Background optimization has flag checkProfiles as true,
performDexOptLI check profile is updated with checkProfiles.
(isProfileUpdated() -> mergeProfiles -> analyze_profiles())
analyze_profiles decides if it is need to compile and clear
the profile or not. But analyze_profiles and profman merge
only based on existing profiles. Eventhough checksum of
application dex was changed, profman only check the profile
can be merge or not.

With below TC, the return value of profman is PROFMAN_BIN_
RETURN_CODE_SKIP_COMPILATION(1). Because current profile
has not enough informations than reference profile.
I think ProcessProfilesInternal should consider change
of dex checksum, If there are mismatch checksum of dex
between profiles and dex, then profman should return with
PROFMAN_BIN_RETURN_CODE_BAD_PROFILES (2).
After that analyze_profiles can reset profiles with
PROFMAN_BIN_RETURN_CODE_BAD_PROFILES.

But profman does not have that implemtation for verify
the profile based on checksum. So, It is need to drop
the profile based on change of application version.

Test: System update
1. Factory Image with system application. (vendor, system app)
2. Use Sample application to generage current profile.
3. BackgroundDexOptService optimize with speed-profile.
4. Use Sample application to generage current profile.
5. There are small size of current profile and large size
    of reference profile.
6. System update with application change.
7. Reboot.
8. Next background optimization would be fail permanently.

Bug: 77839992

Change-Id: Iac575ae5906498a59b750df0b281fab01df57b3e

services/core/java/com/android/server/pm/PackageManagerService.java

index af5521d..a9eb745 100644 (file)
@@ -8482,6 +8482,29 @@ public class PackageManagerService extends IPackageManager.Stub
     }
 
     /**
+     * Clear the package profile if this was an upgrade and the package
+     * version was updated.
+     */
+    private void maybeClearProfilesForUpgradesLI(
+            @Nullable PackageSetting originalPkgSetting,
+            @NonNull PackageParser.Package currentPkg) {
+        if (originalPkgSetting == null || !isUpgrade()) {
+          return;
+        }
+        if (originalPkgSetting.versionCode == currentPkg.mVersionCode) {
+          return;
+        }
+
+        clearAppProfilesLIF(currentPkg, UserHandle.USER_ALL);
+        if (DEBUG_INSTALL) {
+            Slog.d(TAG, originalPkgSetting.name
+                  + " clear profile due to version change "
+                  + originalPkgSetting.versionCode + " != "
+                  + currentPkg.mVersionCode);
+        }
+    }
+
+    /**
      *  Traces a package scan.
      *  @see #scanPackageLI(File, int, int, long, UserHandle)
      */
@@ -8763,6 +8786,13 @@ public class PackageManagerService extends IPackageManager.Stub
                 (forceCollect && canSkipFullPackageVerification(pkg));
         collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify);
 
+        // Reset profile if the application version is changed
+        maybeClearProfilesForUpgradesLI(pkgSetting, pkg);
+
+        /*
+         * A new system app appeared, but we already had a non-system one of the
+         * same name installed earlier.
+         */
         boolean shouldHideSystemApp = false;
         // A new application appeared on /system, but, we already have a copy of
         // the application installed on /data.