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 
17 package com.android.server;
18 
19 import android.annotation.NonNull;
20 import android.app.ActivityManager;
21 import android.app.AlarmManager;
22 import android.content.Context;
23 import android.content.ContextWrapper;
24 import android.os.Handler;
25 import android.os.UserHandle;
26 import android.provider.Settings;
27 import android.provider.Settings.Secure;
28 import android.support.test.InstrumentationRegistry;
29 import android.support.test.runner.AndroidJUnit4;
30 import android.test.mock.MockContentResolver;
31 
32 import com.android.internal.app.NightDisplayController;
33 import com.android.internal.app.NightDisplayController.LocalTime;
34 import com.android.internal.util.test.FakeSettingsProvider;
35 import com.android.server.display.DisplayTransformManager;
36 import com.android.server.display.NightDisplayService;
37 import com.android.server.twilight.TwilightListener;
38 import com.android.server.twilight.TwilightManager;
39 import com.android.server.twilight.TwilightState;
40 import org.junit.After;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.mockito.Mockito;
45 
46 import java.util.Calendar;
47 import java.util.HashMap;
48 import java.util.Map;
49 import java.util.concurrent.CountDownLatch;
50 import java.util.concurrent.TimeUnit;
51 
52 import static com.google.common.truth.Truth.assertWithMessage;
53 import static org.mockito.Mockito.doReturn;
54 
55 @RunWith(AndroidJUnit4.class)
56 public 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
setUp()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
tearDown()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
customSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff()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
customSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff()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
customSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff()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
customSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff()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
customSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn()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
customSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff()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
customSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff()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
customSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff()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
customSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff()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
customSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff()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
customSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff()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
customSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff()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
customSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff()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
customSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff()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
customSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff()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
customSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn()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
customSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn()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
customSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn()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
customSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn()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
customSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff()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
customSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn()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
customSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn()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
customSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn()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
customSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn()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
twilightSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff()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
twilightSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff()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
twilightSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff()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
twilightSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff()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
twilightSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn()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
twilightSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff()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
twilightSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff()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
twilightSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff()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
twilightSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff()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
twilightSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff()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
twilightSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff()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
twilightSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff()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
twilightSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff()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
twilightSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff()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
twilightSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff()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
twilightSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn()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
twilightSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn()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
twilightSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn()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
twilightSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn()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
twilightSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff()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
twilightSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn()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
twilightSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn()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
twilightSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn()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
twilightSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn()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
twilightSchedule_whenRebootedAfterNight_ifOffAfterNight_turnsOff()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
twilightSchedule_whenRebootedAfterNight_ifOffBeforeNight_turnsOff()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
twilightSchedule_whenRebootedAfterNight_ifOffDuringNight_turnsOff()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
twilightSchedule_whenRebootedAfterNight_ifOffInFuture_turnsOff()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
twilightSchedule_whenRebootedAfterNight_ifOnAfterNight_turnsOn()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
twilightSchedule_whenRebootedAfterNight_ifOnBeforeNight_turnsOff()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
twilightSchedule_whenRebootedAfterNight_ifOnDuringNight_turnsOff()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
twilightSchedule_whenRebootedAfterNight_ifOnInFuture_turnsOff()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
twilightSchedule_whenRebootedBeforeNight_ifOffAfterNight_turnsOff()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
twilightSchedule_whenRebootedBeforeNight_ifOffBeforeNight_turnsOff()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
twilightSchedule_whenRebootedBeforeNight_ifOffDuringNight_turnsOff()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
twilightSchedule_whenRebootedBeforeNight_ifOffInPast_turnsOff()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
twilightSchedule_whenRebootedBeforeNight_ifOnAfterNight_turnsOff()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
twilightSchedule_whenRebootedBeforeNight_ifOnBeforeNight_turnsOff()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
twilightSchedule_whenRebootedBeforeNight_ifOnDuringNight_turnsOff()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
twilightSchedule_whenRebootedBeforeNight_ifOnInPast_turnsOn()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
twilightSchedule_whenRebootedDuringNight_ifOffAfterNight_turnsOn()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
twilightSchedule_whenRebootedDuringNight_ifOffBeforeNight_turnsOn()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
twilightSchedule_whenRebootedDuringNight_ifOffDuringNightInFuture_turnsOn()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
twilightSchedule_whenRebootedDuringNight_ifOffDuringNightInPast_turnsOff()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
twilightSchedule_whenRebootedDuringNight_ifOnAfterNight_turnsOn()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
twilightSchedule_whenRebootedDuringNight_ifOnBeforeNight_turnsOn()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
twilightSchedule_whenRebootedDuringNight_ifOnDuringNightInFuture_turnsOn()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
twilightSchedule_whenRebootedDuringNight_ifOnDuringNightInPast_turnsOn()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      */
setAutoModeCustom(int startTimeOffset, int endTimeOffset)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      */
setAutoModeTwilight(int sunsetOffset, int sunriseOffset)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      */
setActivated(boolean activated, int lastActivatedTimeOffset)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      */
startService()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      */
assertActivated(boolean activated)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      */
getLocalTimeRelativeToNow(int offsetMinutes)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      */
getTwilightStateRelativeToNow(int sunsetOffset, int sunriseOffset)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          */
setTwilightState(TwilightState state)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
registerListener(@onNull TwilightListener listener, @NonNull Handler handler)1033         public void registerListener(@NonNull TwilightListener listener, @NonNull Handler handler) {
1034             synchronized (mListeners) {
1035                 mListeners.put(listener, handler);
1036             }
1037         }
1038 
1039         @Override
unregisterListener(@onNull TwilightListener listener)1040         public void unregisterListener(@NonNull TwilightListener listener) {
1041             synchronized (mListeners) {
1042                 mListeners.remove(listener);
1043             }
1044         }
1045 
1046         @Override
getLastTwilightState()1047         public TwilightState getLastTwilightState() {
1048             return mTwilightState;
1049         }
1050     }
1051 }
1052