A bit more refactoring in BackgroundDexOptService

Extract convenient methods to help with:
- adding a shell command to run the background dexopt job
- extending idleOptimizations to cover secondary dex files

Test: device boots, background job run.
Bug: 32871170

(cherry picked from commit c660475aaf)

Change-Id: I146e4faeea90f2d58144a5dba26ae7f90a36b402

Merged-In: I18fde62a1cb05c030a620722d5f217589beaefb1
This commit is contained in:
Calin Juravle
2017-01-25 17:08:03 -08:00
parent e69fba3f7f
commit a57ef16375

View File

@@ -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");
} }
@@ -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);
@@ -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 {
// Conservatively add package to the list of failing ones in case performDexOpt
// never returns.
sFailedPackageNames.add(pkg);
} }
} }
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
// never returns.
synchronized (sFailedPackageNames) {
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,
@@ -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
@@ -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");
} }