NightDisplayServiceTest.java revision 3da4c44d73fa038c3f24ac1a25395469d4a91394
1/*
2 * Copyright (C) 2017 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;
18
19import android.annotation.NonNull;
20import android.app.ActivityManager;
21import android.app.AlarmManager;
22import android.content.Context;
23import android.content.ContextWrapper;
24import android.os.Handler;
25import android.os.UserHandle;
26import android.provider.Settings;
27import android.provider.Settings.Secure;
28import android.support.test.InstrumentationRegistry;
29import android.support.test.runner.AndroidJUnit4;
30import android.test.mock.MockContentResolver;
31
32import com.android.internal.app.NightDisplayController;
33import com.android.internal.app.NightDisplayController.LocalTime;
34import com.android.internal.util.test.FakeSettingsProvider;
35import com.android.server.display.DisplayTransformManager;
36import com.android.server.display.NightDisplayService;
37import com.android.server.twilight.TwilightListener;
38import com.android.server.twilight.TwilightManager;
39import com.android.server.twilight.TwilightState;
40import org.junit.After;
41import org.junit.Before;
42import org.junit.Test;
43import org.junit.runner.RunWith;
44import org.mockito.Mockito;
45
46import java.util.Calendar;
47import java.util.HashMap;
48import java.util.Map;
49import java.util.concurrent.CountDownLatch;
50import java.util.concurrent.TimeUnit;
51
52import static com.google.common.truth.Truth.assertWithMessage;
53import static org.mockito.Mockito.doReturn;
54
55@RunWith(AndroidJUnit4.class)
56public class NightDisplayServiceTest {
57
58    private Context mContext;
59    private int mUserId;
60
61    private MockTwilightManager mTwilightManager;
62
63    private NightDisplayController mNightDisplayController;
64    private NightDisplayService mNightDisplayService;
65
66    @Before
67    public void setUp() {
68        mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
69        mUserId = ActivityManager.getCurrentUser();
70
71        doReturn(mContext).when(mContext).getApplicationContext();
72
73        final MockContentResolver cr = new MockContentResolver(mContext);
74        cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
75        doReturn(cr).when(mContext).getContentResolver();
76
77        final AlarmManager am = Mockito.mock(AlarmManager.class);
78        doReturn(am).when(mContext).getSystemService(Context.ALARM_SERVICE);
79
80        final DisplayTransformManager dtm = Mockito.mock(DisplayTransformManager.class);
81        LocalServices.addService(DisplayTransformManager.class, dtm);
82
83        mTwilightManager = new MockTwilightManager();
84        LocalServices.addService(TwilightManager.class, mTwilightManager);
85
86        mNightDisplayController = new NightDisplayController(mContext, mUserId);
87        mNightDisplayService = new NightDisplayService(mContext);
88    }
89
90    @After
91    public void tearDown() {
92        LocalServices.removeServiceForTest(DisplayTransformManager.class);
93        LocalServices.removeServiceForTest(TwilightManager.class);
94
95        mNightDisplayService = null;
96        mNightDisplayController = null;
97
98        mTwilightManager = null;
99
100        mUserId = UserHandle.USER_NULL;
101        mContext = null;
102    }
103
104    @Test
105    public void customSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
106        setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
107        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
108
109        startService();
110        assertActivated(false /* activated */);
111    }
112
113    @Test
114    public void customSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
115        setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
116        setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
117
118        startService();
119        assertActivated(false /* activated */);
120    }
121
122    @Test
123    public void customSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
124        setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
125        setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
126
127        startService();
128        assertActivated(false /* activated */);
129    }
130
131    @Test
132    public void customSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
133        setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
134        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
135
136        startService();
137        assertActivated(false /* activated */);
138    }
139
140    @Test
141    public void customSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
142        setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
143        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
144
145        startService();
146        assertActivated(true /* activated */);
147    }
148
149    @Test
150    public void customSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
151        setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
152        setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
153
154        startService();
155        assertActivated(false /* activated */);
156    }
157
158    @Test
159    public void customSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
160        setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
161        setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
162
163        startService();
164        assertActivated(false /* activated */);
165    }
166
167    @Test
168    public void customSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
169        setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
170        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
171
172        startService();
173        assertActivated(false /* activated */);
174    }
175
176    @Test
177    public void customSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
178        setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
179        setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
180
181        startService();
182        assertActivated(false /* activated */);
183    }
184
185    @Test
186    public void customSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
187        setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
188        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
189
190        startService();
191        assertActivated(false /* activated */);
192    }
193
194    @Test
195    public void customSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
196        setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
197        setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
198
199        startService();
200        assertActivated(false /* activated */);
201    }
202
203    @Test
204    public void customSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
205        setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
206        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
207
208        startService();
209        assertActivated(false /* activated */);
210    }
211
212    @Test
213    public void customSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
214        setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
215        setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
216
217        startService();
218        assertActivated(false /* activated */);
219    }
220
221    @Test
222    public void customSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
223        setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
224        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
225
226        startService();
227        assertActivated(false /* activated */);
228    }
229
230    @Test
231    public void customSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
232        setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
233        setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
234
235        startService();
236        assertActivated(false /* activated */);
237    }
238
239    @Test
240    public void customSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
241        setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
242        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
243
244        startService();
245        assertActivated(true /* activated */);
246    }
247
248    @Test
249    public void customSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
250        setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
251        setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
252
253        startService();
254        assertActivated(true /* activated */);
255    }
256
257    @Test
258    public void customSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
259        setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
260        setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
261
262        startService();
263        assertActivated(true /* activated */);
264    }
265
266    @Test
267    public void customSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
268        setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
269        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
270
271        startService();
272        assertActivated(true /* activated */);
273    }
274
275    @Test
276    public void customSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
277        setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
278        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
279
280        startService();
281        assertActivated(false /* activated */);
282    }
283
284    @Test
285    public void customSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
286        setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
287        setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
288
289        startService();
290        assertActivated(true /* activated */);
291    }
292
293    @Test
294    public void customSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
295        setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
296        setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
297
298        startService();
299        assertActivated(true /* activated */);
300    }
301
302    @Test
303    public void customSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
304        setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
305        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
306
307        startService();
308        assertActivated(true /* activated */);
309    }
310
311    @Test
312    public void customSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
313        setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
314        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
315
316        startService();
317        assertActivated(true /* activated */);
318    }
319
320    @Test
321    public void twilightSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
322        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
323        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
324
325        startService();
326        assertActivated(false /* activated */);
327    }
328
329    @Test
330    public void twilightSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
331        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
332        setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
333
334        startService();
335        assertActivated(false /* activated */);
336    }
337
338    @Test
339    public void twilightSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
340        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
341        setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
342
343        startService();
344        assertActivated(false /* activated */);
345    }
346
347    @Test
348    public void twilightSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
349        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
350        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
351
352        startService();
353        assertActivated(false /* activated */);
354    }
355
356    @Test
357    public void twilightSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
358        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
359        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
360
361        startService();
362        assertActivated(true /* activated */);
363    }
364
365    @Test
366    public void twilightSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
367        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
368        setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
369
370        startService();
371        assertActivated(false /* activated */);
372    }
373
374    @Test
375    public void twilightSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
376        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
377        setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
378
379        startService();
380        assertActivated(false /* activated */);
381    }
382
383    @Test
384    public void twilightSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
385        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
386        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
387
388        startService();
389        assertActivated(false /* activated */);
390    }
391
392    @Test
393    public void twilightSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
394        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
395        setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
396
397        startService();
398        assertActivated(false /* activated */);
399    }
400
401    @Test
402    public void twilightSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
403        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
404        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
405
406        startService();
407        assertActivated(false /* activated */);
408    }
409
410    @Test
411    public void twilightSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
412        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
413        setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
414
415        startService();
416        assertActivated(false /* activated */);
417    }
418
419    @Test
420    public void twilightSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
421        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
422        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
423
424        startService();
425        assertActivated(false /* activated */);
426    }
427
428    @Test
429    public void twilightSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
430        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
431        setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
432
433        startService();
434        assertActivated(false /* activated */);
435    }
436
437    @Test
438    public void twilightSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
439        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
440        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
441
442        startService();
443        assertActivated(false /* activated */);
444    }
445
446    @Test
447    public void twilightSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
448        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
449        setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
450
451        startService();
452        assertActivated(false /* activated */);
453    }
454
455    @Test
456    public void twilightSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
457        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
458        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
459
460        startService();
461        assertActivated(true /* activated */);
462    }
463
464    @Test
465    public void twilightSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
466        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
467        setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
468
469        startService();
470        assertActivated(true /* activated */);
471    }
472
473    @Test
474    public void twilightSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
475        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
476        setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
477
478        startService();
479        assertActivated(true /* activated */);
480    }
481
482    @Test
483    public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
484        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
485        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
486
487        startService();
488        assertActivated(true /* activated */);
489    }
490
491    @Test
492    public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
493        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
494        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
495
496        startService();
497        assertActivated(false /* activated */);
498    }
499
500    @Test
501    public void twilightSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
502        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
503        setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
504
505        startService();
506        assertActivated(true /* activated */);
507    }
508
509    @Test
510    public void twilightSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
511        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
512        setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
513
514        startService();
515        assertActivated(true /* activated */);
516    }
517
518    @Test
519    public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
520        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
521        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
522
523        startService();
524        assertActivated(true /* activated */);
525    }
526
527    @Test
528    public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
529        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
530        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
531
532        startService();
533        assertActivated(true /* activated */);
534    }
535
536    @Test
537    public void twilightSchedule_whenRebootedAfterNight_ifOffAfterNight_turnsOff() {
538        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
539        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
540
541        final TwilightState state = mTwilightManager.getLastTwilightState();
542        mTwilightManager.setTwilightState(null);
543
544        startService();
545        assertActivated(false /* activated */);
546
547        mTwilightManager.setTwilightState(state);
548        assertActivated(false /* activated */);
549    }
550
551    @Test
552    public void twilightSchedule_whenRebootedAfterNight_ifOffBeforeNight_turnsOff() {
553        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
554        setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
555
556        final TwilightState state = mTwilightManager.getLastTwilightState();
557        mTwilightManager.setTwilightState(null);
558
559        startService();
560        assertActivated(false /* activated */);
561
562        mTwilightManager.setTwilightState(state);
563        assertActivated(false /* activated */);
564    }
565
566    @Test
567    public void twilightSchedule_whenRebootedAfterNight_ifOffDuringNight_turnsOff() {
568        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
569        setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
570
571        final TwilightState state = mTwilightManager.getLastTwilightState();
572        mTwilightManager.setTwilightState(null);
573
574        startService();
575        assertActivated(false /* activated */);
576
577        mTwilightManager.setTwilightState(state);
578        assertActivated(false /* activated */);
579    }
580
581    @Test
582    public void twilightSchedule_whenRebootedAfterNight_ifOffInFuture_turnsOff() {
583        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
584        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
585
586        final TwilightState state = mTwilightManager.getLastTwilightState();
587        mTwilightManager.setTwilightState(null);
588
589        startService();
590        assertActivated(false /* activated */);
591
592        mTwilightManager.setTwilightState(state);
593        assertActivated(false /* activated */);
594    }
595
596    @Test
597    public void twilightSchedule_whenRebootedAfterNight_ifOnAfterNight_turnsOn() {
598        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
599        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
600
601        final TwilightState state = mTwilightManager.getLastTwilightState();
602        mTwilightManager.setTwilightState(null);
603
604        startService();
605        assertActivated(true /* activated */);
606
607        mTwilightManager.setTwilightState(state);
608        assertActivated(true /* activated */);
609    }
610
611    @Test
612    public void twilightSchedule_whenRebootedAfterNight_ifOnBeforeNight_turnsOff() {
613        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
614        setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
615
616        final TwilightState state = mTwilightManager.getLastTwilightState();
617        mTwilightManager.setTwilightState(null);
618
619        startService();
620        assertActivated(true /* activated */);
621
622        mTwilightManager.setTwilightState(state);
623        assertActivated(false /* activated */);
624    }
625
626    @Test
627    public void twilightSchedule_whenRebootedAfterNight_ifOnDuringNight_turnsOff() {
628        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
629        setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
630
631        final TwilightState state = mTwilightManager.getLastTwilightState();
632        mTwilightManager.setTwilightState(null);
633
634        startService();
635        assertActivated(true /* activated */);
636
637        mTwilightManager.setTwilightState(state);
638        assertActivated(false /* activated */);
639    }
640
641    @Test
642    public void twilightSchedule_whenRebootedAfterNight_ifOnInFuture_turnsOff() {
643        setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
644        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
645
646        final TwilightState state = mTwilightManager.getLastTwilightState();
647        mTwilightManager.setTwilightState(null);
648
649        startService();
650        assertActivated(true /* activated */);
651
652        mTwilightManager.setTwilightState(state);
653        assertActivated(false /* activated */);
654    }
655
656    @Test
657    public void twilightSchedule_whenRebootedBeforeNight_ifOffAfterNight_turnsOff() {
658        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
659        setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
660
661        final TwilightState state = mTwilightManager.getLastTwilightState();
662        mTwilightManager.setTwilightState(null);
663
664        startService();
665        assertActivated(false /* activated */);
666
667        mTwilightManager.setTwilightState(state);
668        assertActivated(false /* activated */);
669    }
670
671    @Test
672    public void twilightSchedule_whenRebootedBeforeNight_ifOffBeforeNight_turnsOff() {
673        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
674        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
675
676        final TwilightState state = mTwilightManager.getLastTwilightState();
677        mTwilightManager.setTwilightState(null);
678
679        startService();
680        assertActivated(false /* activated */);
681
682        mTwilightManager.setTwilightState(state);
683        assertActivated(false /* activated */);
684    }
685
686    @Test
687    public void twilightSchedule_whenRebootedBeforeNight_ifOffDuringNight_turnsOff() {
688        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
689        setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
690
691        final TwilightState state = mTwilightManager.getLastTwilightState();
692        mTwilightManager.setTwilightState(null);
693
694        startService();
695        assertActivated(false /* activated */);
696
697        mTwilightManager.setTwilightState(state);
698        assertActivated(false /* activated */);
699    }
700
701    @Test
702    public void twilightSchedule_whenRebootedBeforeNight_ifOffInPast_turnsOff() {
703        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
704        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
705
706        final TwilightState state = mTwilightManager.getLastTwilightState();
707        mTwilightManager.setTwilightState(null);
708
709        startService();
710        assertActivated(false /* activated */);
711
712        mTwilightManager.setTwilightState(state);
713        assertActivated(false /* activated */);
714    }
715
716    @Test
717    public void twilightSchedule_whenRebootedBeforeNight_ifOnAfterNight_turnsOff() {
718        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
719        setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
720
721        final TwilightState state = mTwilightManager.getLastTwilightState();
722        mTwilightManager.setTwilightState(null);
723
724        startService();
725        assertActivated(true /* activated */);
726
727        mTwilightManager.setTwilightState(state);
728        assertActivated(false /* activated */);
729    }
730
731    @Test
732    public void twilightSchedule_whenRebootedBeforeNight_ifOnBeforeNight_turnsOff() {
733        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
734        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
735
736        final TwilightState state = mTwilightManager.getLastTwilightState();
737        mTwilightManager.setTwilightState(null);
738
739        startService();
740        assertActivated(true /* activated */);
741
742        mTwilightManager.setTwilightState(state);
743        assertActivated(false /* activated */);
744    }
745
746    @Test
747    public void twilightSchedule_whenRebootedBeforeNight_ifOnDuringNight_turnsOff() {
748        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
749        setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
750
751        final TwilightState state = mTwilightManager.getLastTwilightState();
752        mTwilightManager.setTwilightState(null);
753
754        startService();
755        assertActivated(true /* activated */);
756
757        mTwilightManager.setTwilightState(state);
758        assertActivated(false /* activated */);
759    }
760
761    @Test
762    public void twilightSchedule_whenRebootedBeforeNight_ifOnInPast_turnsOn() {
763        setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
764        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
765
766        final TwilightState state = mTwilightManager.getLastTwilightState();
767        mTwilightManager.setTwilightState(null);
768
769        startService();
770        assertActivated(true /* activated */);
771
772        mTwilightManager.setTwilightState(state);
773        assertActivated(true /* activated */);
774    }
775
776    @Test
777    public void twilightSchedule_whenRebootedDuringNight_ifOffAfterNight_turnsOn() {
778        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
779        setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
780
781        final TwilightState state = mTwilightManager.getLastTwilightState();
782        mTwilightManager.setTwilightState(null);
783
784        startService();
785        assertActivated(false /* activated */);
786
787        mTwilightManager.setTwilightState(state);
788        assertActivated(true /* activated */);
789    }
790
791    @Test
792    public void twilightSchedule_whenRebootedDuringNight_ifOffBeforeNight_turnsOn() {
793        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
794        setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
795
796        final TwilightState state = mTwilightManager.getLastTwilightState();
797        mTwilightManager.setTwilightState(null);
798
799        startService();
800        assertActivated(false /* activated */);
801
802        mTwilightManager.setTwilightState(state);
803        assertActivated(true /* activated */);
804    }
805
806    @Test
807    public void twilightSchedule_whenRebootedDuringNight_ifOffDuringNightInFuture_turnsOn() {
808        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
809        setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
810
811        final TwilightState state = mTwilightManager.getLastTwilightState();
812        mTwilightManager.setTwilightState(null);
813
814        startService();
815        assertActivated(false /* activated */);
816
817        mTwilightManager.setTwilightState(state);
818        assertActivated(true /* activated */);
819    }
820
821    @Test
822    public void twilightSchedule_whenRebootedDuringNight_ifOffDuringNightInPast_turnsOff() {
823        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
824        setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
825
826        final TwilightState state = mTwilightManager.getLastTwilightState();
827        mTwilightManager.setTwilightState(null);
828
829        startService();
830        assertActivated(false /* activated */);
831
832        mTwilightManager.setTwilightState(state);
833        assertActivated(false /* activated */);
834    }
835
836    @Test
837    public void twilightSchedule_whenRebootedDuringNight_ifOnAfterNight_turnsOn() {
838        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
839        setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
840
841        final TwilightState state = mTwilightManager.getLastTwilightState();
842        mTwilightManager.setTwilightState(null);
843
844        startService();
845        assertActivated(true /* activated */);
846
847        mTwilightManager.setTwilightState(state);
848        assertActivated(true /* activated */);
849    }
850
851    @Test
852    public void twilightSchedule_whenRebootedDuringNight_ifOnBeforeNight_turnsOn() {
853        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
854        setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
855
856        final TwilightState state = mTwilightManager.getLastTwilightState();
857        mTwilightManager.setTwilightState(null);
858
859        startService();
860        assertActivated(true /* activated */);
861
862        mTwilightManager.setTwilightState(state);
863        assertActivated(true /* activated */);
864    }
865
866    @Test
867    public void twilightSchedule_whenRebootedDuringNight_ifOnDuringNightInFuture_turnsOn() {
868        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
869        setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
870
871        final TwilightState state = mTwilightManager.getLastTwilightState();
872        mTwilightManager.setTwilightState(null);
873
874        startService();
875        assertActivated(true /* activated */);
876
877        mTwilightManager.setTwilightState(state);
878        assertActivated(true /* activated */);
879    }
880
881    @Test
882    public void twilightSchedule_whenRebootedDuringNight_ifOnDuringNightInPast_turnsOn() {
883        setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
884        setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
885
886        final TwilightState state = mTwilightManager.getLastTwilightState();
887        mTwilightManager.setTwilightState(null);
888
889        startService();
890        assertActivated(true /* activated */);
891
892        mTwilightManager.setTwilightState(state);
893        assertActivated(true /* activated */);
894    }
895
896    /**
897     * Configures Night display to use a custom schedule.
898     *
899     * @param startTimeOffset the offset relative to now to activate Night display (in minutes)
900     * @param endTimeOffset the offset relative to now to deactivate Night display (in minutes)
901     */
902    private void setAutoModeCustom(int startTimeOffset, int endTimeOffset) {
903        mNightDisplayController.setAutoMode(NightDisplayController.AUTO_MODE_CUSTOM);
904        mNightDisplayController.setCustomStartTime(getLocalTimeRelativeToNow(startTimeOffset));
905        mNightDisplayController.setCustomEndTime(getLocalTimeRelativeToNow(endTimeOffset));
906    }
907
908    /**
909     * Configures Night display to use the twilight schedule.
910     *
911     * @param sunsetOffset the offset relative to now for sunset (in minutes)
912     * @param sunriseOffset the offset relative to now for sunrise (in minutes)
913     */
914    private void setAutoModeTwilight(int sunsetOffset, int sunriseOffset) {
915        mNightDisplayController.setAutoMode(NightDisplayController.AUTO_MODE_TWILIGHT);
916        mTwilightManager.setTwilightState(
917                getTwilightStateRelativeToNow(sunsetOffset, sunriseOffset));
918    }
919
920    /**
921     * Configures the Night display activated state.
922     *
923     * @param activated {@code true} if Night display should be activated
924     * @param lastActivatedTimeOffset the offset relative to now to record that Night display was
925     * activated (in minutes)
926     */
927    private void setActivated(boolean activated, int lastActivatedTimeOffset) {
928        mNightDisplayController.setActivated(activated);
929
930        final Calendar c = Calendar.getInstance();
931        c.add(Calendar.MINUTE, lastActivatedTimeOffset);
932        Secure.putLongForUser(mContext.getContentResolver(),
933                Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, c.getTimeInMillis(), mUserId);
934    }
935
936    /**
937     * Convenience method to start {@link #mNightDisplayService}.
938     */
939    private void startService() {
940        Secure.putIntForUser(mContext.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, mUserId);
941
942        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
943            @Override
944            public void run() {
945                mNightDisplayService.onStart();
946                mNightDisplayService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
947                mNightDisplayService.onStartUser(mUserId);
948            }
949        });
950    }
951
952    /**
953     * Convenience method for asserting whether Night display should be activated.
954     *
955     * @param activated the expected activated state of Night display
956     */
957    private void assertActivated(boolean activated) {
958        assertWithMessage("Invalid Night display activated state")
959                .that(mNightDisplayController.isActivated())
960                .isEqualTo(activated);
961    }
962
963    /**
964     * Convenience for making a {@link LocalTime} instance with an offset relative to now.
965     *
966     * @param offsetMinutes the offset relative to now (in minutes)
967     * @return the LocalTime instance
968     */
969    private static LocalTime getLocalTimeRelativeToNow(int offsetMinutes) {
970        final Calendar c = Calendar.getInstance();
971        c.add(Calendar.MINUTE, offsetMinutes);
972        return new LocalTime(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
973    }
974
975    /**
976     * Convenience for making a {@link TwilightState} instance with sunrise/sunset relative to now.
977     *
978     * @param sunsetOffset the offset relative to now for sunset (in minutes)
979     * @param sunriseOffset the offset relative to now for sunrise (in minutes)
980     * @return the TwilightState instance
981     */
982    private static TwilightState getTwilightStateRelativeToNow(int sunsetOffset,
983            int sunriseOffset) {
984        final LocalTime sunset = getLocalTimeRelativeToNow(sunsetOffset);
985        final LocalTime sunrise = getLocalTimeRelativeToNow(sunriseOffset);
986
987        final Calendar now = Calendar.getInstance();
988        long sunsetMillis = sunset.getDateTimeBefore(now).getTimeInMillis();
989        long sunriseMillis = sunrise.getDateTimeBefore(now).getTimeInMillis();
990        if (sunsetMillis < sunriseMillis) {
991            sunsetMillis = sunset.getDateTimeAfter(now).getTimeInMillis();
992        } else {
993            sunriseMillis = sunrise.getDateTimeAfter(now).getTimeInMillis();
994        }
995
996        return new TwilightState(sunriseMillis, sunsetMillis);
997    }
998
999    private static class MockTwilightManager implements TwilightManager {
1000
1001        private final Map<TwilightListener, Handler> mListeners = new HashMap<>();
1002        private TwilightState mTwilightState;
1003
1004        /**
1005         * Updates the TwilightState and notifies any registered listeners.
1006         *
1007         * @param state the new TwilightState to use
1008         */
1009        void setTwilightState(TwilightState state) {
1010            synchronized (mListeners) {
1011                mTwilightState = state;
1012
1013                final CountDownLatch latch = new CountDownLatch(mListeners.size());
1014                for (Map.Entry<TwilightListener, Handler> entry : mListeners.entrySet()) {
1015                    entry.getValue().post(new Runnable() {
1016                        @Override
1017                        public void run() {
1018                            entry.getKey().onTwilightStateChanged(state);
1019                            latch.countDown();
1020                        }
1021                    });
1022                }
1023
1024                try {
1025                    latch.await(5, TimeUnit.SECONDS);
1026                } catch (InterruptedException e) {
1027                    throw new RuntimeException(e);
1028                }
1029            }
1030        }
1031
1032        @Override
1033        public void registerListener(@NonNull TwilightListener listener, @NonNull Handler handler) {
1034            synchronized (mListeners) {
1035                mListeners.put(listener, handler);
1036            }
1037        }
1038
1039        @Override
1040        public void unregisterListener(@NonNull TwilightListener listener) {
1041            synchronized (mListeners) {
1042                mListeners.remove(listener);
1043            }
1044        }
1045
1046        @Override
1047        public TwilightState getLastTwilightState() {
1048            return mTwilightState;
1049        }
1050    }
1051}
1052