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;
import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import android.annotation.Nullable;
@@ -24,12 +23,13 @@ import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.Environment;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -37,6 +37,7 @@ import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import com.android.internal.util.ArrayUtils;
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_POST_BOOT_UPDATE = 801;
private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG
? TimeUnit.MINUTES.toMillis(1)
: TimeUnit.DAYS.toMillis(1);
private static final long IDLE_OPTIMIZATION_PERIOD = TimeUnit.DAYS.toMillis(1);
private static ComponentName sDexoptServiceName = new ComponentName(
"android",
@@ -115,14 +114,24 @@ public class BackgroundDexOptService extends JobService {
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
// out-of-date oat files.
js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName)
.setMinimumLatency(TimeUnit.MINUTES.toMillis(1))
.setOverrideDeadline(TimeUnit.MINUTES.toMillis(1))
.build());
// out-of-date oat files. Schedule it 10 minutes after the boot complete event,
// so that we don't overload the boot with additional dex2oat compilations.
context.registerReceiver(new BroadcastReceiver() {
@Override
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
// those with fresh profiling data.
@@ -132,8 +141,8 @@ public class BackgroundDexOptService extends JobService {
.setPeriodic(IDLE_OPTIMIZATION_PERIOD)
.build());
if (DEBUG_DEXOPT) {
Log.i(TAG, "Jobs scheduled");
if (DEBUG) {
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) {
@SuppressWarnings("deprecation")
final long lowThreshold = StorageManager.from(context).getStorageLowBytes(mDataDir);
if (lowThreshold == 0) {
Log.e(TAG, "Invalid low storage threshold");
Slog.e(TAG, "Invalid low storage threshold");
}
return lowThreshold;
@@ -198,9 +186,8 @@ public class BackgroundDexOptService extends JobService {
private void postBootUpdate(JobParameters jobParams, PackageManagerService pm,
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 BatteryManagerInternal batteryManagerInternal =
LocalServices.getService(BatteryManagerInternal.class);
final long lowThreshold = getLowStorageThreshold(this);
mAbortPostBootUpdate.set(false);
@@ -215,20 +202,19 @@ public class BackgroundDexOptService extends JobService {
// Different job, which supersedes this one, is running.
break;
}
if (getBatteryLevel() < lowBatteryThreshold) {
if (batteryManagerInternal.getBatteryLevelLow()) {
// 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: " +
Slog.w(TAG, "Aborting background dex opt job due to low storage: " +
usableSpace);
break;
}
if (DEBUG_DEXOPT) {
Log.i(TAG, "Updating package " + pkg);
if (DEBUG) {
Slog.i(TAG, "Updating package " + pkg);
}
// 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() {
int result = idleOptimization(pm, pkgs, BackgroundDexOptService.this);
if (result == OPTIMIZE_PROCESSED) {
Log.i(TAG, "Idle optimizations completed.");
Slog.i(TAG, "Idle optimizations completed.");
} 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) {
Log.w(TAG, "Idle optimizations aborted by job scheduler.");
Slog.w(TAG, "Idle optimizations aborted by job scheduler.");
} 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) {
// 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).
private int idleOptimization(PackageManagerService pm, ArraySet<String> pkgs,
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.
mExitPostBootUpdate.set(true);
mAbortIdleOptimization.set(false);
@@ -355,11 +341,15 @@ public class BackgroundDexOptService extends JobService {
final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE
* lowStorageThreshold;
boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade);
Log.d(TAG, "Should Downgrade " + shouldDowngrade);
if (DEBUG) {
Slog.d(TAG, "Should Downgrade " + shouldDowngrade);
}
if (shouldDowngrade) {
Set<String> unusedPackages =
pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
Log.d(TAG, "Unsused Packages " + String.join(",", unusedPackages));
if (DEBUG) {
Slog.d(TAG, "Unsused Packages " + String.join(",", unusedPackages));
}
if (!unusedPackages.isEmpty()) {
for (String pkg : unusedPackages) {
@@ -431,7 +421,9 @@ public class BackgroundDexOptService extends JobService {
*/
private boolean downgradePackage(PackageManagerService pm, String pkg,
boolean isForPrimaryDex) {
Log.d(TAG, "Downgrading " + pkg);
if (DEBUG) {
Slog.d(TAG, "Downgrading " + pkg);
}
boolean dex_opt_performed = false;
int reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE;
int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
@@ -553,7 +545,7 @@ public class BackgroundDexOptService extends JobService {
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);
Slog.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace);
return OPTIMIZE_ABORT_NO_SPACE_LEFT;
}
@@ -592,8 +584,8 @@ public class BackgroundDexOptService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
if (DEBUG_DEXOPT) {
Log.i(TAG, "onStartJob");
if (DEBUG) {
Slog.i(TAG, "onStartJob");
}
// 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.
PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
if (pm.isStorageLow()) {
if (DEBUG_DEXOPT) {
Log.i(TAG, "Low storage, skipping this run");
}
Slog.i(TAG, "Low storage, skipping this run");
return false;
}
final ArraySet<String> pkgs = pm.getOptimizablePackages();
if (pkgs.isEmpty()) {
if (DEBUG_DEXOPT) {
Log.i(TAG, "No packages to optimize");
}
Slog.i(TAG, "No packages to optimize");
return false;
}
@@ -627,8 +615,8 @@ public class BackgroundDexOptService extends JobService {
@Override
public boolean onStopJob(JobParameters params) {
if (DEBUG_DEXOPT) {
Log.i(TAG, "onStopJob");
if (DEBUG) {
Slog.d(TAG, "onStopJob");
}
if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
@@ -649,7 +637,7 @@ public class BackgroundDexOptService extends JobService {
private void notifyPinService(ArraySet<String> updatedPackages) {
PinnerService pinnerService = LocalServices.getService(PinnerService.class);
if (pinnerService != null) {
Log.i(TAG, "Pinning optimized code " + updatedPackages);
Slog.i(TAG, "Pinning optimized code " + updatedPackages);
pinnerService.update(updatedPackages, false /* force */);
}
}
@@ -684,7 +672,7 @@ public class BackgroundDexOptService extends JobService {
final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days";
String sysPropValue = SystemProperties.get(sysPropKey);
if (sysPropValue == null || sysPropValue.isEmpty()) {
Log.w(TAG, "SysProp " + sysPropKey + " not set");
Slog.w(TAG, "SysProp " + sysPropKey + " not set");
return Long.MAX_VALUE;
}
return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));