diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index d27b0df08b18e..46b981ecf3555 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -509,6 +509,11 @@ interface IPackageManager { void forceDexOpt(String packageName); + /** + * Execute the background dexopt job immediately. + */ + boolean runBackgroundDexoptJob(); + /** * Reconcile the information we have about the secondary dex files belonging to * {@code packagName} and the actual dex files. For all dex files that were diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 28151abe9a6b5..a2f29c9e48fa1 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -280,6 +280,17 @@ public class BackgroundDexOptService extends JobService { return false; } + /** + * Execute the idle optimizations immediately. + */ + public static boolean runIdleOptimizationsNow(PackageManagerService pm, Context context) { + // Create a new object to make sure we don't interfere with the scheduled jobs. + // Note that this may still run at the same time with the job scheduled by the + // JobScheduler but the scheduler will not be able to cancel it. + BackgroundDexOptService bdos = new BackgroundDexOptService(); + return bdos.idleOptimization(pm, pm.getOptimizablePackages(), context); + } + @Override public boolean onStartJob(JobParameters params) { if (DEBUG_DEXOPT) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0fefcf52318ea..e57121e2c12cf 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -7559,6 +7559,14 @@ public class PackageManagerService extends IPackageManager.Stub { mDexManager.reconcileSecondaryDexFiles(packageName); } + /** + * Execute the background dexopt job immediately. + */ + @Override + public boolean runBackgroundDexoptJob() { + return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext); + } + Collection findSharedNonSystemLibraries(PackageParser.Package p) { if (p.usesLibraries != null || p.usesOptionalLibraries != null) { ArrayList retValue = new ArrayList<>(); diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index b234848101853..1bfc157e1ff84 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -112,6 +112,8 @@ class PackageManagerShellCommand extends ShellCommand { return runCompile(); case "reconcile-secondary-dex-files": return runreconcileSecondaryDexFiles(); + case "bg-dexopt-job": + return runDexoptJob(); case "dump-profiles": return runDumpProfiles(); case "list": @@ -431,6 +433,11 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } + private int runDexoptJob() throws RemoteException { + boolean result = mInterface.runBackgroundDexoptJob(); + return result ? 0 : -1; + } + private int runDumpProfiles() throws RemoteException { String packageName = getNextArg(); mInterface.dumpProfiles(packageName); @@ -1463,7 +1470,13 @@ class PackageManagerShellCommand extends ShellCommand { } pw.println(" --reset: restore package to its post-install state"); pw.println(" --check-prof (true | false): look at profiles when doing dexopt?"); - pw.println(" --secondary-dex: copmile app secondary dex files"); + pw.println(" --secondary-dex: compile app secondary dex files"); + pw.println(" bg-dexopt-job"); + pw.println(" Execute the background optimizations immediately."); + pw.println(" Note that the command only runs the background optimizer logic. It may"); + pw.println(" overlap with the actual job but the job scheduler will not be able to"); + pw.println(" cancel it. It will also run even if the device is not in the idle"); + pw.println(" maintenance mode."); pw.println(" list features"); pw.println(" Prints all features of the system."); pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");