diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java index f8baf17664e22..45f90253a2aa0 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/PinnerService.java @@ -36,6 +36,7 @@ import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.system.StructStat; +import android.util.ArraySet; import android.util.Slog; import com.android.internal.app.ResolverActivity; @@ -77,10 +78,10 @@ public final class PinnerService extends SystemService { // If this user's camera app has been updated, update pinned files accordingly. if (intent.getAction() == Intent.ACTION_PACKAGE_REPLACED) { Uri packageUri = intent.getData(); - ApplicationInfo cameraInfo = getCameraInfo(UserHandle.USER_SYSTEM); - if (cameraInfo.packageName == packageUri.getSchemeSpecificPart()) { - update(); - } + String packageName = packageUri.getSchemeSpecificPart(); + ArraySet updatedPackages = new ArraySet<>(); + updatedPackages.add(packageName); + update(updatedPackages); } } }; @@ -129,10 +130,13 @@ public final class PinnerService extends SystemService { * Specifically, this only updates camera pinning. * The other files pinned in onStart will not need to be updated. */ - public void update() { - Slog.i(TAG, "Updating pinned files."); - mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0) - .sendToTarget(); + public void update(ArraySet updatedPackages) { + ApplicationInfo cameraInfo = getCameraInfo(UserHandle.USER_SYSTEM); + if (cameraInfo != null && updatedPackages.contains(cameraInfo.packageName)) { + Slog.i(TAG, "Updating pinned files."); + mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0) + .sendToTarget(); + } } /** diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 484cd4ea84338..0d1f58ae8a59c 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -177,6 +177,7 @@ public class BackgroundDexOptService extends JobService { mAbortPostBootUpdate.set(false); + ArraySet updatedPackages = new ArraySet<>(); for (String pkg : pkgs) { if (mAbortPostBootUpdate.get()) { // JobScheduler requested an early abort. @@ -210,11 +211,15 @@ public class BackgroundDexOptService extends JobService { // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a // trade-off worth doing to save boot time work. - pm.performDexOpt(pkg, + int result = pm.performDexOptWithStatus(pkg, /* checkProfiles */ false, PackageManagerService.REASON_BOOT, /* force */ false); + if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { + updatedPackages.add(pkg); + } } + notifyPinService(updatedPackages); // Ran to completion, so we abandon our timeslice and do not reschedule. jobFinished(jobParams, /* reschedule */ false); } @@ -267,6 +272,7 @@ public class BackgroundDexOptService extends JobService { private int optimizePackages(PackageManagerService pm, ArraySet pkgs, long lowStorageThreshold, boolean is_for_primary_dex, ArraySet failedPackageNames) { + ArraySet updatedPackages = new ArraySet<>(); for (String pkg : pkgs) { int abort_code = abortIdleOptimizations(lowStorageThreshold); if (abort_code != OPTIMIZE_CONTINUE) { @@ -286,14 +292,21 @@ public class BackgroundDexOptService extends JobService { // Optimize package if needed. Note that there can be no race between // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. - boolean success = is_for_primary_dex - ? pm.performDexOpt(pkg, - /* checkProfiles */ true, - PackageManagerService.REASON_BACKGROUND_DEXOPT, - /* force */ false) - : pm.performDexOptSecondary(pkg, - PackageManagerService.REASON_BACKGROUND_DEXOPT, - /* force */ false); + boolean success; + if (is_for_primary_dex) { + int result = pm.performDexOptWithStatus(pkg, + /* checkProfiles */ true, + PackageManagerService.REASON_BACKGROUND_DEXOPT, + /* force */ false); + success = result != PackageDexOptimizer.DEX_OPT_FAILED; + if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { + updatedPackages.add(pkg); + } + } else { + success = pm.performDexOptSecondary(pkg, + PackageManagerService.REASON_BACKGROUND_DEXOPT, + /* force */ false); + } if (success) { // Dexopt succeeded, remove package from the list of failing ones. synchronized (failedPackageNames) { @@ -301,6 +314,7 @@ public class BackgroundDexOptService extends JobService { } } } + notifyPinService(updatedPackages); return OPTIMIZE_PROCESSED; } @@ -375,12 +389,6 @@ public class BackgroundDexOptService extends JobService { result = runIdleOptimization(params, pm, pkgs); } - PinnerService pinnerService = (PinnerService) LocalServices.getService(PinnerService.class); - if (pinnerService != null) { - Log.i(TAG, "Pinning optimized code"); - pinnerService.update(); - } - return result; } @@ -397,4 +405,12 @@ public class BackgroundDexOptService extends JobService { } return false; } + + private void notifyPinService(ArraySet updatedPackages) { + PinnerService pinnerService = LocalServices.getService(PinnerService.class); + if (pinnerService != null) { + Log.i(TAG, "Pinning optimized code " + updatedPackages); + pinnerService.update(updatedPackages); + } + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index b6b28ede86802..addaccee7b1f2 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -9132,9 +9132,20 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean performDexOpt(String packageName, boolean checkProfiles, int compileReason, boolean force) { - int dexOptStatus = performDexOptTraced(packageName, checkProfiles, + return performDexOptWithStatus(packageName, checkProfiles, compileReason, force) != + PackageDexOptimizer.DEX_OPT_FAILED; + } + + /** + * Perform dexopt on the given package and return one of following result: + * {@link PackageDexOptimizer#DEX_OPT_SKIPPED} + * {@link PackageDexOptimizer#DEX_OPT_PERFORMED} + * {@link PackageDexOptimizer#DEX_OPT_FAILED} + */ + /* package */ int performDexOptWithStatus(String packageName, + boolean checkProfiles, int compileReason, boolean force) { + return performDexOptTraced(packageName, checkProfiles, getCompilerFilterForReason(compileReason), force); - return dexOptStatus != PackageDexOptimizer.DEX_OPT_FAILED; } @Override