Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1958d585 authored by Christian Wailes's avatar Christian Wailes Committed by Automerger Merge Worker
Browse files

Merge "Make BackgroundDexOpt aware of thermal state" am: 6c914b4b

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1706449

Change-Id: I93441b97c6e3d4a397898d349cc5bf6417f24a3d
parents e995e4b4 6c914b4b
Loading
Loading
Loading
Loading
+43 −2
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
include platform/art:/OWNERS
+32 −3
Original line number Diff line number Diff line
@@ -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();
        }
    }
}