summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chris Wailes <chriswailes@google.com> 2020-12-04 09:53:49 -0800
committer Chris Wailes <chriswailes@google.com> 2021-05-14 15:42:29 -0700
commitd63d206f9751281e1d7e652727516bfc4b249667 (patch)
tree6a71b751ccc5717fd500e2a7b7dc5e9c6692029e
parent576dad467388cbf5864b3e499f3eaf7f047f6b30 (diff)
Make BackgroundDexOpt aware of thermal state
This change makes the BackgroundDexOpt service consider the thermal state of the device before running. If the device is in a moderate thermal state or worse background dexopt will not run. Bug: 165935246 Test: Treehugger && atest BackgroundDexOptServiceIntegrationTests Change-Id: Ie5ccbab7aa6d414241780136407f397d326340bf
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java45
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/OWNERS1
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java35
3 files changed, 76 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 77c1c1db2257..49a0a8827699 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -31,6 +31,9 @@ import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.os.BatteryManagerInternal;
import android.os.Environment;
+import android.os.IThermalService;
+import android.os.PowerManager;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -82,10 +85,15 @@ public class BackgroundDexOptService extends JobService {
private static final int OPTIMIZE_ABORT_BY_JOB_SCHEDULER = 2;
// Optimizations should be aborted. No space left on device.
private static final int OPTIMIZE_ABORT_NO_SPACE_LEFT = 3;
+ // Optimizations should be aborted. Thermal throttling level too high.
+ private static final int OPTIMIZE_ABORT_THERMAL = 4;
// Used for calculating space threshold for downgrading unused apps.
private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2;
+ // Thermal cutoff value used if one isn't defined by a system property.
+ private static final int THERMAL_CUTOFF_DEFAULT = PowerManager.THERMAL_STATUS_MODERATE;
+
/**
* Set of failed packages remembered across job runs.
*/
@@ -107,8 +115,14 @@ public class BackgroundDexOptService extends JobService {
private static final long mDowngradeUnusedAppsThresholdInMillis =
getDowngradeUnusedAppsThresholdInMillis();
+ private final IThermalService mThermalService =
+ IThermalService.Stub.asInterface(
+ ServiceManager.getService(Context.THERMAL_SERVICE));
+
private static List<PackagesUpdatedListener> sPackagesUpdatedListeners = new ArrayList<>();
+ private int mThermalStatusCutoff = THERMAL_CUTOFF_DEFAULT;
+
public static void schedule(Context context) {
if (isBackgroundDexoptDisabled()) {
return;
@@ -251,12 +265,18 @@ public class BackgroundDexOptService extends JobService {
Slog.w(TAG, "Idle optimizations aborted because of space constraints.");
} else if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
Slog.w(TAG, "Idle optimizations aborted by job scheduler.");
+ } else if (result == OPTIMIZE_ABORT_THERMAL) {
+ Slog.w(TAG, "Idle optimizations aborted by thermal throttling.");
} else {
Slog.w(TAG, "Idle optimizations ended with unexpected code: " + result);
}
- if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
+
+ if (result == OPTIMIZE_ABORT_THERMAL) {
+ // Abandon our timeslice and reschedule
+ jobFinished(jobParams, /* wantsReschedule */ true);
+ } else if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
// Abandon our timeslice and do not reschedule.
- jobFinished(jobParams, /* reschedule */ false);
+ jobFinished(jobParams, /* wantsReschedule */ false);
}
}
}.start();
@@ -542,6 +562,24 @@ public class BackgroundDexOptService extends JobService {
// JobScheduler requested an early abort.
return OPTIMIZE_ABORT_BY_JOB_SCHEDULER;
}
+
+ // Abort background dexopt if the device is in a moderate or stronger thermal throttling
+ // state.
+ try {
+ final int thermalStatus = mThermalService.getCurrentThermalStatus();
+
+ if (DEBUG) {
+ Log.i(TAG, "Thermal throttling status during bgdexopt: " + thermalStatus);
+ }
+
+ if (thermalStatus >= mThermalStatusCutoff) {
+ return OPTIMIZE_ABORT_THERMAL;
+ }
+ } catch (RemoteException ex) {
+ // Because this is a intra-process Binder call it is impossible for a RemoteException
+ // to be raised.
+ }
+
long usableSpace = mDataDir.getUsableSpace();
if (usableSpace < lowStorageThreshold) {
// Rather bail than completely fill up the disk.
@@ -603,6 +641,9 @@ public class BackgroundDexOptService extends JobService {
return false;
}
+ mThermalStatusCutoff =
+ SystemProperties.getInt("dalvik.vm.dexopt.thermal-cutoff", THERMAL_CUTOFF_DEFAULT);
+
boolean result;
if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
result = runPostBootUpdate(params, pm, pkgs);
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/OWNERS b/tests/BackgroundDexOptServiceIntegrationTests/OWNERS
new file mode 100644
index 000000000000..3414a7469ac2
--- /dev/null
+++ b/tests/BackgroundDexOptServiceIntegrationTests/OWNERS
@@ -0,0 +1 @@
+include platform/art:/OWNERS
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index e05816eb391f..90ddb6ffb34a 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -20,6 +20,7 @@ import android.app.AlarmManager;
import android.content.Context;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.util.Log;
@@ -201,11 +202,16 @@ public final class BackgroundDexOptServiceIntegrationTests {
fillUpStorage((long) (getStorageLowBytes() * LOW_STORAGE_MULTIPLIER));
}
- // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run
private static void runBackgroundDexOpt() throws IOException {
+ runBackgroundDexOpt("Success");
+ }
+
+ // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run
+ private static void runBackgroundDexOpt(String expectedStatus) throws IOException {
String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME);
- if (!result.trim().equals("Success")) {
- throw new IllegalStateException("Expected command success, received >" + result + "<");
+ if (!result.trim().equals(expectedStatus)) {
+ throw new IllegalStateException("Expected status: " + expectedStatus
+ + "; Received: " + result.trim());
}
}
@@ -242,6 +248,16 @@ public final class BackgroundDexOptServiceIntegrationTests {
runShellCommand(String.format("cmd package compile -f -m %s %s", filter, pkg));
}
+ // Override the thermal status of the device
+ public static void overrideThermalStatus(int status) throws IOException {
+ runShellCommand("cmd thermalservice override-status " + status);
+ }
+
+ // Reset the thermal status of the device
+ public static void resetThermalStatus() throws IOException {
+ runShellCommand("cmd thermalservice reset");
+ }
+
// Test that background dexopt under normal conditions succeeds.
@Test
public void testBackgroundDexOpt() throws IOException {
@@ -307,4 +323,17 @@ public final class BackgroundDexOptServiceIntegrationTests {
}
}
+ // Test that background dexopt job doesn't trigger if the device is under thermal throttling.
+ @Test
+ public void testBackgroundDexOptThermalThrottling() throws IOException {
+ try {
+ compilePackageWithFilter(PACKAGE_NAME, "verify");
+ overrideThermalStatus(PowerManager.THERMAL_STATUS_MODERATE);
+ // The bgdexopt task should fail when onStartJob is run
+ runBackgroundDexOpt("Failure");
+ Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME));
+ } finally {
+ resetThermalStatus();
+ }
+ }
}