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

Commit 70780830 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Throttle how frequently delay alarms are set."

parents 65186049 f697a14b
Loading
Loading
Loading
Loading
+14 −3
Original line number Original line Diff line number Diff line
@@ -50,6 +50,9 @@ public final class TimeController extends StateController {
    private static final boolean DEBUG = JobSchedulerService.DEBUG
    private static final boolean DEBUG = JobSchedulerService.DEBUG
            || Log.isLoggable(TAG, Log.DEBUG);
            || Log.isLoggable(TAG, Log.DEBUG);


    @VisibleForTesting
    static final long DELAY_COALESCE_TIME_MS = 30_000L;

    /** Deadline alarm tag for logging purposes */
    /** Deadline alarm tag for logging purposes */
    private final String DEADLINE_TAG = "*job.deadline*";
    private final String DEADLINE_TAG = "*job.deadline*";
    /** Delay alarm tag for logging purposes */
    /** Delay alarm tag for logging purposes */
@@ -57,6 +60,7 @@ public final class TimeController extends StateController {


    private long mNextJobExpiredElapsedMillis;
    private long mNextJobExpiredElapsedMillis;
    private long mNextDelayExpiredElapsedMillis;
    private long mNextDelayExpiredElapsedMillis;
    private volatile long mLastFiredDelayExpiredElapsedMillis;


    private final boolean mChainedAttributionEnabled;
    private final boolean mChainedAttributionEnabled;


@@ -273,7 +277,6 @@ public final class TimeController extends StateController {
    @VisibleForTesting
    @VisibleForTesting
    void checkExpiredDelaysAndResetAlarm() {
    void checkExpiredDelaysAndResetAlarm() {
        synchronized (mLock) {
        synchronized (mLock) {
            final long nowElapsedMillis = sElapsedRealtimeClock.millis();
            long nextDelayTime = Long.MAX_VALUE;
            long nextDelayTime = Long.MAX_VALUE;
            int nextDelayUid = 0;
            int nextDelayUid = 0;
            String nextDelayPackageName = null;
            String nextDelayPackageName = null;
@@ -284,7 +287,7 @@ public final class TimeController extends StateController {
                if (!job.hasTimingDelayConstraint()) {
                if (!job.hasTimingDelayConstraint()) {
                    continue;
                    continue;
                }
                }
                if (evaluateTimingDelayConstraint(job, nowElapsedMillis)) {
                if (evaluateTimingDelayConstraint(job, sElapsedRealtimeClock.millis())) {
                    if (canStopTrackingJobLocked(job)) {
                    if (canStopTrackingJobLocked(job)) {
                        it.remove();
                        it.remove();
                    }
                    }
@@ -356,7 +359,11 @@ public final class TimeController extends StateController {
     * This alarm <b>will not</b> wake up the phone.
     * This alarm <b>will not</b> wake up the phone.
     */
     */
    private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
    private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
        alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
        // To avoid spamming AlarmManager in the case where many delay times are a few milliseconds
        // apart, make sure the alarm is set no earlier than DELAY_COALESCE_TIME_MS since the last
        // time a delay alarm went off and that the alarm is not scheduled for the past.
        alarmTimeElapsedMillis = maybeAdjustAlarmTime(Math.max(alarmTimeElapsedMillis,
                mLastFiredDelayExpiredElapsedMillis + DELAY_COALESCE_TIME_MS));
        if (mNextDelayExpiredElapsedMillis == alarmTimeElapsedMillis) {
        if (mNextDelayExpiredElapsedMillis == alarmTimeElapsedMillis) {
            return;
            return;
        }
        }
@@ -416,6 +423,7 @@ public final class TimeController extends StateController {
            if (DEBUG) {
            if (DEBUG) {
                Slog.d(TAG, "Delay-expired alarm fired");
                Slog.d(TAG, "Delay-expired alarm fired");
            }
            }
            mLastFiredDelayExpiredElapsedMillis = sElapsedRealtimeClock.millis();
            checkExpiredDelaysAndResetAlarm();
            checkExpiredDelaysAndResetAlarm();
        }
        }
    };
    };
@@ -429,6 +437,9 @@ public final class TimeController extends StateController {
        pw.print("Next delay alarm in ");
        pw.print("Next delay alarm in ");
        TimeUtils.formatDuration(mNextDelayExpiredElapsedMillis, nowElapsed, pw);
        TimeUtils.formatDuration(mNextDelayExpiredElapsedMillis, nowElapsed, pw);
        pw.println();
        pw.println();
        pw.print("Last delay alarm fired @ ");
        TimeUtils.formatDuration(nowElapsed, mLastFiredDelayExpiredElapsedMillis, pw);
        pw.println();
        pw.print("Next deadline alarm in ");
        pw.print("Next deadline alarm in ");
        TimeUtils.formatDuration(mNextJobExpiredElapsedMillis, nowElapsed, pw);
        TimeUtils.formatDuration(mNextJobExpiredElapsedMillis, nowElapsed, pw);
        pw.println();
        pw.println();
+45 −0
Original line number Original line Diff line number Diff line
@@ -52,6 +52,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Before;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.MockitoSession;
@@ -631,6 +632,50 @@ public class TimeControllerTest {
                .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
                .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
    }
    }


    @Test
    public void testDelayAlarmSchedulingCoalescedIntervals() {
        doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());

        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();

        JobStatus jobLatest = createJobStatus("testDelayAlarmSchedulingCoalescedIntervals",
                createJob().setMinimumLatency(HOUR_IN_MILLIS));
        JobStatus jobMiddle = createJobStatus("testDelayAlarmSchedulingCoalescedIntervals",
                createJob().setMinimumLatency(TimeController.DELAY_COALESCE_TIME_MS / 2));
        JobStatus jobEarliest = createJobStatus("testDelayAlarmSchedulingCoalescedIntervals",
                createJob().setMinimumLatency(TimeController.DELAY_COALESCE_TIME_MS / 10));

        ArgumentCaptor<AlarmManager.OnAlarmListener> listenerCaptor =
                ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
        InOrder inOrder = inOrder(mAlarmManager);

        mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
        mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
        mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
        inOrder.verify(mAlarmManager, times(1))
                .set(anyInt(), eq(now + TimeController.DELAY_COALESCE_TIME_MS / 10), anyLong(),
                        anyLong(), eq(TAG_DELAY),
                        listenerCaptor.capture(), any(), any());
        final AlarmManager.OnAlarmListener delayListener = listenerCaptor.getValue();

        advanceElapsedClock(TimeController.DELAY_COALESCE_TIME_MS / 10);
        delayListener.onAlarm();
        // The next delay alarm time should be TimeController.DELAY_COALESCE_TIME_MS after the last
        // time the delay alarm fired.
        inOrder.verify(mAlarmManager, times(1))
                .set(anyInt(), eq(now + TimeController.DELAY_COALESCE_TIME_MS / 10
                                + TimeController.DELAY_COALESCE_TIME_MS), anyLong(),
                        anyLong(), eq(TAG_DELAY), any(), any(), any());

        advanceElapsedClock(TimeController.DELAY_COALESCE_TIME_MS);
        delayListener.onAlarm();
        // The last job is significantly after the coalesce time, so the 3rd scheduling shouldn't be
        // affected by the first two jobs' alarms.
        inOrder.verify(mAlarmManager, times(1))
                .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(),
                        anyLong(), eq(TAG_DELAY), any(), any(), any());
    }

    @Test
    @Test
    public void testEvaluateStateLocked_Delay() {
    public void testEvaluateStateLocked_Delay() {
        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();