Loading services/core/java/com/android/server/pm/BackgroundDexOptService.java +44 −27 Original line number Original line Diff line number Diff line Loading @@ -124,9 +124,9 @@ public class BackgroundDexOptService extends JobService { return (100 * level / scale); return (100 * level / scale); } } private long getLowStorageThreshold() { private long getLowStorageThreshold(Context context) { @SuppressWarnings("deprecation") @SuppressWarnings("deprecation") final long lowThreshold = StorageManager.from(this).getStorageLowBytes(mDataDir); final long lowThreshold = StorageManager.from(context).getStorageLowBytes(mDataDir); if (lowThreshold == 0) { if (lowThreshold == 0) { Log.e(TAG, "Invalid low storage threshold"); Log.e(TAG, "Invalid low storage threshold"); } } Loading Loading @@ -155,7 +155,7 @@ public class BackgroundDexOptService extends JobService { // Load low battery threshold from the system config. This is a 0-100 integer. // Load low battery threshold from the system config. This is a 0-100 integer. final int lowBatteryThreshold = getResources().getInteger( final int lowBatteryThreshold = getResources().getInteger( com.android.internal.R.integer.config_lowBatteryWarningLevel); com.android.internal.R.integer.config_lowBatteryWarningLevel); final long lowThreshold = getLowStorageThreshold(); final long lowThreshold = getLowStorageThreshold(this); mAbortPostBootUpdate.set(false); mAbortPostBootUpdate.set(false); Loading Loading @@ -206,47 +206,48 @@ public class BackgroundDexOptService extends JobService { new Thread("BackgroundDexOptService_IdleOptimization") { new Thread("BackgroundDexOptService_IdleOptimization") { @Override @Override public void run() { public void run() { idleOptimization(jobParams, pm, pkgs); idleOptimization(pm, pkgs, BackgroundDexOptService.this); if (!mAbortIdleOptimization.get()) { // If we didn't abort we ran to completion (or stopped because of space). // Abandon our timeslice and do not reschedule. jobFinished(jobParams, /* reschedule */ false); } } } }.start(); }.start(); return true; return true; } } private void idleOptimization(JobParameters jobParams, PackageManagerService pm, // Optimize the given packages and return true if the process was not aborted. ArraySet<String> pkgs) { // The abort can happen either because of job scheduler or because of lack of space. private boolean idleOptimization(PackageManagerService pm, ArraySet<String> pkgs, Context context) { Log.i(TAG, "Performing idle optimizations"); Log.i(TAG, "Performing idle optimizations"); // If post-boot update is still running, request that it exits early. // If post-boot update is still running, request that it exits early. mExitPostBootUpdate.set(true); mExitPostBootUpdate.set(true); mAbortIdleOptimization.set(false); mAbortIdleOptimization.set(false); final long lowThreshold = getLowStorageThreshold(); long lowStorageThreshold = getLowStorageThreshold(context); return optimizePackages(pm, pkgs, lowStorageThreshold); } private boolean optimizePackages(PackageManagerService pm, ArraySet<String> pkgs, long lowStorageThreshold) { for (String pkg : pkgs) { for (String pkg : pkgs) { if (mAbortIdleOptimization.get()) { if (abortIdleOptimizations(lowStorageThreshold)) { // JobScheduler requested an early abort. return false; return; } } synchronized (sFailedPackageNames) { synchronized (sFailedPackageNames) { if (sFailedPackageNames.contains(pkg)) { if (sFailedPackageNames.contains(pkg)) { // Skip previously failing package // Skip previously failing package continue; continue; } } else { } long usableSpace = mDataDir.getUsableSpace(); if (usableSpace < lowThreshold) { // Rather bail than completely fill up the disk. Log.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace); break; } // Conservatively add package to the list of failing ones in case performDexOpt // Conservatively add package to the list of failing ones in case performDexOpt // never returns. // never returns. synchronized (sFailedPackageNames) { sFailedPackageNames.add(pkg); sFailedPackageNames.add(pkg); } } } // Optimize package if needed. Note that there can be no race between // Optimize package if needed. Note that there can be no race between // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. if (pm.performDexOpt(pkg, if (pm.performDexOpt(pkg, Loading @@ -259,8 +260,24 @@ public class BackgroundDexOptService extends JobService { } } } } } } // Ran to completion, so we abandon our timeslice and do not reschedule. return true; jobFinished(jobParams, /* reschedule */ false); } // Return true if the idle optimizations should be aborted because of a space constraints // or because the JobScheduler requested so. private boolean abortIdleOptimizations(long lowStorageThreshold) { if (mAbortIdleOptimization.get()) { // JobScheduler requested an early abort. return true; } long usableSpace = mDataDir.getUsableSpace(); if (usableSpace < lowStorageThreshold) { // Rather bail than completely fill up the disk. Log.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace); return true; } return false; } } @Override @Override Loading @@ -281,7 +298,7 @@ public class BackgroundDexOptService extends JobService { } } final ArraySet<String> pkgs = pm.getOptimizablePackages(); final ArraySet<String> pkgs = pm.getOptimizablePackages(); if (pkgs == null || pkgs.isEmpty()) { if (pkgs.isEmpty()) { if (DEBUG_DEXOPT) { if (DEBUG_DEXOPT) { Log.i(TAG, "No packages to optimize"); Log.i(TAG, "No packages to optimize"); } } Loading Loading
services/core/java/com/android/server/pm/BackgroundDexOptService.java +44 −27 Original line number Original line Diff line number Diff line Loading @@ -124,9 +124,9 @@ public class BackgroundDexOptService extends JobService { return (100 * level / scale); return (100 * level / scale); } } private long getLowStorageThreshold() { private long getLowStorageThreshold(Context context) { @SuppressWarnings("deprecation") @SuppressWarnings("deprecation") final long lowThreshold = StorageManager.from(this).getStorageLowBytes(mDataDir); final long lowThreshold = StorageManager.from(context).getStorageLowBytes(mDataDir); if (lowThreshold == 0) { if (lowThreshold == 0) { Log.e(TAG, "Invalid low storage threshold"); Log.e(TAG, "Invalid low storage threshold"); } } Loading Loading @@ -155,7 +155,7 @@ public class BackgroundDexOptService extends JobService { // Load low battery threshold from the system config. This is a 0-100 integer. // Load low battery threshold from the system config. This is a 0-100 integer. final int lowBatteryThreshold = getResources().getInteger( final int lowBatteryThreshold = getResources().getInteger( com.android.internal.R.integer.config_lowBatteryWarningLevel); com.android.internal.R.integer.config_lowBatteryWarningLevel); final long lowThreshold = getLowStorageThreshold(); final long lowThreshold = getLowStorageThreshold(this); mAbortPostBootUpdate.set(false); mAbortPostBootUpdate.set(false); Loading Loading @@ -206,47 +206,48 @@ public class BackgroundDexOptService extends JobService { new Thread("BackgroundDexOptService_IdleOptimization") { new Thread("BackgroundDexOptService_IdleOptimization") { @Override @Override public void run() { public void run() { idleOptimization(jobParams, pm, pkgs); idleOptimization(pm, pkgs, BackgroundDexOptService.this); if (!mAbortIdleOptimization.get()) { // If we didn't abort we ran to completion (or stopped because of space). // Abandon our timeslice and do not reschedule. jobFinished(jobParams, /* reschedule */ false); } } } }.start(); }.start(); return true; return true; } } private void idleOptimization(JobParameters jobParams, PackageManagerService pm, // Optimize the given packages and return true if the process was not aborted. ArraySet<String> pkgs) { // The abort can happen either because of job scheduler or because of lack of space. private boolean idleOptimization(PackageManagerService pm, ArraySet<String> pkgs, Context context) { Log.i(TAG, "Performing idle optimizations"); Log.i(TAG, "Performing idle optimizations"); // If post-boot update is still running, request that it exits early. // If post-boot update is still running, request that it exits early. mExitPostBootUpdate.set(true); mExitPostBootUpdate.set(true); mAbortIdleOptimization.set(false); mAbortIdleOptimization.set(false); final long lowThreshold = getLowStorageThreshold(); long lowStorageThreshold = getLowStorageThreshold(context); return optimizePackages(pm, pkgs, lowStorageThreshold); } private boolean optimizePackages(PackageManagerService pm, ArraySet<String> pkgs, long lowStorageThreshold) { for (String pkg : pkgs) { for (String pkg : pkgs) { if (mAbortIdleOptimization.get()) { if (abortIdleOptimizations(lowStorageThreshold)) { // JobScheduler requested an early abort. return false; return; } } synchronized (sFailedPackageNames) { synchronized (sFailedPackageNames) { if (sFailedPackageNames.contains(pkg)) { if (sFailedPackageNames.contains(pkg)) { // Skip previously failing package // Skip previously failing package continue; continue; } } else { } long usableSpace = mDataDir.getUsableSpace(); if (usableSpace < lowThreshold) { // Rather bail than completely fill up the disk. Log.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace); break; } // Conservatively add package to the list of failing ones in case performDexOpt // Conservatively add package to the list of failing ones in case performDexOpt // never returns. // never returns. synchronized (sFailedPackageNames) { sFailedPackageNames.add(pkg); sFailedPackageNames.add(pkg); } } } // Optimize package if needed. Note that there can be no race between // Optimize package if needed. Note that there can be no race between // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. if (pm.performDexOpt(pkg, if (pm.performDexOpt(pkg, Loading @@ -259,8 +260,24 @@ public class BackgroundDexOptService extends JobService { } } } } } } // Ran to completion, so we abandon our timeslice and do not reschedule. return true; jobFinished(jobParams, /* reschedule */ false); } // Return true if the idle optimizations should be aborted because of a space constraints // or because the JobScheduler requested so. private boolean abortIdleOptimizations(long lowStorageThreshold) { if (mAbortIdleOptimization.get()) { // JobScheduler requested an early abort. return true; } long usableSpace = mDataDir.getUsableSpace(); if (usableSpace < lowStorageThreshold) { // Rather bail than completely fill up the disk. Log.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace); return true; } return false; } } @Override @Override Loading @@ -281,7 +298,7 @@ public class BackgroundDexOptService extends JobService { } } final ArraySet<String> pkgs = pm.getOptimizablePackages(); final ArraySet<String> pkgs = pm.getOptimizablePackages(); if (pkgs == null || pkgs.isEmpty()) { if (pkgs.isEmpty()) { if (DEBUG_DEXOPT) { if (DEBUG_DEXOPT) { Log.i(TAG, "No packages to optimize"); Log.i(TAG, "No packages to optimize"); } } Loading