Merge changes I87740397,I0cc4538b,Iaceb2b7c

* changes:
  Wait for BOOT_COMPLETE event before scheduling the bootDexoptJob
  Use BatteryManagerInternal to determine low battery.
  BackgroundDexOptService: defer post-boot job further
This commit is contained in:
Treehugger Robot
2021-05-11 16:18:00 +00:00
committed by Gerrit Code Review

View File

@@ -16,7 +16,6 @@
package com.android.server.pm; package com.android.server.pm;
import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import android.annotation.Nullable; import android.annotation.Nullable;
@@ -24,12 +23,13 @@ import android.app.job.JobInfo;
import android.app.job.JobParameters; import android.app.job.JobParameters;
import android.app.job.JobScheduler; import android.app.job.JobScheduler;
import android.app.job.JobService; import android.app.job.JobService;
import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.os.BatteryManager; import android.os.BatteryManagerInternal;
import android.os.Environment; import android.os.Environment;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.SystemProperties; import android.os.SystemProperties;
@@ -37,6 +37,7 @@ import android.os.UserHandle;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import android.util.Slog;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.FrameworkStatsLog;
@@ -65,9 +66,7 @@ public class BackgroundDexOptService extends JobService {
private static final int JOB_IDLE_OPTIMIZE = 800; private static final int JOB_IDLE_OPTIMIZE = 800;
private static final int JOB_POST_BOOT_UPDATE = 801; private static final int JOB_POST_BOOT_UPDATE = 801;
private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG private static final long IDLE_OPTIMIZATION_PERIOD = TimeUnit.DAYS.toMillis(1);
? TimeUnit.MINUTES.toMillis(1)
: TimeUnit.DAYS.toMillis(1);
private static ComponentName sDexoptServiceName = new ComponentName( private static ComponentName sDexoptServiceName = new ComponentName(
"android", "android",
@@ -115,14 +114,24 @@ public class BackgroundDexOptService extends JobService {
return; return;
} }
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); final JobScheduler js = context.getSystemService(JobScheduler.class);
// Schedule a one-off job which scans installed packages and updates // Schedule a one-off job which scans installed packages and updates
// out-of-date oat files. // out-of-date oat files. Schedule it 10 minutes after the boot complete event,
js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName) // so that we don't overload the boot with additional dex2oat compilations.
.setMinimumLatency(TimeUnit.MINUTES.toMillis(1)) context.registerReceiver(new BroadcastReceiver() {
.setOverrideDeadline(TimeUnit.MINUTES.toMillis(1)) @Override
.build()); public void onReceive(Context context, Intent intent) {
js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName)
.setMinimumLatency(TimeUnit.MINUTES.toMillis(10))
.setOverrideDeadline(TimeUnit.MINUTES.toMillis(60))
.build());
context.unregisterReceiver(this);
if (DEBUG) {
Slog.i(TAG, "BootBgDexopt scheduled");
}
}
}, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
// Schedule a daily job which scans installed packages and compiles // Schedule a daily job which scans installed packages and compiles
// those with fresh profiling data. // those with fresh profiling data.
@@ -132,8 +141,8 @@ public class BackgroundDexOptService extends JobService {
.setPeriodic(IDLE_OPTIMIZATION_PERIOD) .setPeriodic(IDLE_OPTIMIZATION_PERIOD)
.build()); .build());
if (DEBUG_DEXOPT) { if (DEBUG) {
Log.i(TAG, "Jobs scheduled"); Slog.d(TAG, "BgDexopt scheduled");
} }
} }
@@ -149,32 +158,11 @@ public class BackgroundDexOptService extends JobService {
} }
} }
// Returns the current battery level as a 0-100 integer.
private int getBatteryLevel() {
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent intent = registerReceiver(null, filter);
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
if (!present) {
// No battery, treat as if 100%, no possibility of draining battery.
return 100;
}
if (level < 0 || scale <= 0) {
// Battery data unavailable. This should never happen, so assume the worst.
return 0;
}
return (100 * level / scale);
}
private long getLowStorageThreshold(Context context) { private long getLowStorageThreshold(Context context) {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
final long lowThreshold = StorageManager.from(context).getStorageLowBytes(mDataDir); final long lowThreshold = StorageManager.from(context).getStorageLowBytes(mDataDir);
if (lowThreshold == 0) { if (lowThreshold == 0) {
Log.e(TAG, "Invalid low storage threshold"); Slog.e(TAG, "Invalid low storage threshold");
} }
return lowThreshold; return lowThreshold;
@@ -198,9 +186,8 @@ public class BackgroundDexOptService extends JobService {
private void postBootUpdate(JobParameters jobParams, PackageManagerService pm, private void postBootUpdate(JobParameters jobParams, PackageManagerService pm,
ArraySet<String> pkgs) { ArraySet<String> pkgs) {
// Load low battery threshold from the system config. This is a 0-100 integer. final BatteryManagerInternal batteryManagerInternal =
final int lowBatteryThreshold = getResources().getInteger( LocalServices.getService(BatteryManagerInternal.class);
com.android.internal.R.integer.config_lowBatteryWarningLevel);
final long lowThreshold = getLowStorageThreshold(this); final long lowThreshold = getLowStorageThreshold(this);
mAbortPostBootUpdate.set(false); mAbortPostBootUpdate.set(false);
@@ -215,20 +202,19 @@ public class BackgroundDexOptService extends JobService {
// Different job, which supersedes this one, is running. // Different job, which supersedes this one, is running.
break; break;
} }
if (getBatteryLevel() < lowBatteryThreshold) { if (batteryManagerInternal.getBatteryLevelLow()) {
// Rather bail than completely drain the battery. // Rather bail than completely drain the battery.
break; break;
} }
long usableSpace = mDataDir.getUsableSpace(); long usableSpace = mDataDir.getUsableSpace();
if (usableSpace < lowThreshold) { if (usableSpace < lowThreshold) {
// Rather bail than completely fill up the disk. // Rather bail than completely fill up the disk.
Log.w(TAG, "Aborting background dex opt job due to low storage: " + Slog.w(TAG, "Aborting background dex opt job due to low storage: " +
usableSpace); usableSpace);
break; break;
} }
if (DEBUG) {
if (DEBUG_DEXOPT) { Slog.i(TAG, "Updating package " + pkg);
Log.i(TAG, "Updating package " + pkg);
} }
// Update package if needed. Note that there can be no race between concurrent // Update package if needed. Note that there can be no race between concurrent
@@ -260,13 +246,13 @@ public class BackgroundDexOptService extends JobService {
public void run() { public void run() {
int result = idleOptimization(pm, pkgs, BackgroundDexOptService.this); int result = idleOptimization(pm, pkgs, BackgroundDexOptService.this);
if (result == OPTIMIZE_PROCESSED) { if (result == OPTIMIZE_PROCESSED) {
Log.i(TAG, "Idle optimizations completed."); Slog.i(TAG, "Idle optimizations completed.");
} else if (result == OPTIMIZE_ABORT_NO_SPACE_LEFT) { } else if (result == OPTIMIZE_ABORT_NO_SPACE_LEFT) {
Log.w(TAG, "Idle optimizations aborted because of space constraints."); Slog.w(TAG, "Idle optimizations aborted because of space constraints.");
} else if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { } else if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
Log.w(TAG, "Idle optimizations aborted by job scheduler."); Slog.w(TAG, "Idle optimizations aborted by job scheduler.");
} else { } else {
Log.w(TAG, "Idle optimizations ended with unexpected code: " + result); Slog.w(TAG, "Idle optimizations ended with unexpected code: " + result);
} }
if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
// Abandon our timeslice and do not reschedule. // Abandon our timeslice and do not reschedule.
@@ -280,7 +266,7 @@ public class BackgroundDexOptService extends JobService {
// Optimize the given packages and return the optimization result (one of the OPTIMIZE_* codes). // Optimize the given packages and return the optimization result (one of the OPTIMIZE_* codes).
private int idleOptimization(PackageManagerService pm, ArraySet<String> pkgs, private int idleOptimization(PackageManagerService pm, ArraySet<String> pkgs,
Context context) { Context context) {
Log.i(TAG, "Performing idle optimizations"); Slog.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);
@@ -355,11 +341,15 @@ public class BackgroundDexOptService extends JobService {
final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE
* lowStorageThreshold; * lowStorageThreshold;
boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade); boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade);
Log.d(TAG, "Should Downgrade " + shouldDowngrade); if (DEBUG) {
Slog.d(TAG, "Should Downgrade " + shouldDowngrade);
}
if (shouldDowngrade) { if (shouldDowngrade) {
Set<String> unusedPackages = Set<String> unusedPackages =
pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis); pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
Log.d(TAG, "Unsused Packages " + String.join(",", unusedPackages)); if (DEBUG) {
Slog.d(TAG, "Unsused Packages " + String.join(",", unusedPackages));
}
if (!unusedPackages.isEmpty()) { if (!unusedPackages.isEmpty()) {
for (String pkg : unusedPackages) { for (String pkg : unusedPackages) {
@@ -431,7 +421,9 @@ public class BackgroundDexOptService extends JobService {
*/ */
private boolean downgradePackage(PackageManagerService pm, String pkg, private boolean downgradePackage(PackageManagerService pm, String pkg,
boolean isForPrimaryDex) { boolean isForPrimaryDex) {
Log.d(TAG, "Downgrading " + pkg); if (DEBUG) {
Slog.d(TAG, "Downgrading " + pkg);
}
boolean dex_opt_performed = false; boolean dex_opt_performed = false;
int reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE; int reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE;
int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
@@ -553,7 +545,7 @@ public class BackgroundDexOptService extends JobService {
long usableSpace = mDataDir.getUsableSpace(); long usableSpace = mDataDir.getUsableSpace();
if (usableSpace < lowStorageThreshold) { if (usableSpace < lowStorageThreshold) {
// Rather bail than completely fill up the disk. // Rather bail than completely fill up the disk.
Log.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace); Slog.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace);
return OPTIMIZE_ABORT_NO_SPACE_LEFT; return OPTIMIZE_ABORT_NO_SPACE_LEFT;
} }
@@ -592,8 +584,8 @@ public class BackgroundDexOptService extends JobService {
@Override @Override
public boolean onStartJob(JobParameters params) { public boolean onStartJob(JobParameters params) {
if (DEBUG_DEXOPT) { if (DEBUG) {
Log.i(TAG, "onStartJob"); Slog.i(TAG, "onStartJob");
} }
// NOTE: PackageManagerService.isStorageLow uses a different set of criteria from // NOTE: PackageManagerService.isStorageLow uses a different set of criteria from
@@ -601,17 +593,13 @@ public class BackgroundDexOptService extends JobService {
// restart with a period of ~1 minute. // restart with a period of ~1 minute.
PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package"); PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
if (pm.isStorageLow()) { if (pm.isStorageLow()) {
if (DEBUG_DEXOPT) { Slog.i(TAG, "Low storage, skipping this run");
Log.i(TAG, "Low storage, skipping this run");
}
return false; return false;
} }
final ArraySet<String> pkgs = pm.getOptimizablePackages(); final ArraySet<String> pkgs = pm.getOptimizablePackages();
if (pkgs.isEmpty()) { if (pkgs.isEmpty()) {
if (DEBUG_DEXOPT) { Slog.i(TAG, "No packages to optimize");
Log.i(TAG, "No packages to optimize");
}
return false; return false;
} }
@@ -627,8 +615,8 @@ public class BackgroundDexOptService extends JobService {
@Override @Override
public boolean onStopJob(JobParameters params) { public boolean onStopJob(JobParameters params) {
if (DEBUG_DEXOPT) { if (DEBUG) {
Log.i(TAG, "onStopJob"); Slog.d(TAG, "onStopJob");
} }
if (params.getJobId() == JOB_POST_BOOT_UPDATE) { if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
@@ -649,7 +637,7 @@ public class BackgroundDexOptService extends JobService {
private void notifyPinService(ArraySet<String> updatedPackages) { private void notifyPinService(ArraySet<String> updatedPackages) {
PinnerService pinnerService = LocalServices.getService(PinnerService.class); PinnerService pinnerService = LocalServices.getService(PinnerService.class);
if (pinnerService != null) { if (pinnerService != null) {
Log.i(TAG, "Pinning optimized code " + updatedPackages); Slog.i(TAG, "Pinning optimized code " + updatedPackages);
pinnerService.update(updatedPackages, false /* force */); pinnerService.update(updatedPackages, false /* force */);
} }
} }
@@ -684,7 +672,7 @@ public class BackgroundDexOptService extends JobService {
final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days"; final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days";
String sysPropValue = SystemProperties.get(sysPropKey); String sysPropValue = SystemProperties.get(sysPropKey);
if (sysPropValue == null || sysPropValue.isEmpty()) { if (sysPropValue == null || sysPropValue.isEmpty()) {
Log.w(TAG, "SysProp " + sysPropKey + " not set"); Slog.w(TAG, "SysProp " + sysPropKey + " not set");
return Long.MAX_VALUE; return Long.MAX_VALUE;
} }
return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue)); return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));