blob: 6c29f6050276202679d4fdb88444d3568d766518 [file] [log] [blame]
Kweku Adamsbffea5a2018-12-13 22:13:28 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.job.controllers;
18
19import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
20import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
21import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
22import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
23import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
24import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
25
26import static org.junit.Assert.assertFalse;
27import static org.junit.Assert.assertTrue;
28import static org.mockito.ArgumentMatchers.any;
29import static org.mockito.ArgumentMatchers.anyInt;
30import static org.mockito.ArgumentMatchers.anyLong;
31import static org.mockito.ArgumentMatchers.anyString;
32import static org.mockito.Mockito.eq;
33import static org.mockito.Mockito.never;
34import static org.mockito.Mockito.times;
35import static org.mockito.Mockito.verify;
36
37import android.app.AlarmManager;
38import android.app.job.JobInfo;
39import android.content.ComponentName;
40import android.content.Context;
41import android.content.pm.PackageManagerInternal;
Kweku Adams4e774a32019-04-24 18:01:29 -070042import android.os.Looper;
Kweku Adamsbffea5a2018-12-13 22:13:28 -080043import android.os.SystemClock;
44
45import androidx.test.runner.AndroidJUnit4;
46
47import com.android.server.LocalServices;
48import com.android.server.job.JobSchedulerService;
49import com.android.server.job.JobSchedulerService.Constants;
50
51import org.junit.After;
52import org.junit.Before;
53import org.junit.Test;
54import org.junit.runner.RunWith;
55import org.mockito.InOrder;
56import org.mockito.Mock;
57import org.mockito.MockitoSession;
58import org.mockito.quality.Strictness;
59
60import java.time.Clock;
61import java.time.Duration;
62import java.time.ZoneOffset;
63
64@RunWith(AndroidJUnit4.class)
65public class TimeControllerTest {
66 private static final long SECOND_IN_MILLIS = 1000L;
67 private static final long MINUTE_IN_MILLIS = 60 * SECOND_IN_MILLIS;
68 private static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS;
69 private static final String TAG_DEADLINE = "*job.deadline*";
70 private static final String TAG_DELAY = "*job.delay*";
71 private static final String SOURCE_PACKAGE = "com.android.frameworks.mockingservicestests";
72 private static final int SOURCE_USER_ID = 0;
73
Kweku Adams4e774a32019-04-24 18:01:29 -070074 private TimeController.TcConstants mConstants;
Kweku Adamsbffea5a2018-12-13 22:13:28 -080075 private TimeController mTimeController;
76
77 private MockitoSession mMockingSession;
78 @Mock
79 private AlarmManager mAlarmManager;
80 @Mock
81 private Context mContext;
82 @Mock
83 private JobSchedulerService mJobSchedulerService;
84
85 @Before
86 public void setUp() {
87 mMockingSession = mockitoSession()
88 .initMocks(this)
89 .strictness(Strictness.LENIENT)
90 .mockStatic(LocalServices.class)
91 .startMocking();
Kweku Adamsbffea5a2018-12-13 22:13:28 -080092
93 // Called in StateController constructor.
94 when(mJobSchedulerService.getTestableContext()).thenReturn(mContext);
95 when(mJobSchedulerService.getLock()).thenReturn(mJobSchedulerService);
Kweku Adams4e774a32019-04-24 18:01:29 -070096 when(mJobSchedulerService.getConstants()).thenReturn(mock(Constants.class));
Kweku Adamsbffea5a2018-12-13 22:13:28 -080097 // Called in TimeController constructor.
Kweku Adams4e774a32019-04-24 18:01:29 -070098 when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
Kweku Adamsbffea5a2018-12-13 22:13:28 -080099 when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
100 // Used in JobStatus.
101 doReturn(mock(PackageManagerInternal.class))
102 .when(() -> LocalServices.getService(PackageManagerInternal.class));
103
104 // Freeze the clocks at this moment in time
105 JobSchedulerService.sSystemClock =
106 Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
107 JobSchedulerService.sUptimeMillisClock =
108 Clock.fixed(SystemClock.uptimeMillisClock().instant(), ZoneOffset.UTC);
109 JobSchedulerService.sElapsedRealtimeClock =
110 Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
111
112 // Initialize real objects.
113 mTimeController = new TimeController(mJobSchedulerService);
Kweku Adams4e774a32019-04-24 18:01:29 -0700114 mConstants = mTimeController.getTcConstants();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800115 spyOn(mTimeController);
116 }
117
118 @After
119 public void tearDown() {
120 if (mMockingSession != null) {
121 mMockingSession.finishMocking();
122 }
123 }
124
125 private Clock getAdvancedClock(Clock clock, long incrementMs) {
126 return Clock.offset(clock, Duration.ofMillis(incrementMs));
127 }
128
129 private void advanceElapsedClock(long incrementMs) {
130 JobSchedulerService.sElapsedRealtimeClock = getAdvancedClock(
131 JobSchedulerService.sElapsedRealtimeClock, incrementMs);
132 }
133
134 private static JobInfo.Builder createJob() {
135 return new JobInfo.Builder(101, new ComponentName("foo", "bar"));
136 }
137
138 private JobStatus createJobStatus(String testTag, JobInfo.Builder job) {
139 JobInfo jobInfo = job.build();
140 return JobStatus.createFromJobInfo(
141 jobInfo, 1000, SOURCE_PACKAGE, SOURCE_USER_ID, testTag);
142 }
143
144 @Test
145 public void testMaybeStartTrackingJobLocked_AlreadySatisfied() {
146 JobStatus delaySatisfied = createJobStatus(
147 "testMaybeStartTrackingJobLocked_AlreadySatisfied",
148 createJob().setMinimumLatency(1));
149 JobStatus deadlineSatisfied = createJobStatus(
150 "testMaybeStartTrackingJobLocked_AlreadySatisfied",
151 createJob().setOverrideDeadline(1));
152
153 advanceElapsedClock(5);
154
155 mTimeController.maybeStartTrackingJobLocked(delaySatisfied, null);
156 mTimeController.maybeStartTrackingJobLocked(deadlineSatisfied, null);
157 verify(mAlarmManager, never())
158 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
159 }
160
161 @Test
162 public void testMaybeStartTrackingJobLocked_DelayInOrder_NoSkipping() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700163 mConstants.SKIP_NOT_READY_JOBS = false;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800164 mTimeController.onConstantsUpdatedLocked();
165
166 runTestMaybeStartTrackingJobLocked_DelayInOrder();
167 }
168
169 @Test
170 public void testMaybeStartTrackingJobLocked_DelayInOrder_WithSkipping_AllReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700171 mConstants.SKIP_NOT_READY_JOBS = true;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800172 mTimeController.onConstantsUpdatedLocked();
173
174 doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
175
176 runTestMaybeStartTrackingJobLocked_DelayInOrder();
177 }
178
179 private void runTestMaybeStartTrackingJobLocked_DelayInOrder() {
180 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
181
182 JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DelayInOrder",
183 createJob().setMinimumLatency(HOUR_IN_MILLIS));
184 JobStatus jobMiddle = createJobStatus("testMaybeStartTrackingJobLocked_DelayInOrder",
185 createJob().setMinimumLatency(30 * MINUTE_IN_MILLIS));
186 JobStatus jobEarliest = createJobStatus("testMaybeStartTrackingJobLocked_DelayInOrder",
187 createJob().setMinimumLatency(5 * MINUTE_IN_MILLIS));
188
189 InOrder inOrder = inOrder(mAlarmManager);
190
191 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
192 inOrder.verify(mAlarmManager, times(1))
193 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
194 any(), any(), any());
195 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
196 inOrder.verify(mAlarmManager, never())
197 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
198 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
199 inOrder.verify(mAlarmManager, never())
200 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
201 }
202
203 @Test
204 public void testMaybeStartTrackingJobLocked_DelayInOrder_WithSkipping_SomeNotReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700205 mConstants.SKIP_NOT_READY_JOBS = true;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800206 mTimeController.onConstantsUpdatedLocked();
207 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
208
209 JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DelayInOrder",
210 createJob().setMinimumLatency(HOUR_IN_MILLIS));
211 JobStatus jobMiddle = createJobStatus("testMaybeStartTrackingJobLocked_DelayInOrder",
212 createJob().setMinimumLatency(30 * MINUTE_IN_MILLIS));
213 JobStatus jobEarliest = createJobStatus("testMaybeStartTrackingJobLocked_DelayInOrder",
214 createJob().setMinimumLatency(5 * MINUTE_IN_MILLIS));
215
216 doReturn(true).when(mTimeController)
217 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
218 doReturn(false).when(mTimeController)
219 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
220 doReturn(true).when(mTimeController)
221 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
222
223 InOrder inOrder = inOrder(mAlarmManager);
224
225 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
226 inOrder.verify(mAlarmManager, times(1))
227 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
228 any(), any(), any());
229 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
230 inOrder.verify(mAlarmManager, never())
231 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
232 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
233 inOrder.verify(mAlarmManager, never())
234 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
235 }
236
237 @Test
238 public void testMaybeStartTrackingJobLocked_DelayReverseOrder_NoSkipping() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700239 mConstants.SKIP_NOT_READY_JOBS = false;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800240 mTimeController.onConstantsUpdatedLocked();
241
242 runTestMaybeStartTrackingJobLocked_DelayReverseOrder();
243 }
244
245 @Test
246 public void testMaybeStartTrackingJobLocked_DelayReverseOrder_WithSkipping_AllReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700247 mConstants.SKIP_NOT_READY_JOBS = true;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800248 mTimeController.onConstantsUpdatedLocked();
249
250 doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
251
252 runTestMaybeStartTrackingJobLocked_DelayReverseOrder();
253 }
254
255 private void runTestMaybeStartTrackingJobLocked_DelayReverseOrder() {
256 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
257
258 JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DelayReverseOrder",
259 createJob().setMinimumLatency(HOUR_IN_MILLIS));
260 JobStatus jobMiddle = createJobStatus("testMaybeStartTrackingJobLocked_DelayReverseOrder",
261 createJob().setMinimumLatency(30 * MINUTE_IN_MILLIS));
262 JobStatus jobEarliest = createJobStatus("testMaybeStartTrackingJobLocked_DelayReverseOrder",
263 createJob().setMinimumLatency(5 * MINUTE_IN_MILLIS));
264
265 InOrder inOrder = inOrder(mAlarmManager);
266
267 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
268 inOrder.verify(mAlarmManager, times(1))
269 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY), any(),
270 any(), any());
271 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
272 inOrder.verify(mAlarmManager, times(1))
273 .set(anyInt(), eq(now + 30 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
274 any(), any(), any());
275 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
276 inOrder.verify(mAlarmManager, times(1))
277 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
278 any(), any(), any());
279 }
280
281 @Test
282 public void testMaybeStartTrackingJobLocked_DelayReverseOrder_WithSkipping_SomeNotReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700283 mConstants.SKIP_NOT_READY_JOBS = true;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800284 mTimeController.onConstantsUpdatedLocked();
285 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
286
287 JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DelayReverseOrder",
288 createJob().setMinimumLatency(HOUR_IN_MILLIS));
289 JobStatus jobMiddle = createJobStatus("testMaybeStartTrackingJobLocked_DelayReverseOrder",
290 createJob().setMinimumLatency(30 * MINUTE_IN_MILLIS));
291 JobStatus jobEarliest = createJobStatus("testMaybeStartTrackingJobLocked_DelayReverseOrder",
292 createJob().setMinimumLatency(5 * MINUTE_IN_MILLIS));
293
294 doReturn(true).when(mTimeController)
295 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
296 doReturn(false).when(mTimeController)
297 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
298 doReturn(true).when(mTimeController)
299 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
300
301 InOrder inOrder = inOrder(mAlarmManager);
302
303 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
304 inOrder.verify(mAlarmManager, times(1))
305 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY), any(),
306 any(), any());
307 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
308 // Middle alarm shouldn't be set since it won't be ready.
309 inOrder.verify(mAlarmManager, never())
310 .set(anyInt(), anyLong(), anyLong(), anyLong(), eq(TAG_DELAY), any(), any(), any());
311 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
312 inOrder.verify(mAlarmManager, times(1))
313 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
314 any(), any(), any());
315 }
316
317 @Test
318 public void testMaybeStartTrackingJobLocked_DeadlineInOrder_NoSkipping() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700319 mConstants.SKIP_NOT_READY_JOBS = false;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800320 mTimeController.onConstantsUpdatedLocked();
321
322 runTestMaybeStartTrackingJobLocked_DeadlineInOrder();
323 }
324
325 @Test
326 public void testMaybeStartTrackingJobLocked_DeadlineInOrder_WithSkipping_AllReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700327 mConstants.SKIP_NOT_READY_JOBS = true;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800328 mTimeController.onConstantsUpdatedLocked();
329
330 doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
331
332 runTestMaybeStartTrackingJobLocked_DeadlineInOrder();
333 }
334
335 private void runTestMaybeStartTrackingJobLocked_DeadlineInOrder() {
336 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
337
338 JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DeadlineInOrder",
339 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
340 JobStatus jobMiddle = createJobStatus("testMaybeStartTrackingJobLocked_DeadlineInOrder",
341 createJob().setOverrideDeadline(30 * MINUTE_IN_MILLIS));
342 JobStatus jobEarliest = createJobStatus("testMaybeStartTrackingJobLocked_DeadlineInOrder",
343 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
344
345 InOrder inOrder = inOrder(mAlarmManager);
346
347 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
348 inOrder.verify(mAlarmManager, times(1))
349 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
350 eq(TAG_DEADLINE), any(), any(), any());
351 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
352 inOrder.verify(mAlarmManager, never())
353 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
354 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
355 inOrder.verify(mAlarmManager, never())
356 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
357 }
358
359 @Test
360 public void testMaybeStartTrackingJobLocked_DeadlineInOrder_WithSkipping_SomeNotReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700361 mConstants.SKIP_NOT_READY_JOBS = true;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800362 mTimeController.onConstantsUpdatedLocked();
363 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
364
365 JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DeadlineInOrder",
366 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
367 JobStatus jobMiddle = createJobStatus("testMaybeStartTrackingJobLocked_DeadlineInOrder",
368 createJob().setOverrideDeadline(30 * MINUTE_IN_MILLIS));
369 JobStatus jobEarliest = createJobStatus("testMaybeStartTrackingJobLocked_DeadlineInOrder",
370 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
371
372 doReturn(true).when(mTimeController)
373 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
374 doReturn(false).when(mTimeController)
375 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
376 doReturn(true).when(mTimeController)
377 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
378
379 InOrder inOrder = inOrder(mAlarmManager);
380
381 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
382 inOrder.verify(mAlarmManager, times(1))
383 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
384 eq(TAG_DEADLINE), any(), any(), any());
385 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
386 inOrder.verify(mAlarmManager, never())
387 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
388 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
389 inOrder.verify(mAlarmManager, never())
390 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
391 }
392
393 @Test
394 public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_NoSkipping() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700395 mConstants.SKIP_NOT_READY_JOBS = false;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800396 mTimeController.onConstantsUpdatedLocked();
397
398 runTestMaybeStartTrackingJobLocked_DeadlineReverseOrder();
399 }
400
401 @Test
402 public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_WithSkipping_AllReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700403 mConstants.SKIP_NOT_READY_JOBS = true;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800404 mTimeController.onConstantsUpdatedLocked();
405
406 doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
407
408 runTestMaybeStartTrackingJobLocked_DeadlineReverseOrder();
409 }
410
411 private void runTestMaybeStartTrackingJobLocked_DeadlineReverseOrder() {
412 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
413
414 JobStatus jobLatest = createJobStatus(
415 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
416 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
417 JobStatus jobMiddle = createJobStatus(
418 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
419 createJob().setOverrideDeadline(30 * MINUTE_IN_MILLIS));
420 JobStatus jobEarliest = createJobStatus(
421 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
422 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
423
424 InOrder inOrder = inOrder(mAlarmManager);
425
426 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
427 inOrder.verify(mAlarmManager, times(1))
428 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DEADLINE),
429 any(), any(), any());
430 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
431 inOrder.verify(mAlarmManager, times(1))
432 .set(anyInt(), eq(now + 30 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
433 eq(TAG_DEADLINE), any(), any(), any());
434 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
435 inOrder.verify(mAlarmManager, times(1))
436 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
437 eq(TAG_DEADLINE), any(), any(), any());
438 }
439
440 @Test
441 public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_WithSkipping_SomeNotReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700442 mConstants.SKIP_NOT_READY_JOBS = true;
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800443 mTimeController.onConstantsUpdatedLocked();
444 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
445
446 JobStatus jobLatest = createJobStatus(
447 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
448 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
449 JobStatus jobMiddle = createJobStatus(
450 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
451 createJob().setOverrideDeadline(30 * MINUTE_IN_MILLIS));
452 JobStatus jobEarliest = createJobStatus(
453 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
454 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
455
456 doReturn(true).when(mTimeController)
457 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
458 doReturn(false).when(mTimeController)
459 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
460 doReturn(true).when(mTimeController)
461 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
462
463 InOrder inOrder = inOrder(mAlarmManager);
464
465 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
466 inOrder.verify(mAlarmManager, times(1))
467 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DEADLINE),
468 any(), any(), any());
469 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
470 // Middle alarm should be skipped since the job wouldn't be ready.
471 inOrder.verify(mAlarmManager, never())
472 .set(anyInt(), anyLong(), anyLong(), anyLong(), eq(TAG_DEADLINE), any(), any(),
473 any());
474 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
475 inOrder.verify(mAlarmManager, times(1))
476 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
477 eq(TAG_DEADLINE), any(), any(), any());
478 }
479
480 @Test
481 public void testJobSkipToggling() {
482 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
483
484 JobStatus jobLatest = createJobStatus(
485 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
486 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
487 JobStatus jobEarliest = createJobStatus(
488 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
489 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
490
491 doReturn(true).when(mTimeController)
492 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
493 doReturn(false).when(mTimeController)
494 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
495
496 // Starting off with the skipping off, we should still set an alarm for the earlier job.
Kweku Adams4e774a32019-04-24 18:01:29 -0700497 mConstants.SKIP_NOT_READY_JOBS = false;
498 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800499 InOrder inOrder = inOrder(mAlarmManager);
500
501 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
502 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
503 inOrder.verify(mAlarmManager, times(1))
504 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
505 eq(TAG_DEADLINE), any(), any(), any());
506
507 // Turn it on, use alarm for later job.
Kweku Adams4e774a32019-04-24 18:01:29 -0700508 mConstants.SKIP_NOT_READY_JOBS = true;
509 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800510
511 inOrder.verify(mAlarmManager, times(1))
512 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DEADLINE),
513 any(), any(), any());
514
515 // Back off, use alarm for earlier job.
Kweku Adams4e774a32019-04-24 18:01:29 -0700516 mConstants.SKIP_NOT_READY_JOBS = false;
517 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800518
519 inOrder.verify(mAlarmManager, times(1))
520 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
521 eq(TAG_DEADLINE), any(), any(), any());
522 }
523
524 @Test
525 public void testCheckExpiredDelaysAndResetAlarm_NoSkipping() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700526 mConstants.SKIP_NOT_READY_JOBS = false;
527 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800528
529 runTestCheckExpiredDelaysAndResetAlarm();
530 }
531
532 @Test
Kweku Adams208b2682020-01-09 16:01:26 -0800533 public void testJobDelayWakeupAlarmToggling() {
534 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
535
536 JobStatus job = createJobStatus(
537 "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
538 createJob().setMinimumLatency(HOUR_IN_MILLIS));
539
540 doReturn(true).when(mTimeController)
541 .wouldBeReadyWithConstraintLocked(eq(job), anyInt());
542
543 // Starting off with using a wakeup alarm.
544 mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = false;
545 InOrder inOrder = inOrder(mAlarmManager);
546
547 mTimeController.maybeStartTrackingJobLocked(job, null);
548 inOrder.verify(mAlarmManager, times(1))
549 .set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(now + HOUR_IN_MILLIS), anyLong(),
550 anyLong(),
551 eq(TAG_DELAY), any(), any(), any());
552
553 // Use a non wakeup alarm.
554 mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = true;
555
556 mTimeController.maybeStartTrackingJobLocked(job, null);
557 inOrder.verify(mAlarmManager, times(1))
558 .set(eq(AlarmManager.ELAPSED_REALTIME), eq(now + HOUR_IN_MILLIS), anyLong(),
559 anyLong(), eq(TAG_DELAY),
560 any(), any(), any());
561
562 // Back off, use a wakeup alarm.
563 mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = false;
564
565 mTimeController.maybeStartTrackingJobLocked(job, null);
566 inOrder.verify(mAlarmManager, times(1))
567 .set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(now + HOUR_IN_MILLIS), anyLong(),
568 anyLong(),
569 eq(TAG_DELAY), any(), any(), any());
570 }
571
572 @Test
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800573 public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_AllReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700574 mConstants.SKIP_NOT_READY_JOBS = true;
575 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800576
577 doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
578
579 runTestCheckExpiredDelaysAndResetAlarm();
580 }
581
582 private void runTestCheckExpiredDelaysAndResetAlarm() {
583 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
584
585 JobStatus jobLatest = createJobStatus("testCheckExpiredDelaysAndResetAlarm",
586 createJob().setMinimumLatency(HOUR_IN_MILLIS));
587 JobStatus jobMiddle = createJobStatus("testCheckExpiredDelaysAndResetAlarm",
588 createJob().setMinimumLatency(30 * MINUTE_IN_MILLIS));
589 JobStatus jobEarliest = createJobStatus("testCheckExpiredDelaysAndResetAlarm",
590 createJob().setMinimumLatency(5 * MINUTE_IN_MILLIS));
591
592 InOrder inOrder = inOrder(mAlarmManager);
593
594 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
595 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
596 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
597 inOrder.verify(mAlarmManager, times(1))
598 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
599 any(), any(), any());
600
601 advanceElapsedClock(10 * MINUTE_IN_MILLIS);
602
603 mTimeController.checkExpiredDelaysAndResetAlarm();
604 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
605 assertFalse(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
606 assertFalse(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
607 inOrder.verify(mAlarmManager, times(1))
608 .set(anyInt(), eq(now + 30 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
609 any(), any(), any());
610
611 advanceElapsedClock(30 * MINUTE_IN_MILLIS);
612
613 mTimeController.checkExpiredDelaysAndResetAlarm();
614 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
615 assertTrue(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
616 assertFalse(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
617 inOrder.verify(mAlarmManager, times(1))
618 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY), any(),
619 any(), any());
620
621 advanceElapsedClock(30 * MINUTE_IN_MILLIS);
622
623 mTimeController.checkExpiredDelaysAndResetAlarm();
624 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
625 assertTrue(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
626 assertTrue(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
627 inOrder.verify(mAlarmManager, never())
628 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
629 }
630
631 @Test
632 public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_SomeNotReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700633 mConstants.SKIP_NOT_READY_JOBS = true;
634 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800635 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
636
637 JobStatus jobLatest = createJobStatus("testCheckExpiredDelaysAndResetAlarm",
638 createJob().setMinimumLatency(HOUR_IN_MILLIS));
639 JobStatus jobMiddle = createJobStatus("testCheckExpiredDelaysAndResetAlarm",
640 createJob().setMinimumLatency(30 * MINUTE_IN_MILLIS));
641 JobStatus jobEarliest = createJobStatus("testCheckExpiredDelaysAndResetAlarm",
642 createJob().setMinimumLatency(5 * MINUTE_IN_MILLIS));
643
644 doReturn(true).when(mTimeController)
645 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
646 doReturn(false).when(mTimeController)
647 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
648 doReturn(true).when(mTimeController)
649 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
650
651 InOrder inOrder = inOrder(mAlarmManager);
652
653 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
654 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
655 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
656 inOrder.verify(mAlarmManager, times(1))
657 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
658 any(), any(), any());
659
660 advanceElapsedClock(10 * MINUTE_IN_MILLIS);
661
662 mTimeController.checkExpiredDelaysAndResetAlarm();
663 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
664 assertFalse(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
665 assertFalse(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
666 // Middle job wouldn't be ready, so its alarm should be skipped.
667 inOrder.verify(mAlarmManager, times(1))
668 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY), any(),
669 any(), any());
670
671 advanceElapsedClock(55 * MINUTE_IN_MILLIS);
672
673 mTimeController.checkExpiredDelaysAndResetAlarm();
674 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
675 assertTrue(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
676 assertTrue(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY));
677 inOrder.verify(mAlarmManager, never())
678 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
679 }
680
681 @Test
682 public void testCheckExpiredDeadlinesAndResetAlarm_NoSkipping() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700683 mConstants.SKIP_NOT_READY_JOBS = false;
684 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800685
686 runTestCheckExpiredDeadlinesAndResetAlarm();
687 }
688
689 @Test
690 public void testCheckExpiredDeadlinesAndResetAlarm_WithSkipping_AllReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700691 mConstants.SKIP_NOT_READY_JOBS = true;
692 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800693
694 doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
695
696 runTestCheckExpiredDeadlinesAndResetAlarm();
697 }
698
699 private void runTestCheckExpiredDeadlinesAndResetAlarm() {
700 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
701
702 JobStatus jobLatest = createJobStatus("testCheckExpiredDeadlinesAndResetAlarm",
703 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
704 JobStatus jobMiddle = createJobStatus("testCheckExpiredDeadlinesAndResetAlarm",
705 createJob().setOverrideDeadline(30 * MINUTE_IN_MILLIS));
706 JobStatus jobEarliest = createJobStatus("testCheckExpiredDeadlinesAndResetAlarm",
707 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
708
709 InOrder inOrder = inOrder(mAlarmManager);
710
711 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
712 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
713 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
714 inOrder.verify(mAlarmManager, times(1))
715 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
716 eq(TAG_DEADLINE), any(), any(), any());
717
718 advanceElapsedClock(10 * MINUTE_IN_MILLIS);
719
720 mTimeController.checkExpiredDeadlinesAndResetAlarm();
721 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
722 assertFalse(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
723 assertFalse(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
724 inOrder.verify(mAlarmManager, times(1))
725 .set(anyInt(), eq(now + 30 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
726 eq(TAG_DEADLINE), any(), any(), any());
727
728 advanceElapsedClock(30 * MINUTE_IN_MILLIS);
729
730 mTimeController.checkExpiredDeadlinesAndResetAlarm();
731 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
732 assertTrue(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
733 assertFalse(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
734 inOrder.verify(mAlarmManager, times(1))
735 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DEADLINE),
736 any(), any(), any());
737
738 advanceElapsedClock(30 * MINUTE_IN_MILLIS);
739
740 mTimeController.checkExpiredDeadlinesAndResetAlarm();
741 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
742 assertTrue(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
743 assertTrue(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
744 inOrder.verify(mAlarmManager, never())
745 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
746 }
747
748 @Test
749 public void testCheckExpiredDeadlinesAndResetAlarm_WithSkipping_SomeNotReady() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700750 mConstants.SKIP_NOT_READY_JOBS = true;
751 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800752 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
753
754 JobStatus jobLatest = createJobStatus("testCheckExpiredDeadlinesAndResetAlarm",
755 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
756 JobStatus jobMiddle = createJobStatus("testCheckExpiredDeadlinesAndResetAlarm",
757 createJob().setOverrideDeadline(30 * MINUTE_IN_MILLIS));
758 JobStatus jobEarliest = createJobStatus("testCheckExpiredDeadlinesAndResetAlarm",
759 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
760
761 doReturn(true).when(mTimeController)
762 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
763 doReturn(false).when(mTimeController)
764 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
765 doReturn(true).when(mTimeController)
766 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
767
768 InOrder inOrder = inOrder(mAlarmManager);
769
770 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
771 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
772 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
773 inOrder.verify(mAlarmManager, times(1))
774 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
775 eq(TAG_DEADLINE), any(), any(), any());
776
777 advanceElapsedClock(10 * MINUTE_IN_MILLIS);
778
779 mTimeController.checkExpiredDeadlinesAndResetAlarm();
780 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
781 assertFalse(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
782 assertFalse(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
783 // Middle job wouldn't be ready, so its alarm should be skipped.
784 inOrder.verify(mAlarmManager, times(1))
785 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DEADLINE),
786 any(), any(), any());
787
788 advanceElapsedClock(55 * MINUTE_IN_MILLIS);
789
790 mTimeController.checkExpiredDeadlinesAndResetAlarm();
791 assertTrue(jobEarliest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
792 assertTrue(jobMiddle.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
793 assertTrue(jobLatest.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
794 inOrder.verify(mAlarmManager, never())
795 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
796 }
797
798 @Test
799 public void testEvaluateStateLocked_SkippingOff() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700800 mConstants.SKIP_NOT_READY_JOBS = false;
801 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800802 JobStatus job = createJobStatus("testEvaluateStateLocked_SkippingOff",
803 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
804
805 mTimeController.evaluateStateLocked(job);
806 verify(mAlarmManager, never())
807 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
808 }
809
810 @Test
811 public void testEvaluateStateLocked_SkippingOn_Delay() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700812 mConstants.SKIP_NOT_READY_JOBS = true;
813 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800814 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
815
816 JobStatus jobLatest = createJobStatus("testEvaluateStateLocked_SkippingOn_Delay",
817 createJob().setMinimumLatency(HOUR_IN_MILLIS));
818 JobStatus jobMiddle = createJobStatus("testEvaluateStateLocked_SkippingOn_Delay",
819 createJob().setMinimumLatency(30 * MINUTE_IN_MILLIS));
820 JobStatus jobEarliest = createJobStatus("testEvaluateStateLocked_SkippingOn_Delay",
821 createJob().setMinimumLatency(5 * MINUTE_IN_MILLIS));
822
823 doReturn(false).when(mTimeController)
824 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
825 doReturn(true).when(mTimeController)
826 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
827 doReturn(false).when(mTimeController)
828 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
829
830 InOrder inOrder = inOrder(mAlarmManager);
831
832 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
833 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
834 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
835 inOrder.verify(mAlarmManager, times(1))
836 .set(anyInt(), eq(now + 30 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
837 any(), any(), any());
838
839 // Test evaluating something after the current deadline.
840 doReturn(true).when(mTimeController)
841 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
842 mTimeController.evaluateStateLocked(jobLatest);
843 inOrder.verify(mAlarmManager, never())
844 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
845
846 // Test evaluating something before the current deadline.
847 doReturn(true).when(mTimeController)
848 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
849 mTimeController.evaluateStateLocked(jobEarliest);
850 inOrder.verify(mAlarmManager, times(1))
851 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DELAY),
852 any(), any(), any());
853 // Job goes back to not being ready. Middle is still true, so use that alarm.
854 doReturn(false).when(mTimeController)
855 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
856 mTimeController.evaluateStateLocked(jobEarliest);
857 inOrder.verify(mAlarmManager, times(1))
858 .set(anyInt(), eq(now + 30 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
859 eq(TAG_DELAY), any(), any(), any());
860 // Turn middle off. Latest is true, so use that alarm.
861 doReturn(false).when(mTimeController)
862 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
863 mTimeController.evaluateStateLocked(jobMiddle);
864 inOrder.verify(mAlarmManager, times(1))
865 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(),
866 eq(TAG_DELAY), any(), any(), any());
867 }
868
869 @Test
870 public void testEvaluateStateLocked_SkippingOn_Deadline() {
Kweku Adams4e774a32019-04-24 18:01:29 -0700871 mConstants.SKIP_NOT_READY_JOBS = true;
872 mTimeController.recheckAlarmsLocked();
Kweku Adamsbffea5a2018-12-13 22:13:28 -0800873 final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
874
875 JobStatus jobLatest = createJobStatus("testEvaluateStateLocked_SkippingOn_Deadline",
876 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
877 JobStatus jobMiddle = createJobStatus("testEvaluateStateLocked_SkippingOn_Deadline",
878 createJob().setOverrideDeadline(30 * MINUTE_IN_MILLIS));
879 JobStatus jobEarliest = createJobStatus("testEvaluateStateLocked_SkippingOn_Deadline",
880 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
881
882 doReturn(false).when(mTimeController)
883 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
884 doReturn(true).when(mTimeController)
885 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
886 doReturn(false).when(mTimeController)
887 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
888
889 InOrder inOrder = inOrder(mAlarmManager);
890
891 mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
892 mTimeController.maybeStartTrackingJobLocked(jobMiddle, null);
893 mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
894 inOrder.verify(mAlarmManager, times(1))
895 .set(anyInt(), eq(now + 30 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
896 eq(TAG_DEADLINE), any(), any(), any());
897
898 // Test evaluating something after the current deadline.
899 doReturn(true).when(mTimeController)
900 .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
901 mTimeController.evaluateStateLocked(jobLatest);
902 inOrder.verify(mAlarmManager, never())
903 .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
904
905 // Test evaluating something before the current deadline.
906 doReturn(true).when(mTimeController)
907 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
908 mTimeController.evaluateStateLocked(jobEarliest);
909 inOrder.verify(mAlarmManager, times(1))
910 .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
911 eq(TAG_DEADLINE), any(), any(), any());
912 // Job goes back to not being ready. Middle is still true, so use that alarm.
913 doReturn(false).when(mTimeController)
914 .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
915 mTimeController.evaluateStateLocked(jobEarliest);
916 inOrder.verify(mAlarmManager, times(1))
917 .set(anyInt(), eq(now + 30 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
918 eq(TAG_DEADLINE), any(), any(), any());
919 // Turn middle off. Latest is true, so use that alarm.
920 doReturn(false).when(mTimeController)
921 .wouldBeReadyWithConstraintLocked(eq(jobMiddle), anyInt());
922 mTimeController.evaluateStateLocked(jobMiddle);
923 inOrder.verify(mAlarmManager, times(1))
924 .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(),
925 eq(TAG_DEADLINE), any(), any(), any());
926 }
927}