Some refactoring in BackgroundDexOptService.
Extract postOta/idle optimizations in their own method.
In preparation for adding the logic to handle secondary dex files.
Test: device boots, pacakges get compiled
Bug: 32871170
(cherry picked from commit be6a71a0b3)
Change-Id: Ie6cdd8461e7214f5de68bc9172f4171ebf72aa39
This commit is contained in:
@@ -69,7 +69,7 @@ public class BackgroundDexOptService extends JobService {
|
|||||||
*/
|
*/
|
||||||
final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
|
final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
|
||||||
|
|
||||||
private final File dataDir = Environment.getDataDirectory();
|
private final File mDataDir = Environment.getDataDirectory();
|
||||||
|
|
||||||
public static void schedule(Context context) {
|
public static void schedule(Context context) {
|
||||||
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
||||||
@@ -120,7 +120,7 @@ public class BackgroundDexOptService extends JobService {
|
|||||||
|
|
||||||
private long getLowStorageThreshold() {
|
private long getLowStorageThreshold() {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
final long lowThreshold = StorageManager.from(this).getStorageLowBytes(dataDir);
|
final long lowThreshold = StorageManager.from(this).getStorageLowBytes(mDataDir);
|
||||||
if (lowThreshold == 0) {
|
if (lowThreshold == 0) {
|
||||||
Log.e(TAG, "Invalid low storage threshold");
|
Log.e(TAG, "Invalid low storage threshold");
|
||||||
}
|
}
|
||||||
@@ -134,114 +134,126 @@ public class BackgroundDexOptService extends JobService {
|
|||||||
// This job has already been superseded. Do not start it.
|
// This job has already been superseded. Do not start it.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load low battery threshold from the system config. This is a 0-100 integer.
|
|
||||||
final int lowBatteryThreshold = getResources().getInteger(
|
|
||||||
com.android.internal.R.integer.config_lowBatteryWarningLevel);
|
|
||||||
|
|
||||||
final long lowThreshold = getLowStorageThreshold();
|
|
||||||
|
|
||||||
mAbortPostBootUpdate.set(false);
|
|
||||||
new Thread("BackgroundDexOptService_PostBootUpdate") {
|
new Thread("BackgroundDexOptService_PostBootUpdate") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (String pkg : pkgs) {
|
postBootUpdate(jobParams, pm, pkgs);
|
||||||
if (mAbortPostBootUpdate.get()) {
|
}
|
||||||
// JobScheduler requested an early abort.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mExitPostBootUpdate.get()) {
|
|
||||||
// Different job, which supersedes this one, is running.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (getBatteryLevel() < lowBatteryThreshold) {
|
|
||||||
// Rather bail than completely drain the battery.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
long usableSpace = dataDir.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG_DEXOPT) {
|
}.start();
|
||||||
Log.i(TAG, "Updating package " + pkg);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update package if needed. Note that there can be no race between concurrent
|
private void postBootUpdate(JobParameters jobParams, PackageManagerService pm,
|
||||||
// jobs because PackageDexOptimizer.performDexOpt is synchronized.
|
ArraySet<String> pkgs) {
|
||||||
|
// Load low battery threshold from the system config. This is a 0-100 integer.
|
||||||
|
final int lowBatteryThreshold = getResources().getInteger(
|
||||||
|
com.android.internal.R.integer.config_lowBatteryWarningLevel);
|
||||||
|
final long lowThreshold = getLowStorageThreshold();
|
||||||
|
|
||||||
// checkProfiles is false to avoid merging profiles during boot which
|
mAbortPostBootUpdate.set(false);
|
||||||
// might interfere with background compilation (b/28612421).
|
|
||||||
// Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
|
for (String pkg : pkgs) {
|
||||||
// behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
|
if (mAbortPostBootUpdate.get()) {
|
||||||
// trade-off worth doing to save boot time work.
|
// JobScheduler requested an early abort.
|
||||||
pm.performDexOpt(pkg,
|
return;
|
||||||
/* checkProfiles */ false,
|
}
|
||||||
PackageManagerService.REASON_BOOT,
|
if (mExitPostBootUpdate.get()) {
|
||||||
/* force */ false);
|
// Different job, which supersedes this one, is running.
|
||||||
}
|
break;
|
||||||
// Ran to completion, so we abandon our timeslice and do not reschedule.
|
}
|
||||||
jobFinished(jobParams, /* reschedule */ false);
|
if (getBatteryLevel() < lowBatteryThreshold) {
|
||||||
|
// Rather bail than completely drain the battery.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG_DEXOPT) {
|
||||||
|
Log.i(TAG, "Updating package " + pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update package if needed. Note that there can be no race between concurrent
|
||||||
|
// jobs because PackageDexOptimizer.performDexOpt is synchronized.
|
||||||
|
|
||||||
|
// checkProfiles is false to avoid merging profiles during boot which
|
||||||
|
// might interfere with background compilation (b/28612421).
|
||||||
|
// 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,
|
||||||
|
/* checkProfiles */ false,
|
||||||
|
PackageManagerService.REASON_BOOT,
|
||||||
|
/* force */ false);
|
||||||
|
}
|
||||||
|
// Ran to completion, so we abandon our timeslice and do not reschedule.
|
||||||
|
jobFinished(jobParams, /* reschedule */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean runIdleOptimization(final JobParameters jobParams,
|
||||||
|
final PackageManagerService pm, final ArraySet<String> pkgs) {
|
||||||
|
new Thread("BackgroundDexOptService_IdleOptimization") {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
idleOptimization(jobParams, pm, pkgs);
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean runIdleOptimization(final JobParameters jobParams,
|
private void idleOptimization(JobParameters jobParams, PackageManagerService pm,
|
||||||
final PackageManagerService pm, final ArraySet<String> pkgs) {
|
ArraySet<String> pkgs) {
|
||||||
// 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();
|
final long lowThreshold = getLowStorageThreshold();
|
||||||
|
for (String pkg : pkgs) {
|
||||||
new Thread("BackgroundDexOptService_IdleOptimization") {
|
if (mAbortIdleOptimization.get()) {
|
||||||
@Override
|
// JobScheduler requested an early abort.
|
||||||
public void run() {
|
return;
|
||||||
for (String pkg : pkgs) {
|
|
||||||
if (mAbortIdleOptimization.get()) {
|
|
||||||
// JobScheduler requested an early abort.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sFailedPackageNames.contains(pkg)) {
|
|
||||||
// Skip previously failing package
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
long usableSpace = dataDir.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
|
|
||||||
// concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
|
|
||||||
if (pm.performDexOpt(pkg,
|
|
||||||
/* checkProfiles */ true,
|
|
||||||
PackageManagerService.REASON_BACKGROUND_DEXOPT,
|
|
||||||
/* force */ false)) {
|
|
||||||
// Dexopt succeeded, remove package from the list of failing ones.
|
|
||||||
synchronized (sFailedPackageNames) {
|
|
||||||
sFailedPackageNames.remove(pkg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Ran to completion, so we abandon our timeslice and do not reschedule.
|
|
||||||
jobFinished(jobParams, /* reschedule */ false);
|
|
||||||
}
|
}
|
||||||
}.start();
|
|
||||||
return true;
|
synchronized (sFailedPackageNames) {
|
||||||
|
if (sFailedPackageNames.contains(pkg)) {
|
||||||
|
// Skip previously failing package
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
// concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
|
||||||
|
if (pm.performDexOpt(pkg,
|
||||||
|
/* checkProfiles */ true,
|
||||||
|
PackageManagerService.REASON_BACKGROUND_DEXOPT,
|
||||||
|
/* force */ false)) {
|
||||||
|
// Dexopt succeeded, remove package from the list of failing ones.
|
||||||
|
synchronized (sFailedPackageNames) {
|
||||||
|
sFailedPackageNames.remove(pkg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ran to completion, so we abandon our timeslice and do not reschedule.
|
||||||
|
jobFinished(jobParams, /* reschedule */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user