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

Commit 043dc863 authored by Christian Wailes's avatar Christian Wailes Committed by Android (Google) Code Review
Browse files

Merge "Make BackgroundDexOpt aware of thermal state" into sc-dev

parents d6999024 5d8c1369
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();
        }
    }
}