Loading core/java/com/android/internal/util/FunctionalUtils.java +13 −0 Original line number Diff line number Diff line Loading @@ -247,6 +247,19 @@ public class FunctionalUtils { } } /** * A {@link Supplier} that allows the caller to specify a custom checked {@link Exception} that * can be thrown by the implementer. This is usually used when proxying/wrapping calls between * different classes. * * @param <Output> Method return type * @param <ExceptionType> Checked exception type */ @FunctionalInterface public interface ThrowingCheckedSupplier<Output, ExceptionType extends Exception> { Output get() throws ExceptionType; } /** * A {@link Consumer} that allows the caller to specify a custom checked {@link Exception} that * can be thrown by the implementer. This is usually used when proxying/wrapping calls between Loading services/core/java/com/android/server/pm/AppDataHelper.java +44 −28 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.pm; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static com.android.server.pm.DexOptHelper.useArtService; import static com.android.server.pm.PackageManagerService.TAG; import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; Loading Loading @@ -45,6 +46,7 @@ import android.util.TimingsTraceLog; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.android.server.SystemServerInitThreadPool; import com.android.server.pm.Installer.LegacyDexoptDisabledException; import com.android.server.pm.dex.ArtManagerService; import com.android.server.pm.parsing.pkg.AndroidPackageUtils; import com.android.server.pm.pkg.AndroidPackage; Loading Loading @@ -242,6 +244,7 @@ public class AppDataHelper { } } if (!useArtService()) { // ART Service handles this on demand instead. // Prepare the application profiles only for upgrades and // first boot (so that we don't repeat the same operation at // each boot). Loading @@ -267,8 +270,13 @@ public class AppDataHelper { // profiles. if (mPm.isDeviceUpgrading() || mPm.isFirstBoot() || (userId != UserHandle.USER_SYSTEM)) { try { mArtManagerService.prepareAppProfiles(pkg, userId, /* updateReferenceProfileContent= */ false); } catch (LegacyDexoptDisabledException e2) { throw new RuntimeException(e2); } } } if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) { Loading Loading @@ -578,7 +586,12 @@ public class AppDataHelper { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } // TODO(b/251903639): Call into ART Service. try { mArtManagerService.clearAppProfiles(pkg); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } } public void destroyAppDataLIF(AndroidPackage pkg, int userId, int flags) { Loading Loading @@ -615,8 +628,11 @@ public class AppDataHelper { } private void destroyAppProfilesLeafLIF(AndroidPackage pkg) { // TODO(b/251903639): Call into ART Service. try { mInstaller.destroyAppProfiles(pkg.getPackageName()); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } catch (Installer.InstallerException e) { Slog.w(TAG, String.valueOf(e)); } Loading services/core/java/com/android/server/pm/BackgroundDexOptService.java +85 −56 Original line number Diff line number Diff line Loading @@ -55,9 +55,11 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.FunctionalUtils.ThrowingCheckedSupplier; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.PinnerService; import com.android.server.pm.Installer.LegacyDexoptDisabledException; import com.android.server.pm.PackageDexOptimizer.DexOptResult; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; Loading @@ -71,7 +73,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; /** * Controls background dex optimization run as idle job or command line. Loading Loading @@ -202,7 +203,8 @@ public final class BackgroundDexOptService { } /** Start scheduling job after boot completion */ public void systemReady() { public void systemReady() throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); if (mInjector.isBackgroundDexOptDisabled()) { return; } Loading Loading @@ -272,7 +274,8 @@ public final class BackgroundDexOptService { * @return true if dex optimization is complete. false if the task is cancelled or if there was * an error. */ public boolean runBackgroundDexoptJob(@Nullable List<String> packageNames) { public boolean runBackgroundDexoptJob(@Nullable List<String> packageNames) throws LegacyDexoptDisabledException { enforceRootOrShell(); long identity = Binder.clearCallingIdentity(); try { Loading Loading @@ -301,7 +304,8 @@ public final class BackgroundDexOptService { * * <p>This is only for shell command and only root or shell user can use this. */ public void cancelBackgroundDexoptJob() { public void cancelBackgroundDexoptJob() throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); enforceRootOrShell(); Binder.withCleanCallingIdentity(() -> cancelDexOptAndWaitForCompletion()); } Loading @@ -315,7 +319,8 @@ public final class BackgroundDexOptService { * * @param disable True if JobScheduler invocations should be disabled, false otherwise. */ public void setDisableJobSchedulerJobs(boolean disable) { public void setDisableJobSchedulerJobs(boolean disable) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); enforceRootOrShell(); synchronized (mLock) { mDisableJobSchedulerJobs = disable; Loading @@ -323,14 +328,18 @@ public final class BackgroundDexOptService { } /** Adds listener for package update */ public void addPackagesUpdatedListener(PackagesUpdatedListener listener) { public void addPackagesUpdatedListener(PackagesUpdatedListener listener) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); synchronized (mLock) { mPackagesUpdatedListeners.add(listener); } } /** Removes package update listener */ public void removePackagesUpdatedListener(PackagesUpdatedListener listener) { public void removePackagesUpdatedListener(PackagesUpdatedListener listener) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); synchronized (mLock) { mPackagesUpdatedListeners.remove(listener); } Loading @@ -340,7 +349,8 @@ public final class BackgroundDexOptService { * Notifies package change and removes the package from the failed package list so that * the package can run dexopt again. */ public void notifyPackageChanged(String packageName) { public void notifyPackageChanged(String packageName) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); // The idle maintenance job skips packages which previously failed to // compile. The given package has changed and may successfully compile // now. Remove it from the list of known failing packages. Loading Loading @@ -387,6 +397,7 @@ public final class BackgroundDexOptService { // Post boot job not finished yet. Run post boot job first. return false; } try { resetStatesForNewDexOptRunLocked(mInjector.createAndStartThread( "BackgroundDexOptService_" + (isPostBootUpdateJob ? "PostBoot" : "Idle"), () -> { Loading @@ -397,6 +408,8 @@ public final class BackgroundDexOptService { try { completed = runIdleOptimization( pm, pkgs, params.getJobId() == JOB_POST_BOOT_UPDATE); } catch (LegacyDexoptDisabledException e) { Slog.wtf(TAG, e); } finally { // Those cleanup should be done always. tr.traceEnd(); Slog.i(TAG, Loading @@ -418,6 +431,9 @@ public final class BackgroundDexOptService { markDexOptCompleted(); } })); } catch (LegacyDexoptDisabledException e) { Slog.wtf(TAG, e); } } return true; } Loading @@ -425,11 +441,16 @@ public final class BackgroundDexOptService { /** For BackgroundDexOptJobService to dispatch onStopJob event */ /* package */ boolean onStopJob(BackgroundDexOptJobService job, JobParameters params) { Slog.i(TAG, "onStopJob:" + params.getJobId()); // This cannot block as it is in main thread, thus dispatch to a newly created thread and // cancel it from there. // As this event does not happen often, creating a new thread is justified rather than // having one thread kept permanently. mInjector.createAndStartThread("DexOptCancel", this::cancelDexOptAndWaitForCompletion); // This cannot block as it is in main thread, thus dispatch to a newly created thread // and cancel it from there. As this event does not happen often, creating a new thread // is justified rather than having one thread kept permanently. mInjector.createAndStartThread("DexOptCancel", () -> { try { cancelDexOptAndWaitForCompletion(); } catch (LegacyDexoptDisabledException e) { Slog.wtf(TAG, e); } }); // Always reschedule for cancellation. return true; } Loading @@ -438,7 +459,7 @@ public final class BackgroundDexOptService { * Cancels pending dexopt and wait for completion of the cancellation. This can block the caller * until cancellation is done. */ private void cancelDexOptAndWaitForCompletion() { private void cancelDexOptAndWaitForCompletion() throws LegacyDexoptDisabledException { synchronized (mLock) { if (mDexOptThread == null) { return; Loading Loading @@ -496,7 +517,8 @@ public final class BackgroundDexOptService { } @GuardedBy("mLock") private void resetStatesForNewDexOptRunLocked(Thread thread) { private void resetStatesForNewDexOptRunLocked(Thread thread) throws LegacyDexoptDisabledException { mDexOptThread = thread; mLastCancelledPackages.clear(); controlDexOptBlockingLocked(false); Loading @@ -510,7 +532,7 @@ public final class BackgroundDexOptService { } @GuardedBy("mLock") private void controlDexOptBlockingLocked(boolean block) { private void controlDexOptBlockingLocked(boolean block) throws LegacyDexoptDisabledException { PackageManagerService pm = mInjector.getPackageManagerService(); mDexOptHelper.controlDexOptBlocking(block); } Loading Loading @@ -564,8 +586,8 @@ public final class BackgroundDexOptService { * Returns whether we've successfully run the job. Note that it will return true even if some * packages may have failed compiling. */ private boolean runIdleOptimization( PackageManagerService pm, List<String> pkgs, boolean isPostBootUpdate) { private boolean runIdleOptimization(PackageManagerService pm, List<String> pkgs, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { synchronized (mLock) { mLastExecutionStatus = STATUS_UNSPECIFIED; mLastExecutionStartUptimeMs = SystemClock.uptimeMillis(); Loading Loading @@ -631,7 +653,8 @@ public final class BackgroundDexOptService { @Status private int idleOptimizePackages(PackageManagerService pm, List<String> pkgs, long lowStorageThreshold, boolean isPostBootUpdate) { long lowStorageThreshold, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { ArraySet<String> updatedPackages = new ArraySet<>(); try { Loading Loading @@ -707,7 +730,8 @@ public final class BackgroundDexOptService { @Status private int optimizePackages(List<String> pkgs, long lowStorageThreshold, ArraySet<String> updatedPackages, boolean isPostBootUpdate) { ArraySet<String> updatedPackages, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { boolean supportSecondaryDex = mInjector.supportSecondaryDex(); // Keep the error if there is any error from any package. Loading Loading @@ -760,7 +784,8 @@ public final class BackgroundDexOptService { */ @DexOptResult private int downgradePackage(@NonNull Computer snapshot, PackageManagerService pm, String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) { boolean isForPrimaryDex, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { if (DEBUG) { Slog.d(TAG, "Downgrading " + pkg); } Loading Loading @@ -808,7 +833,7 @@ public final class BackgroundDexOptService { } @Status private int reconcileSecondaryDexFiles() { private int reconcileSecondaryDexFiles() throws LegacyDexoptDisabledException { // TODO(calin): should we denylist packages for which we fail to reconcile? for (String p : mInjector.getDexManager().getAllPackagesWithSecondaryDexFiles()) { if (isCancelling()) { Loading @@ -829,7 +854,8 @@ public final class BackgroundDexOptService { * @return PackageDexOptimizer#DEX_OPT_* */ @DexOptResult private int optimizePackage(String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) { private int optimizePackage(String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { int reason = isPostBootUpdate ? PackageManagerService.REASON_POST_BOOT : PackageManagerService.REASON_BACKGROUND_DEXOPT; String filter = getCompilerFilterForReason(reason); Loading Loading @@ -857,7 +883,8 @@ public final class BackgroundDexOptService { } @DexOptResult private int performDexOptPrimary(String pkg, int reason, String filter, int dexoptFlags) { private int performDexOptPrimary(String pkg, int reason, String filter, int dexoptFlags) throws LegacyDexoptDisabledException { DexoptOptions dexoptOptions = new DexoptOptions(pkg, reason, filter, /*splitName=*/null, dexoptFlags); return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/true, Loading @@ -865,7 +892,8 @@ public final class BackgroundDexOptService { } @DexOptResult private int performDexOptSecondary(String pkg, int reason, String filter, int dexoptFlags) { private int performDexOptSecondary(String pkg, int reason, String filter, int dexoptFlags) throws LegacyDexoptDisabledException { DexoptOptions dexoptOptions = new DexoptOptions(pkg, reason, filter, /*splitName=*/null, dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX); return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/false, Loading @@ -885,8 +913,9 @@ public final class BackgroundDexOptService { * {@link PackageDexOptimizer#DEX_OPT_FAILED} */ @DexOptResult private int trackPerformDexOpt( String pkg, boolean isForPrimaryDex, Supplier<Integer> performDexOptWrapper) { private int trackPerformDexOpt(String pkg, boolean isForPrimaryDex, ThrowingCheckedSupplier<Integer, LegacyDexoptDisabledException> performDexOptWrapper) throws LegacyDexoptDisabledException { ArraySet<String> failedPackageNames; synchronized (mLock) { failedPackageNames = Loading services/core/java/com/android/server/pm/ComputerEngine.java +8 −2 Original line number Diff line number Diff line Loading @@ -124,6 +124,7 @@ import com.android.internal.util.CollectionUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.pm.Installer.LegacyDexoptDisabledException; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.PackageDexUsage; import com.android.server.pm.parsing.PackageInfoUtils; Loading Loading @@ -3009,8 +3010,13 @@ public class ComputerEngine implements Computer { ipw.println("[" + pkgName + "]"); ipw.increaseIndent(); // TODO(b/251903639): Call into ART Service. try { mPackageDexOptimizer.dumpDexoptState(ipw, pkg, pkgSetting, mDexManager.getPackageUseInfoOrDefault(pkgName)); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } ipw.decreaseIndent(); } ipw.println("BgDexopt state:"); Loading services/core/java/com/android/server/pm/DexOptHelper.java +38 −15 Original line number Diff line number Diff line Loading @@ -66,6 +66,8 @@ import com.android.server.art.DexUseManagerLocal; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.OptimizeParams; import com.android.server.art.model.OptimizeResult; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.Installer.LegacyDexoptDisabledException; import com.android.server.pm.PackageDexOptimizer.DexOptResult; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; Loading Loading @@ -125,8 +127,9 @@ public final class DexOptHelper { * and {@code numberOfPackagesFailed}. */ public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates, boolean showDialog, final int compilationReason, boolean bootComplete) { final int compilationReason, boolean bootComplete) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); int numberOfPackagesVisited = 0; int numberOfPackagesOptimized = 0; int numberOfPackagesSkipped = 0; Loading Loading @@ -158,7 +161,7 @@ public final class DexOptHelper { // even if things are already compiled. // useProfileForDexopt = true; } } catch (Exception e) { } catch (InstallerException | RuntimeException e) { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ", e); } Loading Loading @@ -193,7 +196,7 @@ public final class DexOptHelper { } else { useProfileForDexopt = true; } } catch (Exception e) { } catch (InstallerException | RuntimeException e) { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ", e); } Loading Loading @@ -284,7 +287,8 @@ public final class DexOptHelper { * Checks if system UI package (typically "com.android.systemui") needs to be re-compiled, and * compiles it if needed. */ private void checkAndDexOptSystemUi() { private void checkAndDexOptSystemUi() throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); Computer snapshot = mPm.snapshotComputer(); String sysUiPackageName = mPm.mContext.getString(com.android.internal.R.string.config_systemUi); Loading Loading @@ -320,7 +324,7 @@ public final class DexOptHelper { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath()); } } } catch (Exception e) { } catch (InstallerException | RuntimeException e) { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath(), e); } } Loading @@ -341,7 +345,7 @@ public final class DexOptHelper { } @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG) public void performPackageDexOptUpgradeIfNeeded() { public void performPackageDexOptUpgradeIfNeeded() throws LegacyDexoptDisabledException { PackageManagerServiceUtils.enforceSystemOrRoot( "Only the system can request package update"); Loading Loading @@ -413,7 +417,12 @@ public final class DexOptHelper { } if (options.isDexoptOnlySecondaryDex()) { // TODO(b/251903639): Call into ART Service. try { return mPm.getDexManager().dexoptSecondaryDex(options); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } } else { int dexoptStatus = performDexOptWithStatus(options); return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED; Loading Loading @@ -470,6 +479,8 @@ public final class DexOptHelper { final long callingId = Binder.clearCallingIdentity(); try { return performDexOptInternalWithDependenciesLI(p, pkgSetting, options); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } finally { Binder.restoreCallingIdentity(callingId); } Loading Loading @@ -542,7 +553,8 @@ public final class DexOptHelper { @DexOptResult private int performDexOptInternalWithDependenciesLI( AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) { AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) throws LegacyDexoptDisabledException { // System server gets a special path. if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) { return mPm.getDexManager().dexoptSystemServer(options); Loading Loading @@ -621,7 +633,11 @@ public final class DexOptHelper { if (artSrvRes.isPresent()) { res = artSrvRes.get(); } else { try { res = performDexOptInternalWithDependenciesLI(pkg, packageState, options); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Loading Loading @@ -666,8 +682,8 @@ public final class DexOptHelper { return installerPkg.getUid() == Binder.getCallingUid(); } public boolean performDexOptSecondary(String packageName, String compilerFilter, boolean force) { public boolean performDexOptSecondary( String packageName, String compilerFilter, boolean force) { int flags = DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX | DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES | DexoptOptions.DEXOPT_BOOT_COMPLETE Loading Loading @@ -869,7 +885,7 @@ public final class DexOptHelper { } } /*package*/ void controlDexOptBlocking(boolean block) { /*package*/ void controlDexOptBlocking(boolean block) throws LegacyDexoptDisabledException { mPm.mPackageDexOptimizer.controlDexOptBlocking(block); } Loading Loading @@ -928,11 +944,18 @@ public final class DexOptHelper { Slog.i(TAG, "Falling back to old PackageManager dexopt for " + packageName + ": " + reason); } /** * Returns true if ART Service should be used for package optimization. */ public static boolean useArtService() { return SystemProperties.getBoolean("dalvik.vm.useartservice", false); } /** * Returns {@link DexUseManagerLocal} if ART Service should be used for package optimization. */ public static @Nullable DexUseManagerLocal getDexUseManagerLocal() { if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) { if (!useArtService()) { return null; } try { Loading @@ -946,7 +969,7 @@ public final class DexOptHelper { * Returns {@link ArtManagerLocal} if ART Service should be used for package optimization. */ private static @Nullable ArtManagerLocal getArtManagerLocal() { if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) { if (!useArtService()) { return null; } try { Loading Loading
core/java/com/android/internal/util/FunctionalUtils.java +13 −0 Original line number Diff line number Diff line Loading @@ -247,6 +247,19 @@ public class FunctionalUtils { } } /** * A {@link Supplier} that allows the caller to specify a custom checked {@link Exception} that * can be thrown by the implementer. This is usually used when proxying/wrapping calls between * different classes. * * @param <Output> Method return type * @param <ExceptionType> Checked exception type */ @FunctionalInterface public interface ThrowingCheckedSupplier<Output, ExceptionType extends Exception> { Output get() throws ExceptionType; } /** * A {@link Consumer} that allows the caller to specify a custom checked {@link Exception} that * can be thrown by the implementer. This is usually used when proxying/wrapping calls between Loading
services/core/java/com/android/server/pm/AppDataHelper.java +44 −28 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.pm; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static com.android.server.pm.DexOptHelper.useArtService; import static com.android.server.pm.PackageManagerService.TAG; import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; Loading Loading @@ -45,6 +46,7 @@ import android.util.TimingsTraceLog; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.android.server.SystemServerInitThreadPool; import com.android.server.pm.Installer.LegacyDexoptDisabledException; import com.android.server.pm.dex.ArtManagerService; import com.android.server.pm.parsing.pkg.AndroidPackageUtils; import com.android.server.pm.pkg.AndroidPackage; Loading Loading @@ -242,6 +244,7 @@ public class AppDataHelper { } } if (!useArtService()) { // ART Service handles this on demand instead. // Prepare the application profiles only for upgrades and // first boot (so that we don't repeat the same operation at // each boot). Loading @@ -267,8 +270,13 @@ public class AppDataHelper { // profiles. if (mPm.isDeviceUpgrading() || mPm.isFirstBoot() || (userId != UserHandle.USER_SYSTEM)) { try { mArtManagerService.prepareAppProfiles(pkg, userId, /* updateReferenceProfileContent= */ false); } catch (LegacyDexoptDisabledException e2) { throw new RuntimeException(e2); } } } if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) { Loading Loading @@ -578,7 +586,12 @@ public class AppDataHelper { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } // TODO(b/251903639): Call into ART Service. try { mArtManagerService.clearAppProfiles(pkg); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } } public void destroyAppDataLIF(AndroidPackage pkg, int userId, int flags) { Loading Loading @@ -615,8 +628,11 @@ public class AppDataHelper { } private void destroyAppProfilesLeafLIF(AndroidPackage pkg) { // TODO(b/251903639): Call into ART Service. try { mInstaller.destroyAppProfiles(pkg.getPackageName()); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } catch (Installer.InstallerException e) { Slog.w(TAG, String.valueOf(e)); } Loading
services/core/java/com/android/server/pm/BackgroundDexOptService.java +85 −56 Original line number Diff line number Diff line Loading @@ -55,9 +55,11 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.FunctionalUtils.ThrowingCheckedSupplier; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.PinnerService; import com.android.server.pm.Installer.LegacyDexoptDisabledException; import com.android.server.pm.PackageDexOptimizer.DexOptResult; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; Loading @@ -71,7 +73,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; /** * Controls background dex optimization run as idle job or command line. Loading Loading @@ -202,7 +203,8 @@ public final class BackgroundDexOptService { } /** Start scheduling job after boot completion */ public void systemReady() { public void systemReady() throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); if (mInjector.isBackgroundDexOptDisabled()) { return; } Loading Loading @@ -272,7 +274,8 @@ public final class BackgroundDexOptService { * @return true if dex optimization is complete. false if the task is cancelled or if there was * an error. */ public boolean runBackgroundDexoptJob(@Nullable List<String> packageNames) { public boolean runBackgroundDexoptJob(@Nullable List<String> packageNames) throws LegacyDexoptDisabledException { enforceRootOrShell(); long identity = Binder.clearCallingIdentity(); try { Loading Loading @@ -301,7 +304,8 @@ public final class BackgroundDexOptService { * * <p>This is only for shell command and only root or shell user can use this. */ public void cancelBackgroundDexoptJob() { public void cancelBackgroundDexoptJob() throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); enforceRootOrShell(); Binder.withCleanCallingIdentity(() -> cancelDexOptAndWaitForCompletion()); } Loading @@ -315,7 +319,8 @@ public final class BackgroundDexOptService { * * @param disable True if JobScheduler invocations should be disabled, false otherwise. */ public void setDisableJobSchedulerJobs(boolean disable) { public void setDisableJobSchedulerJobs(boolean disable) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); enforceRootOrShell(); synchronized (mLock) { mDisableJobSchedulerJobs = disable; Loading @@ -323,14 +328,18 @@ public final class BackgroundDexOptService { } /** Adds listener for package update */ public void addPackagesUpdatedListener(PackagesUpdatedListener listener) { public void addPackagesUpdatedListener(PackagesUpdatedListener listener) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); synchronized (mLock) { mPackagesUpdatedListeners.add(listener); } } /** Removes package update listener */ public void removePackagesUpdatedListener(PackagesUpdatedListener listener) { public void removePackagesUpdatedListener(PackagesUpdatedListener listener) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); synchronized (mLock) { mPackagesUpdatedListeners.remove(listener); } Loading @@ -340,7 +349,8 @@ public final class BackgroundDexOptService { * Notifies package change and removes the package from the failed package list so that * the package can run dexopt again. */ public void notifyPackageChanged(String packageName) { public void notifyPackageChanged(String packageName) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); // The idle maintenance job skips packages which previously failed to // compile. The given package has changed and may successfully compile // now. Remove it from the list of known failing packages. Loading Loading @@ -387,6 +397,7 @@ public final class BackgroundDexOptService { // Post boot job not finished yet. Run post boot job first. return false; } try { resetStatesForNewDexOptRunLocked(mInjector.createAndStartThread( "BackgroundDexOptService_" + (isPostBootUpdateJob ? "PostBoot" : "Idle"), () -> { Loading @@ -397,6 +408,8 @@ public final class BackgroundDexOptService { try { completed = runIdleOptimization( pm, pkgs, params.getJobId() == JOB_POST_BOOT_UPDATE); } catch (LegacyDexoptDisabledException e) { Slog.wtf(TAG, e); } finally { // Those cleanup should be done always. tr.traceEnd(); Slog.i(TAG, Loading @@ -418,6 +431,9 @@ public final class BackgroundDexOptService { markDexOptCompleted(); } })); } catch (LegacyDexoptDisabledException e) { Slog.wtf(TAG, e); } } return true; } Loading @@ -425,11 +441,16 @@ public final class BackgroundDexOptService { /** For BackgroundDexOptJobService to dispatch onStopJob event */ /* package */ boolean onStopJob(BackgroundDexOptJobService job, JobParameters params) { Slog.i(TAG, "onStopJob:" + params.getJobId()); // This cannot block as it is in main thread, thus dispatch to a newly created thread and // cancel it from there. // As this event does not happen often, creating a new thread is justified rather than // having one thread kept permanently. mInjector.createAndStartThread("DexOptCancel", this::cancelDexOptAndWaitForCompletion); // This cannot block as it is in main thread, thus dispatch to a newly created thread // and cancel it from there. As this event does not happen often, creating a new thread // is justified rather than having one thread kept permanently. mInjector.createAndStartThread("DexOptCancel", () -> { try { cancelDexOptAndWaitForCompletion(); } catch (LegacyDexoptDisabledException e) { Slog.wtf(TAG, e); } }); // Always reschedule for cancellation. return true; } Loading @@ -438,7 +459,7 @@ public final class BackgroundDexOptService { * Cancels pending dexopt and wait for completion of the cancellation. This can block the caller * until cancellation is done. */ private void cancelDexOptAndWaitForCompletion() { private void cancelDexOptAndWaitForCompletion() throws LegacyDexoptDisabledException { synchronized (mLock) { if (mDexOptThread == null) { return; Loading Loading @@ -496,7 +517,8 @@ public final class BackgroundDexOptService { } @GuardedBy("mLock") private void resetStatesForNewDexOptRunLocked(Thread thread) { private void resetStatesForNewDexOptRunLocked(Thread thread) throws LegacyDexoptDisabledException { mDexOptThread = thread; mLastCancelledPackages.clear(); controlDexOptBlockingLocked(false); Loading @@ -510,7 +532,7 @@ public final class BackgroundDexOptService { } @GuardedBy("mLock") private void controlDexOptBlockingLocked(boolean block) { private void controlDexOptBlockingLocked(boolean block) throws LegacyDexoptDisabledException { PackageManagerService pm = mInjector.getPackageManagerService(); mDexOptHelper.controlDexOptBlocking(block); } Loading Loading @@ -564,8 +586,8 @@ public final class BackgroundDexOptService { * Returns whether we've successfully run the job. Note that it will return true even if some * packages may have failed compiling. */ private boolean runIdleOptimization( PackageManagerService pm, List<String> pkgs, boolean isPostBootUpdate) { private boolean runIdleOptimization(PackageManagerService pm, List<String> pkgs, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { synchronized (mLock) { mLastExecutionStatus = STATUS_UNSPECIFIED; mLastExecutionStartUptimeMs = SystemClock.uptimeMillis(); Loading Loading @@ -631,7 +653,8 @@ public final class BackgroundDexOptService { @Status private int idleOptimizePackages(PackageManagerService pm, List<String> pkgs, long lowStorageThreshold, boolean isPostBootUpdate) { long lowStorageThreshold, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { ArraySet<String> updatedPackages = new ArraySet<>(); try { Loading Loading @@ -707,7 +730,8 @@ public final class BackgroundDexOptService { @Status private int optimizePackages(List<String> pkgs, long lowStorageThreshold, ArraySet<String> updatedPackages, boolean isPostBootUpdate) { ArraySet<String> updatedPackages, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { boolean supportSecondaryDex = mInjector.supportSecondaryDex(); // Keep the error if there is any error from any package. Loading Loading @@ -760,7 +784,8 @@ public final class BackgroundDexOptService { */ @DexOptResult private int downgradePackage(@NonNull Computer snapshot, PackageManagerService pm, String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) { boolean isForPrimaryDex, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { if (DEBUG) { Slog.d(TAG, "Downgrading " + pkg); } Loading Loading @@ -808,7 +833,7 @@ public final class BackgroundDexOptService { } @Status private int reconcileSecondaryDexFiles() { private int reconcileSecondaryDexFiles() throws LegacyDexoptDisabledException { // TODO(calin): should we denylist packages for which we fail to reconcile? for (String p : mInjector.getDexManager().getAllPackagesWithSecondaryDexFiles()) { if (isCancelling()) { Loading @@ -829,7 +854,8 @@ public final class BackgroundDexOptService { * @return PackageDexOptimizer#DEX_OPT_* */ @DexOptResult private int optimizePackage(String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) { private int optimizePackage(String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) throws LegacyDexoptDisabledException { int reason = isPostBootUpdate ? PackageManagerService.REASON_POST_BOOT : PackageManagerService.REASON_BACKGROUND_DEXOPT; String filter = getCompilerFilterForReason(reason); Loading Loading @@ -857,7 +883,8 @@ public final class BackgroundDexOptService { } @DexOptResult private int performDexOptPrimary(String pkg, int reason, String filter, int dexoptFlags) { private int performDexOptPrimary(String pkg, int reason, String filter, int dexoptFlags) throws LegacyDexoptDisabledException { DexoptOptions dexoptOptions = new DexoptOptions(pkg, reason, filter, /*splitName=*/null, dexoptFlags); return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/true, Loading @@ -865,7 +892,8 @@ public final class BackgroundDexOptService { } @DexOptResult private int performDexOptSecondary(String pkg, int reason, String filter, int dexoptFlags) { private int performDexOptSecondary(String pkg, int reason, String filter, int dexoptFlags) throws LegacyDexoptDisabledException { DexoptOptions dexoptOptions = new DexoptOptions(pkg, reason, filter, /*splitName=*/null, dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX); return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/false, Loading @@ -885,8 +913,9 @@ public final class BackgroundDexOptService { * {@link PackageDexOptimizer#DEX_OPT_FAILED} */ @DexOptResult private int trackPerformDexOpt( String pkg, boolean isForPrimaryDex, Supplier<Integer> performDexOptWrapper) { private int trackPerformDexOpt(String pkg, boolean isForPrimaryDex, ThrowingCheckedSupplier<Integer, LegacyDexoptDisabledException> performDexOptWrapper) throws LegacyDexoptDisabledException { ArraySet<String> failedPackageNames; synchronized (mLock) { failedPackageNames = Loading
services/core/java/com/android/server/pm/ComputerEngine.java +8 −2 Original line number Diff line number Diff line Loading @@ -124,6 +124,7 @@ import com.android.internal.util.CollectionUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.pm.Installer.LegacyDexoptDisabledException; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.PackageDexUsage; import com.android.server.pm.parsing.PackageInfoUtils; Loading Loading @@ -3009,8 +3010,13 @@ public class ComputerEngine implements Computer { ipw.println("[" + pkgName + "]"); ipw.increaseIndent(); // TODO(b/251903639): Call into ART Service. try { mPackageDexOptimizer.dumpDexoptState(ipw, pkg, pkgSetting, mDexManager.getPackageUseInfoOrDefault(pkgName)); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } ipw.decreaseIndent(); } ipw.println("BgDexopt state:"); Loading
services/core/java/com/android/server/pm/DexOptHelper.java +38 −15 Original line number Diff line number Diff line Loading @@ -66,6 +66,8 @@ import com.android.server.art.DexUseManagerLocal; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.OptimizeParams; import com.android.server.art.model.OptimizeResult; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.Installer.LegacyDexoptDisabledException; import com.android.server.pm.PackageDexOptimizer.DexOptResult; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; Loading Loading @@ -125,8 +127,9 @@ public final class DexOptHelper { * and {@code numberOfPackagesFailed}. */ public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates, boolean showDialog, final int compilationReason, boolean bootComplete) { final int compilationReason, boolean bootComplete) throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); int numberOfPackagesVisited = 0; int numberOfPackagesOptimized = 0; int numberOfPackagesSkipped = 0; Loading Loading @@ -158,7 +161,7 @@ public final class DexOptHelper { // even if things are already compiled. // useProfileForDexopt = true; } } catch (Exception e) { } catch (InstallerException | RuntimeException e) { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ", e); } Loading Loading @@ -193,7 +196,7 @@ public final class DexOptHelper { } else { useProfileForDexopt = true; } } catch (Exception e) { } catch (InstallerException | RuntimeException e) { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ", e); } Loading Loading @@ -284,7 +287,8 @@ public final class DexOptHelper { * Checks if system UI package (typically "com.android.systemui") needs to be re-compiled, and * compiles it if needed. */ private void checkAndDexOptSystemUi() { private void checkAndDexOptSystemUi() throws LegacyDexoptDisabledException { Installer.checkLegacyDexoptDisabled(); Computer snapshot = mPm.snapshotComputer(); String sysUiPackageName = mPm.mContext.getString(com.android.internal.R.string.config_systemUi); Loading Loading @@ -320,7 +324,7 @@ public final class DexOptHelper { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath()); } } } catch (Exception e) { } catch (InstallerException | RuntimeException e) { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath(), e); } } Loading @@ -341,7 +345,7 @@ public final class DexOptHelper { } @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG) public void performPackageDexOptUpgradeIfNeeded() { public void performPackageDexOptUpgradeIfNeeded() throws LegacyDexoptDisabledException { PackageManagerServiceUtils.enforceSystemOrRoot( "Only the system can request package update"); Loading Loading @@ -413,7 +417,12 @@ public final class DexOptHelper { } if (options.isDexoptOnlySecondaryDex()) { // TODO(b/251903639): Call into ART Service. try { return mPm.getDexManager().dexoptSecondaryDex(options); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } } else { int dexoptStatus = performDexOptWithStatus(options); return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED; Loading Loading @@ -470,6 +479,8 @@ public final class DexOptHelper { final long callingId = Binder.clearCallingIdentity(); try { return performDexOptInternalWithDependenciesLI(p, pkgSetting, options); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } finally { Binder.restoreCallingIdentity(callingId); } Loading Loading @@ -542,7 +553,8 @@ public final class DexOptHelper { @DexOptResult private int performDexOptInternalWithDependenciesLI( AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) { AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) throws LegacyDexoptDisabledException { // System server gets a special path. if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) { return mPm.getDexManager().dexoptSystemServer(options); Loading Loading @@ -621,7 +633,11 @@ public final class DexOptHelper { if (artSrvRes.isPresent()) { res = artSrvRes.get(); } else { try { res = performDexOptInternalWithDependenciesLI(pkg, packageState, options); } catch (LegacyDexoptDisabledException e) { throw new RuntimeException(e); } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Loading Loading @@ -666,8 +682,8 @@ public final class DexOptHelper { return installerPkg.getUid() == Binder.getCallingUid(); } public boolean performDexOptSecondary(String packageName, String compilerFilter, boolean force) { public boolean performDexOptSecondary( String packageName, String compilerFilter, boolean force) { int flags = DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX | DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES | DexoptOptions.DEXOPT_BOOT_COMPLETE Loading Loading @@ -869,7 +885,7 @@ public final class DexOptHelper { } } /*package*/ void controlDexOptBlocking(boolean block) { /*package*/ void controlDexOptBlocking(boolean block) throws LegacyDexoptDisabledException { mPm.mPackageDexOptimizer.controlDexOptBlocking(block); } Loading Loading @@ -928,11 +944,18 @@ public final class DexOptHelper { Slog.i(TAG, "Falling back to old PackageManager dexopt for " + packageName + ": " + reason); } /** * Returns true if ART Service should be used for package optimization. */ public static boolean useArtService() { return SystemProperties.getBoolean("dalvik.vm.useartservice", false); } /** * Returns {@link DexUseManagerLocal} if ART Service should be used for package optimization. */ public static @Nullable DexUseManagerLocal getDexUseManagerLocal() { if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) { if (!useArtService()) { return null; } try { Loading @@ -946,7 +969,7 @@ public final class DexOptHelper { * Returns {@link ArtManagerLocal} if ART Service should be used for package optimization. */ private static @Nullable ArtManagerLocal getArtManagerLocal() { if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) { if (!useArtService()) { return null; } try { Loading