blob: d79795593456b9d6e1dd6021efb20358e46c7caf [file] [log] [blame]
Neil Fuller4773b9d2018-06-08 18:44:49 +01001/*
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.timedetector;
18
Neil Fuller4980bbc2018-06-12 21:06:20 +010019import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertNotNull;
22import static org.junit.Assert.assertNull;
23import static org.junit.Assert.assertTrue;
24import static org.junit.Assert.fail;
Neil Fuller4773b9d2018-06-08 18:44:49 +010025
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010026import android.app.timedetector.PhoneTimeSuggestion;
Neil Fuller4980bbc2018-06-12 21:06:20 +010027import android.content.Intent;
28import android.icu.util.Calendar;
29import android.icu.util.GregorianCalendar;
30import android.icu.util.TimeZone;
Neil Fuller4773b9d2018-06-08 18:44:49 +010031import android.util.TimestampedValue;
32
Brett Chabot8091d9e2019-02-26 14:52:33 -080033import androidx.test.runner.AndroidJUnit4;
34
Neil Fuller4773b9d2018-06-08 18:44:49 +010035import org.junit.Before;
36import org.junit.Test;
37import org.junit.runner.RunWith;
38
39@RunWith(AndroidJUnit4.class)
40public class SimpleTimeZoneDetectorStrategyTest {
41
Neil Fuller4980bbc2018-06-12 21:06:20 +010042 private static final Scenario SCENARIO_1 = new Scenario.Builder()
43 .setInitialDeviceSystemClockUtc(1977, 1, 1, 12, 0, 0)
44 .setInitialDeviceRealtimeMillis(123456789L)
45 .setActualTimeUtc(2018, 1, 1, 12, 0, 0)
46 .build();
Neil Fuller4773b9d2018-06-08 18:44:49 +010047
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010048 private static final int ARBITRARY_PHONE_ID = 123456;
49
Neil Fuller4980bbc2018-06-12 21:06:20 +010050 private Script mScript;
Neil Fuller4773b9d2018-06-08 18:44:49 +010051
52 @Before
53 public void setUp() {
Neil Fuller4980bbc2018-06-12 21:06:20 +010054 mScript = new Script();
Neil Fuller4773b9d2018-06-08 18:44:49 +010055 }
56
57 @Test
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010058 public void testSuggestPhoneTime_nitz_timeDetectionEnabled() {
Neil Fuller4980bbc2018-06-12 21:06:20 +010059 Scenario scenario = SCENARIO_1;
60 mScript.pokeFakeClocks(scenario)
61 .pokeTimeDetectionEnabled(true);
Neil Fuller4773b9d2018-06-08 18:44:49 +010062
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010063 PhoneTimeSuggestion timeSuggestion =
64 scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
Neil Fuller4980bbc2018-06-12 21:06:20 +010065 final int clockIncrement = 1000;
66 long expectSystemClockMillis = scenario.getActualTimeMillis() + clockIncrement;
Neil Fuller4773b9d2018-06-08 18:44:49 +010067
Neil Fuller4980bbc2018-06-12 21:06:20 +010068 mScript.simulateTimePassing(clockIncrement)
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010069 .simulatePhoneTimeSuggestion(timeSuggestion)
Neil Fuller4980bbc2018-06-12 21:06:20 +010070 .verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis);
71 }
72
73 @Test
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010074 public void testSuggestPhoneTime_systemClockThreshold() {
Neil Fuller4980bbc2018-06-12 21:06:20 +010075 Scenario scenario = SCENARIO_1;
76 final int systemClockUpdateThresholdMillis = 1000;
77 mScript.pokeFakeClocks(scenario)
78 .pokeThresholds(systemClockUpdateThresholdMillis)
79 .pokeTimeDetectionEnabled(true);
80
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010081 PhoneTimeSuggestion timeSuggestion1 =
82 scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
83 TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
Neil Fuller4980bbc2018-06-12 21:06:20 +010084
85 final int clockIncrement = 100;
86 // Increment the the device clocks to simulate the passage of time.
87 mScript.simulateTimePassing(clockIncrement);
88
89 long expectSystemClockMillis1 =
90 TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
91
92 // Send the first time signal. It should be used.
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010093 mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
Neil Fuller4980bbc2018-06-12 21:06:20 +010094 .verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis1);
95
96 // Now send another time signal, but one that is too similar to the last one and should be
97 // ignored.
98 int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
99 TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
100 mScript.peekElapsedRealtimeMillis(),
101 mScript.peekSystemClockMillis() + underThresholdMillis);
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100102 PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
Neil Fuller4980bbc2018-06-12 21:06:20 +0100103 mScript.simulateTimePassing(clockIncrement)
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100104 .simulatePhoneTimeSuggestion(timeSuggestion2)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100105 .verifySystemClockWasNotSetAndResetCallTracking();
106
107 // Now send another time signal, but one that is on the threshold and so should be used.
108 TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
109 mScript.peekElapsedRealtimeMillis(),
110 mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
111
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100112 PhoneTimeSuggestion timeSuggestion3 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
Neil Fuller4980bbc2018-06-12 21:06:20 +0100113 mScript.simulateTimePassing(clockIncrement);
114
115 long expectSystemClockMillis3 =
116 TimeDetectorStrategy.getTimeAt(utcTime3, mScript.peekElapsedRealtimeMillis());
117
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100118 mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100119 .verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis3);
120 }
121
122 @Test
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100123 public void testSuggestPhoneTime_nitz_timeDetectionDisabled() {
Neil Fuller4980bbc2018-06-12 21:06:20 +0100124 Scenario scenario = SCENARIO_1;
125 mScript.pokeFakeClocks(scenario)
126 .pokeTimeDetectionEnabled(false);
127
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100128 PhoneTimeSuggestion timeSuggestion =
129 scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
130 mScript.simulatePhoneTimeSuggestion(timeSuggestion)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100131 .verifySystemClockWasNotSetAndResetCallTracking();
132 }
133
134 @Test
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100135 public void testSuggestPhoneTime_nitz_invalidNitzReferenceTimesIgnored() {
Neil Fuller4980bbc2018-06-12 21:06:20 +0100136 Scenario scenario = SCENARIO_1;
137 final int systemClockUpdateThreshold = 2000;
138 mScript.pokeFakeClocks(scenario)
139 .pokeThresholds(systemClockUpdateThreshold)
140 .pokeTimeDetectionEnabled(true);
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100141 PhoneTimeSuggestion timeSuggestion1 =
142 scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
143 TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
Neil Fuller4980bbc2018-06-12 21:06:20 +0100144
145 // Initialize the strategy / device with a time set from NITZ.
146 mScript.simulateTimePassing(100);
147 long expectedSystemClockMillis1 =
148 TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100149 mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100150 .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1);
151
152 // The UTC time increment should be larger than the system clock update threshold so we
153 // know it shouldn't be ignored for other reasons.
154 long validUtcTimeMillis = utcTime1.getValue() + (2 * systemClockUpdateThreshold);
155
156 // Now supply a new signal that has an obviously bogus reference time : older than the last
157 // one.
158 long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
159 TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
160 referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100161 PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
162 mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100163 .verifySystemClockWasNotSetAndResetCallTracking();
164
165 // Now supply a new signal that has an obviously bogus reference time : substantially in the
166 // future.
167 long referenceTimeInFutureMillis =
168 utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
169 TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
170 referenceTimeInFutureMillis, validUtcTimeMillis);
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100171 PhoneTimeSuggestion timeSuggestion3 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
172 mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100173 .verifySystemClockWasNotSetAndResetCallTracking();
174
175 // Just to prove validUtcTimeMillis is valid.
176 long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
177 TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
178 validReferenceTimeMillis, validUtcTimeMillis);
179 long expectedSystemClockMillis4 =
180 TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100181 PhoneTimeSuggestion timeSuggestion4 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime4);
182 mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100183 .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4);
184 }
185
186 @Test
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100187 public void testSuggestPhoneTime_timeDetectionToggled() {
Neil Fuller4980bbc2018-06-12 21:06:20 +0100188 Scenario scenario = SCENARIO_1;
189 final int clockIncrementMillis = 100;
190 final int systemClockUpdateThreshold = 2000;
191 mScript.pokeFakeClocks(scenario)
192 .pokeThresholds(systemClockUpdateThreshold)
193 .pokeTimeDetectionEnabled(false);
194
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100195 PhoneTimeSuggestion timeSuggestion1 =
196 scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
197 TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
Neil Fuller4980bbc2018-06-12 21:06:20 +0100198
199 // Simulate time passing.
200 mScript.simulateTimePassing(clockIncrementMillis);
201
202 // Simulate the time signal being received. It should not be used because auto time
203 // detection is off but it should be recorded.
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100204 mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100205 .verifySystemClockWasNotSetAndResetCallTracking();
206
207 // Simulate more time passing.
208 mScript.simulateTimePassing(clockIncrementMillis);
209
210 long expectedSystemClockMillis1 =
211 TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
212
213 // Turn on auto time detection.
214 mScript.simulateAutoTimeDetectionToggle()
215 .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1);
216
217 // Turn off auto time detection.
218 mScript.simulateAutoTimeDetectionToggle()
219 .verifySystemClockWasNotSetAndResetCallTracking();
220
221 // Receive another valid time signal.
222 // It should be on the threshold and accounting for the clock increments.
223 TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
224 mScript.peekElapsedRealtimeMillis(),
225 mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100226 PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
Neil Fuller4980bbc2018-06-12 21:06:20 +0100227
228 // Simulate more time passing.
229 mScript.simulateTimePassing(clockIncrementMillis);
230
231 long expectedSystemClockMillis2 =
232 TimeDetectorStrategy.getTimeAt(utcTime2, mScript.peekElapsedRealtimeMillis());
233
234 // The new time, though valid, should not be set in the system clock because auto time is
235 // disabled.
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100236 mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
Neil Fuller4980bbc2018-06-12 21:06:20 +0100237 .verifySystemClockWasNotSetAndResetCallTracking();
238
239 // Turn on auto time detection.
240 mScript.simulateAutoTimeDetectionToggle()
241 .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2);
Neil Fuller4773b9d2018-06-08 18:44:49 +0100242 }
243
Neil Fuller4980bbc2018-06-12 21:06:20 +0100244 /**
245 * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
246 * like the real thing should, it also asserts preconditions.
247 */
248 private static class FakeCallback implements TimeDetectorStrategy.Callback {
249 private boolean mTimeDetectionEnabled;
250 private boolean mWakeLockAcquired;
251 private long mElapsedRealtimeMillis;
252 private long mSystemClockMillis;
253 private int mSystemClockUpdateThresholdMillis = 2000;
254
255 // Tracking operations.
256 private boolean mSystemClockWasSet;
257 private Intent mBroadcastSent;
258
259 @Override
260 public int systemClockUpdateThresholdMillis() {
261 return mSystemClockUpdateThresholdMillis;
262 }
263
264 @Override
265 public boolean isTimeDetectionEnabled() {
266 return mTimeDetectionEnabled;
267 }
268
269 @Override
270 public void acquireWakeLock() {
271 if (mWakeLockAcquired) {
272 fail("Wake lock already acquired");
273 }
274 mWakeLockAcquired = true;
275 }
276
277 @Override
278 public long elapsedRealtimeMillis() {
279 assertWakeLockAcquired();
280 return mElapsedRealtimeMillis;
281 }
282
283 @Override
284 public long systemClockMillis() {
285 assertWakeLockAcquired();
286 return mSystemClockMillis;
287 }
288
289 @Override
290 public void setSystemClock(long newTimeMillis) {
291 assertWakeLockAcquired();
292 mSystemClockWasSet = true;
293 mSystemClockMillis = newTimeMillis;
294 }
295
296 @Override
297 public void releaseWakeLock() {
298 assertWakeLockAcquired();
299 mWakeLockAcquired = false;
300 }
301
302 @Override
303 public void sendStickyBroadcast(Intent intent) {
304 assertNotNull(intent);
305 mBroadcastSent = intent;
306 }
307
308 // Methods below are for managing the fake's behavior.
309
310 public void pokeSystemClockUpdateThreshold(int thresholdMillis) {
311 mSystemClockUpdateThresholdMillis = thresholdMillis;
312 }
313
314 public void pokeElapsedRealtimeMillis(long elapsedRealtimeMillis) {
315 mElapsedRealtimeMillis = elapsedRealtimeMillis;
316 }
317
318 public void pokeSystemClockMillis(long systemClockMillis) {
319 mSystemClockMillis = systemClockMillis;
320 }
321
322 public void pokeTimeDetectionEnabled(boolean enabled) {
323 mTimeDetectionEnabled = enabled;
324 }
325
326 public long peekElapsedRealtimeMillis() {
327 return mElapsedRealtimeMillis;
328 }
329
330 public long peekSystemClockMillis() {
331 return mSystemClockMillis;
332 }
333
334 public void simulateTimePassing(int incrementMillis) {
335 mElapsedRealtimeMillis += incrementMillis;
336 mSystemClockMillis += incrementMillis;
337 }
338
339 public void verifySystemClockNotSet() {
340 assertFalse(mSystemClockWasSet);
341 }
342
343 public void verifySystemClockWasSet(long expectSystemClockMillis) {
344 assertTrue(mSystemClockWasSet);
345 assertEquals(expectSystemClockMillis, mSystemClockMillis);
346 }
347
348 public void verifyIntentWasBroadcast() {
349 assertTrue(mBroadcastSent != null);
350 }
351
352 public void verifyIntentWasNotBroadcast() {
353 assertNull(mBroadcastSent);
354 }
355
356 public void resetCallTracking() {
357 mSystemClockWasSet = false;
358 mBroadcastSent = null;
359 }
360
361 private void assertWakeLockAcquired() {
362 assertTrue("The operation must be performed only after acquiring the wakelock",
363 mWakeLockAcquired);
364 }
365 }
366
367 /**
368 * A fluent helper class for tests.
369 */
370 private class Script {
371
372 private final FakeCallback mFakeCallback;
373 private final SimpleTimeDetectorStrategy mSimpleTimeDetectorStrategy;
374
375 public Script() {
376 mFakeCallback = new FakeCallback();
377 mSimpleTimeDetectorStrategy = new SimpleTimeDetectorStrategy();
378 mSimpleTimeDetectorStrategy.initialize(mFakeCallback);
379
380 }
381
382 Script pokeTimeDetectionEnabled(boolean enabled) {
383 mFakeCallback.pokeTimeDetectionEnabled(enabled);
384 return this;
385 }
386
387 Script pokeFakeClocks(Scenario scenario) {
388 mFakeCallback.pokeElapsedRealtimeMillis(scenario.getInitialRealTimeMillis());
389 mFakeCallback.pokeSystemClockMillis(scenario.getInitialSystemClockMillis());
390 return this;
391 }
392
393 Script pokeThresholds(int systemClockUpdateThreshold) {
394 mFakeCallback.pokeSystemClockUpdateThreshold(systemClockUpdateThreshold);
395 return this;
396 }
397
398 long peekElapsedRealtimeMillis() {
399 return mFakeCallback.peekElapsedRealtimeMillis();
400 }
401
402 long peekSystemClockMillis() {
403 return mFakeCallback.peekSystemClockMillis();
404 }
405
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100406 Script simulatePhoneTimeSuggestion(PhoneTimeSuggestion timeSuggestion) {
407 mSimpleTimeDetectorStrategy.suggestPhoneTime(timeSuggestion);
Neil Fuller4980bbc2018-06-12 21:06:20 +0100408 return this;
409 }
410
411 Script simulateAutoTimeDetectionToggle() {
412 boolean enabled = !mFakeCallback.isTimeDetectionEnabled();
413 mFakeCallback.pokeTimeDetectionEnabled(enabled);
414 mSimpleTimeDetectorStrategy.handleAutoTimeDetectionToggle(enabled);
415 return this;
416 }
417
418 Script simulateTimePassing(int clockIncrement) {
419 mFakeCallback.simulateTimePassing(clockIncrement);
420 return this;
421 }
422
423 Script verifySystemClockWasNotSetAndResetCallTracking() {
424 mFakeCallback.verifySystemClockNotSet();
425 mFakeCallback.verifyIntentWasNotBroadcast();
426 mFakeCallback.resetCallTracking();
427 return this;
428 }
429
430 Script verifySystemClockWasSetAndResetCallTracking(long expectSystemClockMillis) {
431 mFakeCallback.verifySystemClockWasSet(expectSystemClockMillis);
432 mFakeCallback.verifyIntentWasBroadcast();
433 mFakeCallback.resetCallTracking();
434 return this;
435 }
436 }
437
438 /**
439 * A starting scenario used during tests. Describes a fictional "physical" reality.
440 */
441 private static class Scenario {
442
443 private final long mInitialDeviceSystemClockMillis;
444 private final long mInitialDeviceRealtimeMillis;
445 private final long mActualTimeMillis;
446
447 Scenario(long initialDeviceSystemClock, long elapsedRealtime, long timeMillis) {
448 mInitialDeviceSystemClockMillis = initialDeviceSystemClock;
449 mActualTimeMillis = timeMillis;
450 mInitialDeviceRealtimeMillis = elapsedRealtime;
451 }
452
453 long getInitialRealTimeMillis() {
454 return mInitialDeviceRealtimeMillis;
455 }
456
457 long getInitialSystemClockMillis() {
458 return mInitialDeviceSystemClockMillis;
459 }
460
461 long getActualTimeMillis() {
462 return mActualTimeMillis;
463 }
464
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100465 PhoneTimeSuggestion createPhoneTimeSuggestionForActual(int phoneId) {
Neil Fuller4980bbc2018-06-12 21:06:20 +0100466 TimestampedValue<Long> time = new TimestampedValue<>(
467 mInitialDeviceRealtimeMillis, mActualTimeMillis);
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100468 return new PhoneTimeSuggestion(phoneId, time);
Neil Fuller4980bbc2018-06-12 21:06:20 +0100469 }
470
471 static class Builder {
472
473 private long mInitialDeviceSystemClockMillis;
474 private long mInitialDeviceRealtimeMillis;
475 private long mActualTimeMillis;
476
477 Builder setInitialDeviceSystemClockUtc(int year, int monthInYear, int day,
478 int hourOfDay, int minute, int second) {
479 mInitialDeviceSystemClockMillis = createUtcTime(year, monthInYear, day, hourOfDay,
480 minute, second);
481 return this;
482 }
483
484 Builder setInitialDeviceRealtimeMillis(long realtimeMillis) {
485 mInitialDeviceRealtimeMillis = realtimeMillis;
486 return this;
487 }
488
489 Builder setActualTimeUtc(int year, int monthInYear, int day, int hourOfDay,
490 int minute, int second) {
491 mActualTimeMillis =
492 createUtcTime(year, monthInYear, day, hourOfDay, minute, second);
493 return this;
494 }
495
496 Scenario build() {
497 return new Scenario(mInitialDeviceSystemClockMillis, mInitialDeviceRealtimeMillis,
498 mActualTimeMillis);
499 }
500 }
501 }
502
503 private static long createUtcTime(int year, int monthInYear, int day, int hourOfDay, int minute,
504 int second) {
505 Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/UTC"));
506 cal.clear();
507 cal.set(year, monthInYear - 1, day, hourOfDay, minute, second);
508 return cal.getTimeInMillis();
Neil Fuller4773b9d2018-06-08 18:44:49 +0100509 }
510}