Merge "Use non-wakeup alarm for delay constraint."

This commit is contained in:
Treehugger Robot
2020-01-15 20:07:43 +00:00
committed by Gerrit Code Review
3 changed files with 74 additions and 10 deletions

View File

@@ -232,6 +232,8 @@ message ConstantsProto {
// Whether or not TimeController should skip setting wakeup alarms for jobs that aren't // Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
// ready now. // ready now.
optional bool skip_not_ready_jobs = 1; optional bool skip_not_ready_jobs = 1;
// Whether or not TimeController will use a non-wakeup alarm for delay constraints.
optional bool use_non_wakeup_alarm_for_delay = 2;
} }
optional TimeController time_controller = 25; optional TimeController time_controller = 25;

View File

@@ -325,8 +325,7 @@ public final class TimeController extends StateController {
&& !wouldBeReadyWithConstraintLocked( && !wouldBeReadyWithConstraintLocked(
job, JobStatus.CONSTRAINT_TIMING_DELAY)) { job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
if (DEBUG) { if (DEBUG) {
Slog.i(TAG, Slog.i(TAG, "Skipping " + job + " because delay won't make it ready.");
"Skipping " + job + " because delay won't make it ready.");
} }
continue; continue;
} }
@@ -385,7 +384,8 @@ public final class TimeController extends StateController {
/** /**
* Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's * Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's
* delay will expire. * delay will expire.
* This alarm <b>will</b> wake up the phone. * This alarm <b>will not</b> wake up the phone if
* {@link TcConstants#USE_NON_WAKEUP_ALARM_FOR_DELAY} is true.
*/ */
private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) { private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis); alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
@@ -393,8 +393,11 @@ public final class TimeController extends StateController {
return; return;
} }
mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis; mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener, final int alarmType =
mNextDelayExpiredElapsedMillis, ws); mTcConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY
? AlarmManager.ELAPSED_REALTIME : AlarmManager.ELAPSED_REALTIME_WAKEUP;
updateAlarmWithListenerLocked(DELAY_TAG, alarmType,
mNextDelayExpiredListener, mNextDelayExpiredElapsedMillis, ws);
} }
/** /**
@@ -408,16 +411,16 @@ public final class TimeController extends StateController {
return; return;
} }
mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis; mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis;
updateAlarmWithListenerLocked(DEADLINE_TAG, mDeadlineExpiredListener, updateAlarmWithListenerLocked(DEADLINE_TAG, AlarmManager.ELAPSED_REALTIME_WAKEUP,
mNextJobExpiredElapsedMillis, ws); mDeadlineExpiredListener, mNextJobExpiredElapsedMillis, ws);
} }
private long maybeAdjustAlarmTime(long proposedAlarmTimeElapsedMillis) { private long maybeAdjustAlarmTime(long proposedAlarmTimeElapsedMillis) {
return Math.max(proposedAlarmTimeElapsedMillis, sElapsedRealtimeClock.millis()); return Math.max(proposedAlarmTimeElapsedMillis, sElapsedRealtimeClock.millis());
} }
private void updateAlarmWithListenerLocked(String tag, OnAlarmListener listener, private void updateAlarmWithListenerLocked(String tag, @AlarmManager.AlarmType int alarmType,
long alarmTimeElapsed, WorkSource ws) { OnAlarmListener listener, long alarmTimeElapsed, WorkSource ws) {
ensureAlarmServiceLocked(); ensureAlarmServiceLocked();
if (alarmTimeElapsed == Long.MAX_VALUE) { if (alarmTimeElapsed == Long.MAX_VALUE) {
mAlarmService.cancel(listener); mAlarmService.cancel(listener);
@@ -425,7 +428,7 @@ public final class TimeController extends StateController {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "Setting " + tag + " for: " + alarmTimeElapsed); Slog.d(TAG, "Setting " + tag + " for: " + alarmTimeElapsed);
} }
mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTimeElapsed, mAlarmService.set(alarmType, alarmTimeElapsed,
AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, ws); AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, ws);
} }
} }
@@ -464,8 +467,11 @@ public final class TimeController extends StateController {
private final KeyValueListParser mParser = new KeyValueListParser(','); private final KeyValueListParser mParser = new KeyValueListParser(',');
private static final String KEY_SKIP_NOT_READY_JOBS = "skip_not_ready_jobs"; private static final String KEY_SKIP_NOT_READY_JOBS = "skip_not_ready_jobs";
private static final String KEY_USE_NON_WAKEUP_ALARM_FOR_DELAY =
"use_non_wakeup_delay_alarm";
private static final boolean DEFAULT_SKIP_NOT_READY_JOBS = true; private static final boolean DEFAULT_SKIP_NOT_READY_JOBS = true;
private static final boolean DEFAULT_USE_NON_WAKEUP_ALARM_FOR_DELAY = true;
/** /**
* Whether or not TimeController should skip setting wakeup alarms for jobs that aren't * Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
@@ -473,6 +479,12 @@ public final class TimeController extends StateController {
*/ */
public boolean SKIP_NOT_READY_JOBS = DEFAULT_SKIP_NOT_READY_JOBS; public boolean SKIP_NOT_READY_JOBS = DEFAULT_SKIP_NOT_READY_JOBS;
/**
* Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
* ready now.
*/
public boolean USE_NON_WAKEUP_ALARM_FOR_DELAY = DEFAULT_USE_NON_WAKEUP_ALARM_FOR_DELAY;
/** /**
* Creates a content observer. * Creates a content observer.
* *
@@ -510,6 +522,12 @@ public final class TimeController extends StateController {
recheckAlarmsLocked(); recheckAlarmsLocked();
} }
} }
USE_NON_WAKEUP_ALARM_FOR_DELAY = mParser.getBoolean(
KEY_USE_NON_WAKEUP_ALARM_FOR_DELAY, DEFAULT_USE_NON_WAKEUP_ALARM_FOR_DELAY);
// Intentionally not calling checkExpiredDelaysAndResetAlarm() here. There's no need to
// iterate through the entire list again for this constant change. The next delay alarm
// that is set will make use of the new constant value.
} }
private void dump(IndentingPrintWriter pw) { private void dump(IndentingPrintWriter pw) {
@@ -517,12 +535,16 @@ public final class TimeController extends StateController {
pw.println("TimeController:"); pw.println("TimeController:");
pw.increaseIndent(); pw.increaseIndent();
pw.printPair(KEY_SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS).println(); pw.printPair(KEY_SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS).println();
pw.printPair(KEY_USE_NON_WAKEUP_ALARM_FOR_DELAY,
USE_NON_WAKEUP_ALARM_FOR_DELAY).println();
pw.decreaseIndent(); pw.decreaseIndent();
} }
private void dump(ProtoOutputStream proto) { private void dump(ProtoOutputStream proto) {
final long tcToken = proto.start(ConstantsProto.TIME_CONTROLLER); final long tcToken = proto.start(ConstantsProto.TIME_CONTROLLER);
proto.write(ConstantsProto.TimeController.SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS); proto.write(ConstantsProto.TimeController.SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS);
proto.write(ConstantsProto.TimeController.USE_NON_WAKEUP_ALARM_FOR_DELAY,
USE_NON_WAKEUP_ALARM_FOR_DELAY);
proto.end(tcToken); proto.end(tcToken);
} }
} }

View File

@@ -529,6 +529,46 @@ public class TimeControllerTest {
runTestCheckExpiredDelaysAndResetAlarm(); runTestCheckExpiredDelaysAndResetAlarm();
} }
@Test
public void testJobDelayWakeupAlarmToggling() {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
JobStatus job = createJobStatus(
"testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
createJob().setMinimumLatency(HOUR_IN_MILLIS));
doReturn(true).when(mTimeController)
.wouldBeReadyWithConstraintLocked(eq(job), anyInt());
// Starting off with using a wakeup alarm.
mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = false;
InOrder inOrder = inOrder(mAlarmManager);
mTimeController.maybeStartTrackingJobLocked(job, null);
inOrder.verify(mAlarmManager, times(1))
.set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(now + HOUR_IN_MILLIS), anyLong(),
anyLong(),
eq(TAG_DELAY), any(), any(), any());
// Use a non wakeup alarm.
mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = true;
mTimeController.maybeStartTrackingJobLocked(job, null);
inOrder.verify(mAlarmManager, times(1))
.set(eq(AlarmManager.ELAPSED_REALTIME), eq(now + HOUR_IN_MILLIS), anyLong(),
anyLong(), eq(TAG_DELAY),
any(), any(), any());
// Back off, use a wakeup alarm.
mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = false;
mTimeController.maybeStartTrackingJobLocked(job, null);
inOrder.verify(mAlarmManager, times(1))
.set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(now + HOUR_IN_MILLIS), anyLong(),
anyLong(),
eq(TAG_DELAY), any(), any(), any());
}
@Test @Test
public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_AllReady() { public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_AllReady() {
mConstants.SKIP_NOT_READY_JOBS = true; mConstants.SKIP_NOT_READY_JOBS = true;