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.display.color;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.anyInt;
24 import static org.mockito.ArgumentMatchers.eq;
25 import static org.mockito.Mockito.doReturn;
26 import static org.mockito.Mockito.never;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
29 
30 import android.annotation.NonNull;
31 import android.app.ActivityManager;
32 import android.app.AlarmManager;
33 import android.content.Context;
34 import android.content.ContextWrapper;
35 import android.content.res.Resources;
36 import android.hardware.display.ColorDisplayManager;
37 import android.hardware.display.DisplayManagerInternal;
38 import android.hardware.display.Time;
39 import android.os.Handler;
40 import android.os.UserHandle;
41 import android.platform.test.annotations.RequiresFlagsEnabled;
42 import android.platform.test.flag.junit.CheckFlagsRule;
43 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
44 import android.provider.Settings;
45 import android.provider.Settings.Secure;
46 import android.provider.Settings.System;
47 import android.test.mock.MockContentResolver;
48 import android.view.Display;
49 
50 import androidx.test.platform.app.InstrumentationRegistry;
51 import androidx.test.runner.AndroidJUnit4;
52 
53 import com.android.internal.R;
54 import com.android.internal.util.test.FakeSettingsProvider;
55 import com.android.internal.util.test.LocalServiceKeeperRule;
56 import com.android.server.SystemService;
57 import com.android.server.display.feature.flags.Flags;
58 import com.android.server.twilight.TwilightListener;
59 import com.android.server.twilight.TwilightManager;
60 import com.android.server.twilight.TwilightState;
61 
62 import org.junit.After;
63 import org.junit.Before;
64 import org.junit.Rule;
65 import org.junit.Test;
66 import org.junit.runner.RunWith;
67 import org.mockito.Mockito;
68 
69 import java.time.LocalDateTime;
70 import java.time.LocalTime;
71 import java.time.ZoneId;
72 import java.util.Calendar;
73 import java.util.HashMap;
74 import java.util.Map;
75 import java.util.concurrent.CountDownLatch;
76 import java.util.concurrent.TimeUnit;
77 
78 @RunWith(AndroidJUnit4.class)
79 public class ColorDisplayServiceTest {
80 
81     private Context mContext;
82     private int mUserId;
83 
84     private MockTwilightManager mTwilightManager;
85     private DisplayTransformManager mDisplayTransformManager;
86     private DisplayManagerInternal mDisplayManagerInternal;
87 
88     private ColorDisplayService mCds;
89     private ColorDisplayService.BinderService mBinderService;
90 
91     private Resources mResourcesSpy;
92 
93     private static final int[] MINIMAL_COLOR_MODES = new int[] {
94         ColorDisplayManager.COLOR_MODE_NATURAL,
95         ColorDisplayManager.COLOR_MODE_BOOSTED,
96     };
97 
98     @Rule
99     public LocalServiceKeeperRule mLocalServiceKeeperRule = new LocalServiceKeeperRule();
100 
101     @Rule
102     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
103 
104     @Before
setUp()105     public void setUp() {
106         mContext = Mockito.spy(new ContextWrapper(
107                 InstrumentationRegistry.getInstrumentation().getTargetContext()));
108         doReturn(mContext).when(mContext).getApplicationContext();
109 
110         final Resources res = Mockito.spy(mContext.getResources());
111         doReturn(MINIMAL_COLOR_MODES).when(res).getIntArray(R.array.config_availableColorModes);
112         doReturn(true).when(res).getBoolean(R.bool.config_nightDisplayAvailable);
113         doReturn(true).when(res).getBoolean(R.bool.config_displayWhiteBalanceAvailable);
114         when(mContext.getResources()).thenReturn(res);
115         mResourcesSpy = res;
116 
117         mUserId = ActivityManager.getCurrentUser();
118 
119         final MockContentResolver cr = new MockContentResolver(mContext);
120         cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
121         doReturn(cr).when(mContext).getContentResolver();
122 
123         final AlarmManager am = Mockito.mock(AlarmManager.class);
124         doReturn(am).when(mContext).getSystemService(Context.ALARM_SERVICE);
125 
126         mTwilightManager = new MockTwilightManager();
127         mLocalServiceKeeperRule.overrideLocalService(TwilightManager.class, mTwilightManager);
128 
129         mDisplayTransformManager = Mockito.mock(DisplayTransformManager.class);
130         doReturn(true).when(mDisplayTransformManager).needsLinearColorMatrix();
131         mLocalServiceKeeperRule.overrideLocalService(
132                 DisplayTransformManager.class, mDisplayTransformManager);
133 
134         mDisplayManagerInternal = Mockito.mock(DisplayManagerInternal.class);
135         mLocalServiceKeeperRule.overrideLocalService(
136                 DisplayManagerInternal.class, mDisplayManagerInternal);
137 
138         mCds = new ColorDisplayService(mContext);
139         mBinderService = mCds.new BinderService();
140         mLocalServiceKeeperRule.overrideLocalService(
141                 ColorDisplayService.ColorDisplayServiceInternal.class,
142                 mCds.new ColorDisplayServiceInternal());
143     }
144 
145     @After
tearDown()146     public void tearDown() {
147         // synchronously cancel all animations
148         mCds.mHandler.runWithScissors(() -> mCds.cancelAllAnimators(), /* timeout */ 1000);
149         mCds = null;
150 
151         mTwilightManager = null;
152 
153         mUserId = UserHandle.USER_NULL;
154         mContext = null;
155 
156         FakeSettingsProvider.clearSettingsProvider();
157     }
158 
159     @Test
customSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff()160     public void customSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
161         setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
162         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
163 
164         startService();
165         assertActivated(false /* activated */);
166     }
167 
168     @Test
customSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff()169     public void customSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
170         setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
171         setNightDisplayActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
172 
173         startService();
174         assertActivated(false /* activated */);
175     }
176 
177     @Test
customSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff()178     public void customSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
179         setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
180         setNightDisplayActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
181 
182         startService();
183         assertActivated(false /* activated */);
184     }
185 
186     @Test
customSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff()187     public void customSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
188         setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
189         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
190 
191         startService();
192         assertActivated(false /* activated */);
193     }
194 
195     @Test
customSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn()196     public void customSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
197         setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
198         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
199 
200         startService();
201         assertActivated(true /* activated */);
202     }
203 
204     @Test
customSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff()205     public void customSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
206         setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
207         setNightDisplayActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
208 
209         startService();
210         assertActivated(false /* activated */);
211     }
212 
213     @Test
customSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff()214     public void customSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
215         setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
216         setNightDisplayActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
217 
218         startService();
219         assertActivated(false /* activated */);
220     }
221 
222     @Test
customSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff()223     public void customSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
224         setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
225         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
226 
227         startService();
228         assertActivated(false /* activated */);
229     }
230 
231     @Test
customSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff()232     public void customSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
233         setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
234         setNightDisplayActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
235 
236         startService();
237         assertActivated(false /* activated */);
238     }
239 
240     @Test
customSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff()241     public void customSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
242         setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
243         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
244 
245         startService();
246         assertActivated(false /* activated */);
247     }
248 
249     @Test
customSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff()250     public void customSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
251         setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
252         setNightDisplayActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
253 
254         startService();
255         assertActivated(false /* activated */);
256     }
257 
258     @Test
customSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff()259     public void customSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
260         setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
261         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
262 
263         startService();
264         assertActivated(false /* activated */);
265     }
266 
267     @Test
customSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff()268     public void customSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
269         setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
270         setNightDisplayActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
271 
272         startService();
273         assertActivated(false /* activated */);
274     }
275 
276     @Test
customSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff()277     public void customSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
278         setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
279         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
280 
281         startService();
282         assertActivated(false /* activated */);
283     }
284 
285     @Test
customSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff()286     public void customSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
287         setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
288         setNightDisplayActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
289 
290         startService();
291         assertActivated(false /* activated */);
292     }
293 
294     @Test
customSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn()295     public void customSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
296         setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
297         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
298 
299         startService();
300         assertActivated(true /* activated */);
301     }
302 
303     @Test
customSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn()304     public void customSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
305         setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
306         setNightDisplayActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
307 
308         startService();
309         assertActivated(true /* activated */);
310     }
311 
312     @Test
customSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn()313     public void customSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
314         setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
315         setNightDisplayActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
316 
317         startService();
318         assertActivated(true /* activated */);
319     }
320 
321     @Test
customSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn()322     public void customSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
323         setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
324         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
325 
326         startService();
327         assertActivated(true /* activated */);
328     }
329 
330     @Test
customSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff()331     public void customSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
332         setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
333         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
334 
335         startService();
336         assertActivated(false /* activated */);
337     }
338 
339     @Test
customSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn()340     public void customSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
341         setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
342         setNightDisplayActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
343 
344         startService();
345         assertActivated(true /* activated */);
346     }
347 
348     @Test
customSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn()349     public void customSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
350         setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
351         setNightDisplayActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
352 
353         startService();
354         assertActivated(true /* activated */);
355     }
356 
357     @Test
customSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn()358     public void customSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
359         setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
360         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
361 
362         startService();
363         assertActivated(true /* activated */);
364     }
365 
366     @Test
customSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn()367     public void customSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
368         setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
369         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
370 
371         startService();
372         assertActivated(true /* activated */);
373     }
374 
375     @Test
twilightSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff()376     public void twilightSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
377         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
378         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
379 
380         startService();
381         assertActivated(false /* activated */);
382     }
383 
384     @Test
twilightSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff()385     public void twilightSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
386         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
387         setNightDisplayActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
388 
389         startService();
390         assertActivated(false /* activated */);
391     }
392 
393     @Test
twilightSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff()394     public void twilightSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
395         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
396         setNightDisplayActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
397 
398         startService();
399         assertActivated(false /* activated */);
400     }
401 
402     @Test
twilightSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff()403     public void twilightSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
404         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
405         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
406 
407         startService();
408         assertActivated(false /* activated */);
409     }
410 
411     @Test
twilightSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn()412     public void twilightSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
413         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
414         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
415 
416         startService();
417         assertActivated(true /* activated */);
418     }
419 
420     @Test
twilightSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff()421     public void twilightSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
422         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
423         setNightDisplayActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
424 
425         startService();
426         assertActivated(false /* activated */);
427     }
428 
429     @Test
twilightSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff()430     public void twilightSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
431         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
432         setNightDisplayActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
433 
434         startService();
435         assertActivated(false /* activated */);
436     }
437 
438     @Test
twilightSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff()439     public void twilightSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
440         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
441         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
442 
443         startService();
444         assertActivated(false /* activated */);
445     }
446 
447     @Test
twilightSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff()448     public void twilightSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
449         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
450         setNightDisplayActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
451 
452         startService();
453         assertActivated(false /* activated */);
454     }
455 
456     @Test
twilightSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff()457     public void twilightSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
458         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
459         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
460 
461         startService();
462         assertActivated(false /* activated */);
463     }
464 
465     @Test
twilightSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff()466     public void twilightSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
467         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
468         setNightDisplayActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
469 
470         startService();
471         assertActivated(false /* activated */);
472     }
473 
474     @Test
twilightSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff()475     public void twilightSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
476         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
477         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
478 
479         startService();
480         assertActivated(false /* activated */);
481     }
482 
483     @Test
twilightSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff()484     public void twilightSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
485         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
486         setNightDisplayActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
487 
488         startService();
489         assertActivated(false /* activated */);
490     }
491 
492     @Test
twilightSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff()493     public void twilightSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
494         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
495         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
496 
497         startService();
498         assertActivated(false /* activated */);
499     }
500 
501     @Test
twilightSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff()502     public void twilightSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
503         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
504         setNightDisplayActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
505 
506         startService();
507         assertActivated(false /* activated */);
508     }
509 
510     @Test
twilightSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn()511     public void twilightSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
512         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
513         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
514 
515         startService();
516         assertActivated(true /* activated */);
517     }
518 
519     @Test
twilightSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn()520     public void twilightSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
521         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
522         setNightDisplayActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
523 
524         startService();
525         assertActivated(true /* activated */);
526     }
527 
528     @Test
twilightSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn()529     public void twilightSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
530         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
531         setNightDisplayActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
532 
533         startService();
534         assertActivated(true /* activated */);
535     }
536 
537     @Test
twilightSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn()538     public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
539         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
540         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
541 
542         startService();
543         assertActivated(true /* activated */);
544     }
545 
546     @Test
twilightSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff()547     public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
548         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
549         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
550 
551         startService();
552         assertActivated(false /* activated */);
553     }
554 
555     @Test
twilightSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn()556     public void twilightSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
557         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
558         setNightDisplayActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
559 
560         startService();
561         assertActivated(true /* activated */);
562     }
563 
564     @Test
twilightSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn()565     public void twilightSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
566         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
567         setNightDisplayActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
568 
569         startService();
570         assertActivated(true /* activated */);
571     }
572 
573     @Test
twilightSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn()574     public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
575         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
576         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
577 
578         startService();
579         assertActivated(true /* activated */);
580     }
581 
582     @Test
twilightSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn()583     public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
584         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
585         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
586 
587         startService();
588         assertActivated(true /* activated */);
589     }
590 
591     @Test
twilightSchedule_whenRebootedAfterNight_ifOffAfterNight_turnsOff()592     public void twilightSchedule_whenRebootedAfterNight_ifOffAfterNight_turnsOff() {
593         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
594         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
595 
596         final TwilightState state = mTwilightManager.getLastTwilightState();
597         mTwilightManager.setTwilightState(null);
598 
599         startService();
600         assertActivated(false /* activated */);
601 
602         mTwilightManager.setTwilightState(state);
603         assertActivated(false /* activated */);
604     }
605 
606     @Test
twilightSchedule_whenRebootedAfterNight_ifOffBeforeNight_turnsOff()607     public void twilightSchedule_whenRebootedAfterNight_ifOffBeforeNight_turnsOff() {
608         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
609         setNightDisplayActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
610 
611         final TwilightState state = mTwilightManager.getLastTwilightState();
612         mTwilightManager.setTwilightState(null);
613 
614         startService();
615         assertActivated(false /* activated */);
616 
617         mTwilightManager.setTwilightState(state);
618         assertActivated(false /* activated */);
619     }
620 
621     @Test
twilightSchedule_whenRebootedAfterNight_ifOffDuringNight_turnsOff()622     public void twilightSchedule_whenRebootedAfterNight_ifOffDuringNight_turnsOff() {
623         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
624         setNightDisplayActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
625 
626         final TwilightState state = mTwilightManager.getLastTwilightState();
627         mTwilightManager.setTwilightState(null);
628 
629         startService();
630         assertActivated(false /* activated */);
631 
632         mTwilightManager.setTwilightState(state);
633         assertActivated(false /* activated */);
634     }
635 
636     @Test
twilightSchedule_whenRebootedAfterNight_ifOffInFuture_turnsOff()637     public void twilightSchedule_whenRebootedAfterNight_ifOffInFuture_turnsOff() {
638         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
639         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
640 
641         final TwilightState state = mTwilightManager.getLastTwilightState();
642         mTwilightManager.setTwilightState(null);
643 
644         startService();
645         assertActivated(false /* activated */);
646 
647         mTwilightManager.setTwilightState(state);
648         assertActivated(false /* activated */);
649     }
650 
651     @Test
twilightSchedule_whenRebootedAfterNight_ifOnAfterNight_turnsOn()652     public void twilightSchedule_whenRebootedAfterNight_ifOnAfterNight_turnsOn() {
653         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
654         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
655 
656         final TwilightState state = mTwilightManager.getLastTwilightState();
657         mTwilightManager.setTwilightState(null);
658 
659         startService();
660         assertActivated(true /* activated */);
661 
662         mTwilightManager.setTwilightState(state);
663         assertActivated(true /* activated */);
664     }
665 
666     @Test
twilightSchedule_whenRebootedAfterNight_ifOnBeforeNight_turnsOff()667     public void twilightSchedule_whenRebootedAfterNight_ifOnBeforeNight_turnsOff() {
668         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
669         setNightDisplayActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
670 
671         final TwilightState state = mTwilightManager.getLastTwilightState();
672         mTwilightManager.setTwilightState(null);
673 
674         startService();
675         assertActivated(true /* activated */);
676 
677         mTwilightManager.setTwilightState(state);
678         assertActivated(false /* activated */);
679     }
680 
681     @Test
twilightSchedule_whenRebootedAfterNight_ifOnDuringNight_turnsOff()682     public void twilightSchedule_whenRebootedAfterNight_ifOnDuringNight_turnsOff() {
683         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
684         setNightDisplayActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
685 
686         final TwilightState state = mTwilightManager.getLastTwilightState();
687         mTwilightManager.setTwilightState(null);
688 
689         startService();
690         assertActivated(true /* activated */);
691 
692         mTwilightManager.setTwilightState(state);
693         assertActivated(false /* activated */);
694     }
695 
696     @Test
twilightSchedule_whenRebootedAfterNight_ifOnInFuture_turnsOff()697     public void twilightSchedule_whenRebootedAfterNight_ifOnInFuture_turnsOff() {
698         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
699         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
700 
701         final TwilightState state = mTwilightManager.getLastTwilightState();
702         mTwilightManager.setTwilightState(null);
703 
704         startService();
705         assertActivated(true /* activated */);
706 
707         mTwilightManager.setTwilightState(state);
708         assertActivated(false /* activated */);
709     }
710 
711     @Test
twilightSchedule_whenRebootedBeforeNight_ifOffAfterNight_turnsOff()712     public void twilightSchedule_whenRebootedBeforeNight_ifOffAfterNight_turnsOff() {
713         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
714         setNightDisplayActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
715 
716         final TwilightState state = mTwilightManager.getLastTwilightState();
717         mTwilightManager.setTwilightState(null);
718 
719         startService();
720         assertActivated(false /* activated */);
721 
722         mTwilightManager.setTwilightState(state);
723         assertActivated(false /* activated */);
724     }
725 
726     @Test
twilightSchedule_whenRebootedBeforeNight_ifOffBeforeNight_turnsOff()727     public void twilightSchedule_whenRebootedBeforeNight_ifOffBeforeNight_turnsOff() {
728         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
729         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
730 
731         final TwilightState state = mTwilightManager.getLastTwilightState();
732         mTwilightManager.setTwilightState(null);
733 
734         startService();
735         assertActivated(false /* activated */);
736 
737         mTwilightManager.setTwilightState(state);
738         assertActivated(false /* activated */);
739     }
740 
741     @Test
twilightSchedule_whenRebootedBeforeNight_ifOffDuringNight_turnsOff()742     public void twilightSchedule_whenRebootedBeforeNight_ifOffDuringNight_turnsOff() {
743         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
744         setNightDisplayActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
745 
746         final TwilightState state = mTwilightManager.getLastTwilightState();
747         mTwilightManager.setTwilightState(null);
748 
749         startService();
750         assertActivated(false /* activated */);
751 
752         mTwilightManager.setTwilightState(state);
753         assertActivated(false /* activated */);
754     }
755 
756     @Test
twilightSchedule_whenRebootedBeforeNight_ifOffInPast_turnsOff()757     public void twilightSchedule_whenRebootedBeforeNight_ifOffInPast_turnsOff() {
758         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
759         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
760 
761         final TwilightState state = mTwilightManager.getLastTwilightState();
762         mTwilightManager.setTwilightState(null);
763 
764         startService();
765         assertActivated(false /* activated */);
766 
767         mTwilightManager.setTwilightState(state);
768         assertActivated(false /* activated */);
769     }
770 
771     @Test
twilightSchedule_whenRebootedBeforeNight_ifOnAfterNight_turnsOff()772     public void twilightSchedule_whenRebootedBeforeNight_ifOnAfterNight_turnsOff() {
773         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
774         setNightDisplayActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
775 
776         final TwilightState state = mTwilightManager.getLastTwilightState();
777         mTwilightManager.setTwilightState(null);
778 
779         startService();
780         assertActivated(true /* activated */);
781 
782         mTwilightManager.setTwilightState(state);
783         assertActivated(false /* activated */);
784     }
785 
786     @Test
twilightSchedule_whenRebootedBeforeNight_ifOnBeforeNight_turnsOff()787     public void twilightSchedule_whenRebootedBeforeNight_ifOnBeforeNight_turnsOff() {
788         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
789         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
790 
791         final TwilightState state = mTwilightManager.getLastTwilightState();
792         mTwilightManager.setTwilightState(null);
793 
794         startService();
795         assertActivated(true /* activated */);
796 
797         mTwilightManager.setTwilightState(state);
798         assertActivated(false /* activated */);
799     }
800 
801     @Test
twilightSchedule_whenRebootedBeforeNight_ifOnDuringNight_turnsOff()802     public void twilightSchedule_whenRebootedBeforeNight_ifOnDuringNight_turnsOff() {
803         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
804         setNightDisplayActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
805 
806         final TwilightState state = mTwilightManager.getLastTwilightState();
807         mTwilightManager.setTwilightState(null);
808 
809         startService();
810         assertActivated(true /* activated */);
811 
812         mTwilightManager.setTwilightState(state);
813         assertActivated(false /* activated */);
814     }
815 
816     @Test
twilightSchedule_whenRebootedBeforeNight_ifOnInPast_turnsOn()817     public void twilightSchedule_whenRebootedBeforeNight_ifOnInPast_turnsOn() {
818         setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
819         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
820 
821         final TwilightState state = mTwilightManager.getLastTwilightState();
822         mTwilightManager.setTwilightState(null);
823 
824         startService();
825         assertActivated(true /* activated */);
826 
827         mTwilightManager.setTwilightState(state);
828         assertActivated(true /* activated */);
829     }
830 
831     @Test
twilightSchedule_whenRebootedDuringNight_ifOffAfterNight_turnsOn()832     public void twilightSchedule_whenRebootedDuringNight_ifOffAfterNight_turnsOn() {
833         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
834         setNightDisplayActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
835 
836         final TwilightState state = mTwilightManager.getLastTwilightState();
837         mTwilightManager.setTwilightState(null);
838 
839         startService();
840         assertActivated(false /* activated */);
841 
842         mTwilightManager.setTwilightState(state);
843         assertActivated(true /* activated */);
844     }
845 
846     @Test
twilightSchedule_whenRebootedDuringNight_ifOffBeforeNight_turnsOn()847     public void twilightSchedule_whenRebootedDuringNight_ifOffBeforeNight_turnsOn() {
848         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
849         setNightDisplayActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
850 
851         final TwilightState state = mTwilightManager.getLastTwilightState();
852         mTwilightManager.setTwilightState(null);
853 
854         startService();
855         assertActivated(false /* activated */);
856 
857         mTwilightManager.setTwilightState(state);
858         assertActivated(true /* activated */);
859     }
860 
861     @Test
twilightSchedule_whenRebootedDuringNight_ifOffDuringNightInFuture_turnsOn()862     public void twilightSchedule_whenRebootedDuringNight_ifOffDuringNightInFuture_turnsOn() {
863         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
864         setNightDisplayActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
865 
866         final TwilightState state = mTwilightManager.getLastTwilightState();
867         mTwilightManager.setTwilightState(null);
868 
869         startService();
870         assertActivated(false /* activated */);
871 
872         mTwilightManager.setTwilightState(state);
873         assertActivated(true /* activated */);
874     }
875 
876     @Test
twilightSchedule_whenRebootedDuringNight_ifOffDuringNightInPast_turnsOff()877     public void twilightSchedule_whenRebootedDuringNight_ifOffDuringNightInPast_turnsOff() {
878         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
879         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
880 
881         final TwilightState state = mTwilightManager.getLastTwilightState();
882         mTwilightManager.setTwilightState(null);
883 
884         startService();
885         assertActivated(false /* activated */);
886 
887         mTwilightManager.setTwilightState(state);
888         assertActivated(false /* activated */);
889     }
890 
891     @Test
twilightSchedule_whenRebootedDuringNight_ifOnAfterNight_turnsOn()892     public void twilightSchedule_whenRebootedDuringNight_ifOnAfterNight_turnsOn() {
893         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
894         setNightDisplayActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
895 
896         final TwilightState state = mTwilightManager.getLastTwilightState();
897         mTwilightManager.setTwilightState(null);
898 
899         startService();
900         assertActivated(true /* activated */);
901 
902         mTwilightManager.setTwilightState(state);
903         assertActivated(true /* activated */);
904     }
905 
906     @Test
twilightSchedule_whenRebootedDuringNight_ifOnBeforeNight_turnsOn()907     public void twilightSchedule_whenRebootedDuringNight_ifOnBeforeNight_turnsOn() {
908         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
909         setNightDisplayActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
910 
911         final TwilightState state = mTwilightManager.getLastTwilightState();
912         mTwilightManager.setTwilightState(null);
913 
914         startService();
915         assertActivated(true /* activated */);
916 
917         mTwilightManager.setTwilightState(state);
918         assertActivated(true /* activated */);
919     }
920 
921     @Test
twilightSchedule_whenRebootedDuringNight_ifOnDuringNightInFuture_turnsOn()922     public void twilightSchedule_whenRebootedDuringNight_ifOnDuringNightInFuture_turnsOn() {
923         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
924         setNightDisplayActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
925 
926         final TwilightState state = mTwilightManager.getLastTwilightState();
927         mTwilightManager.setTwilightState(null);
928 
929         startService();
930         assertActivated(true /* activated */);
931 
932         mTwilightManager.setTwilightState(state);
933         assertActivated(true /* activated */);
934     }
935 
936     @Test
twilightSchedule_whenRebootedDuringNight_ifOnDuringNightInPast_turnsOn()937     public void twilightSchedule_whenRebootedDuringNight_ifOnDuringNightInPast_turnsOn() {
938         setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
939         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
940 
941         final TwilightState state = mTwilightManager.getLastTwilightState();
942         mTwilightManager.setTwilightState(null);
943 
944         startService();
945         assertActivated(true /* activated */);
946 
947         mTwilightManager.setTwilightState(state);
948         assertActivated(true /* activated */);
949     }
950 
951     @Test
accessibility_colorInversion_transformActivated()952     public void accessibility_colorInversion_transformActivated() {
953         if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
954             return;
955         }
956 
957         setAccessibilityColorInversion(true);
958         setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
959 
960         startService();
961         assertUserColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
962         assertActiveColorMode(mContext.getResources().getInteger(
963                 R.integer.config_accessibilityColorMode));
964     }
965 
966     @Test
accessibility_colorCorrection_transformActivated()967     public void accessibility_colorCorrection_transformActivated() {
968         if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
969             return;
970         }
971 
972         setAccessibilityColorCorrection(true);
973         setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
974 
975         startService();
976         assertUserColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
977         assertActiveColorMode(mContext.getResources().getInteger(
978                 R.integer.config_accessibilityColorMode));
979     }
980 
981     @Test
accessibility_all_transformActivated()982     public void accessibility_all_transformActivated() {
983         if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
984             return;
985         }
986 
987         setAccessibilityColorCorrection(true);
988         setAccessibilityColorInversion(true);
989         setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
990 
991         startService();
992         assertUserColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
993         assertActiveColorMode(mContext.getResources().getInteger(
994                 R.integer.config_accessibilityColorMode));
995     }
996 
997     @Test
accessibility_none_transformActivated()998     public void accessibility_none_transformActivated() {
999         if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
1000             return;
1001         }
1002 
1003         setAccessibilityColorCorrection(false);
1004         setAccessibilityColorInversion(false);
1005         setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
1006 
1007         startService();
1008         assertUserColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
1009         assertActiveColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
1010     }
1011 
1012     @Test
1013     @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER)
ensureRbcDisabledWhenEvenDimmerEnabled()1014     public void ensureRbcDisabledWhenEvenDimmerEnabled() {
1015         // If rbc & even dimmer are enabled
1016         doReturn(true).when(mResourcesSpy).getBoolean(
1017                 R.bool.config_reduceBrightColorsAvailable);
1018         doReturn(true).when(mResourcesSpy).getBoolean(
1019                 com.android.internal.R.bool.config_evenDimmerEnabled);
1020         startService();
1021 
1022         // ensure rbc isn't enabled, since even dimmer is the successor.
1023         assertThat(ColorDisplayManager.isReduceBrightColorsAvailable(mContext)).isFalse();
1024     }
1025 
1026     @Test
displayWhiteBalance_enabled()1027     public void displayWhiteBalance_enabled() {
1028         setDisplayWhiteBalanceEnabled(true);
1029         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
1030         mBinderService.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
1031         startService();
1032         assertDwbActive(true);
1033     }
1034 
1035     @Test
displayWhiteBalance_disabledAfterNightDisplayEnabled()1036     public void displayWhiteBalance_disabledAfterNightDisplayEnabled() {
1037         setDisplayWhiteBalanceEnabled(true);
1038         startService();
1039         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
1040 
1041         /* Since we are using FakeSettingsProvider which could not trigger observer change,
1042          * force an update here.*/
1043         mCds.updateDisplayWhiteBalanceStatus();
1044         assertDwbActive(false);
1045     }
1046 
1047     @Test
displayWhiteBalance_enabledAfterNightDisplayDisabled()1048     public void displayWhiteBalance_enabledAfterNightDisplayDisabled() {
1049         setDisplayWhiteBalanceEnabled(true);
1050         startService();
1051         setNightDisplayActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
1052 
1053         mCds.updateDisplayWhiteBalanceStatus();
1054         assertDwbActive(false);
1055 
1056         setNightDisplayActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
1057         mCds.updateDisplayWhiteBalanceStatus();
1058         assertDwbActive(true);
1059     }
1060 
1061     @Test
displayWhiteBalance_enabledAfterLinearColorModeSelected()1062     public void displayWhiteBalance_enabledAfterLinearColorModeSelected() {
1063         if (!isColorModeValid(ColorDisplayManager.COLOR_MODE_SATURATED)) {
1064             return;
1065         }
1066         setDisplayWhiteBalanceEnabled(true);
1067         mBinderService.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED);
1068         startService();
1069         assertDwbActive(false);
1070 
1071         mBinderService.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
1072         mCds.updateDisplayWhiteBalanceStatus();
1073         assertDwbActive(true);
1074     }
1075 
1076     @Test
displayWhiteBalance_disabledWhileAccessibilityColorCorrectionEnabled()1077     public void displayWhiteBalance_disabledWhileAccessibilityColorCorrectionEnabled() {
1078         setDisplayWhiteBalanceEnabled(true);
1079         setAccessibilityColorCorrection(true);
1080         startService();
1081         assertDwbActive(false);
1082 
1083         setAccessibilityColorCorrection(false);
1084         mCds.updateDisplayWhiteBalanceStatus();
1085         assertDwbActive(true);
1086     }
1087 
1088     @Test
displayWhiteBalance_disabledWhileAccessibilityColorInversionEnabled()1089     public void displayWhiteBalance_disabledWhileAccessibilityColorInversionEnabled() {
1090         setDisplayWhiteBalanceEnabled(true);
1091         setAccessibilityColorInversion(true);
1092         startService();
1093         assertDwbActive(false);
1094 
1095         setAccessibilityColorInversion(false);
1096         mCds.updateDisplayWhiteBalanceStatus();
1097         assertDwbActive(true);
1098     }
1099 
1100     @Test
compositionColorSpaces_noResources()1101     public void compositionColorSpaces_noResources() {
1102         when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes))
1103             .thenReturn(new int[] {});
1104         when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces))
1105             .thenReturn(new int[] {});
1106         setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
1107         startService();
1108         verify(mDisplayTransformManager).setColorMode(
1109                 eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), eq(Display.COLOR_MODE_INVALID));
1110     }
1111 
1112     @Test
compositionColorSpaces_invalidResources()1113     public void compositionColorSpaces_invalidResources() {
1114         when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes))
1115                 .thenReturn(new int[] {
1116                         ColorDisplayManager.COLOR_MODE_NATURAL,
1117                         // Missing second color mode
1118                 });
1119         when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces))
1120                 .thenReturn(new int[] {
1121                         Display.COLOR_MODE_SRGB,
1122                         Display.COLOR_MODE_DISPLAY_P3
1123                 });
1124         setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
1125         startService();
1126         verify(mDisplayTransformManager).setColorMode(
1127                 eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), eq(Display.COLOR_MODE_INVALID));
1128     }
1129 
1130     @Test
compositionColorSpaces_validResources_validColorMode()1131     public void compositionColorSpaces_validResources_validColorMode() {
1132         when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes))
1133                 .thenReturn(new int[] {
1134                         ColorDisplayManager.COLOR_MODE_NATURAL
1135                 });
1136         when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces))
1137                 .thenReturn(new int[] {
1138                         Display.COLOR_MODE_SRGB,
1139                 });
1140         setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
1141         startService();
1142         verify(mDisplayTransformManager).setColorMode(
1143                 eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), eq(Display.COLOR_MODE_SRGB));
1144     }
1145 
1146     @Test
compositionColorSpaces_validResources_invalidColorMode()1147     public void compositionColorSpaces_validResources_invalidColorMode() {
1148         when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes))
1149                 .thenReturn(new int[] {
1150                         ColorDisplayManager.COLOR_MODE_NATURAL
1151                 });
1152         when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces))
1153                 .thenReturn(new int[] {
1154                         Display.COLOR_MODE_SRGB,
1155                 });
1156         setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED);
1157         startService();
1158         verify(mDisplayTransformManager).setColorMode(
1159                 eq(ColorDisplayManager.COLOR_MODE_BOOSTED), any(), eq(Display.COLOR_MODE_INVALID));
1160     }
1161 
1162     @Test
getColorMode_noAvailableModes_returnsNotSet()1163     public void getColorMode_noAvailableModes_returnsNotSet() {
1164         when(mResourcesSpy.getIntArray(R.array.config_availableColorModes))
1165                     .thenReturn(new int[] {});
1166         startService();
1167         verify(mDisplayTransformManager, never()).setColorMode(anyInt(), any(), anyInt());
1168         assertThat(mBinderService.getColorMode()).isEqualTo(-1);
1169     }
1170 
1171     /**
1172      * Configures Night display to use a custom schedule.
1173      *
1174      * @param startTimeOffset the offset relative to now to activate Night display (in minutes)
1175      * @param endTimeOffset the offset relative to now to deactivate Night display (in minutes)
1176      */
setAutoModeCustom(int startTimeOffset, int endTimeOffset)1177     private void setAutoModeCustom(int startTimeOffset, int endTimeOffset) {
1178         mBinderService.setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_CUSTOM_TIME);
1179         mBinderService.setNightDisplayCustomStartTime(
1180                 new Time(getLocalTimeRelativeToNow(startTimeOffset)));
1181         mBinderService
1182                 .setNightDisplayCustomEndTime(new Time(getLocalTimeRelativeToNow(endTimeOffset)));
1183     }
1184 
1185     /**
1186      * Configures Night display to use the twilight schedule.
1187      *
1188      * @param sunsetOffset the offset relative to now for sunset (in minutes)
1189      * @param sunriseOffset the offset relative to now for sunrise (in minutes)
1190      */
setAutoModeTwilight(int sunsetOffset, int sunriseOffset)1191     private void setAutoModeTwilight(int sunsetOffset, int sunriseOffset) {
1192         mBinderService.setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_TWILIGHT);
1193         mTwilightManager.setTwilightState(
1194                 getTwilightStateRelativeToNow(sunsetOffset, sunriseOffset));
1195     }
1196 
1197     /**
1198      * Configures the Night display activated state.
1199      *
1200      * @param activated {@code true} if Night display should be activated
1201      * @param lastActivatedTimeOffset the offset relative to now to record that Night display was
1202      * activated (in minutes)
1203      */
setNightDisplayActivated(boolean activated, int lastActivatedTimeOffset)1204     private void setNightDisplayActivated(boolean activated, int lastActivatedTimeOffset) {
1205         mBinderService.setNightDisplayActivated(activated);
1206         Secure.putStringForUser(mContext.getContentResolver(),
1207                 Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
1208                 LocalDateTime.now().plusMinutes(lastActivatedTimeOffset).toString(),
1209                 mUserId);
1210     }
1211 
1212     /**
1213      * Configures the Accessibility color correction setting state.
1214      *
1215      * @param state {@code true} if color inversion should be activated
1216      */
setAccessibilityColorCorrection(boolean state)1217     private void setAccessibilityColorCorrection(boolean state) {
1218         Secure.putIntForUser(mContext.getContentResolver(),
1219                 Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, state ? 1 : 0, mUserId);
1220     }
1221 
1222     /**
1223      * Configures the Accessibility color inversion setting state.
1224      *
1225      * @param state {@code true} if color inversion should be activated
1226      */
setAccessibilityColorInversion(boolean state)1227     private void setAccessibilityColorInversion(boolean state) {
1228         Secure.putIntForUser(mContext.getContentResolver(),
1229                 Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, state ? 1 : 0, mUserId);
1230     }
1231 
1232     /**
1233      * Configures the Display White Balance setting state.
1234      *
1235      * @param enabled {@code true} if display white balance should be enabled
1236      */
setDisplayWhiteBalanceEnabled(boolean enabled)1237     private void setDisplayWhiteBalanceEnabled(boolean enabled) {
1238         Secure.putIntForUser(mContext.getContentResolver(),
1239                 Secure.DISPLAY_WHITE_BALANCE_ENABLED, enabled ? 1 : 0, mUserId);
1240     }
1241 
1242     /**
1243      * Configures color mode.
1244      */
setColorMode(int colorMode)1245     private void setColorMode(int colorMode) {
1246         mBinderService.setColorMode(colorMode);
1247     }
1248 
1249     /**
1250      * Returns whether the color mode is valid on the device the tests are running on.
1251      */
isColorModeValid(int mode)1252     private boolean isColorModeValid(int mode) {
1253         final int[] availableColorModes = mContext.getResources().getIntArray(
1254                 R.array.config_availableColorModes);
1255         if (availableColorModes != null) {
1256             for (int availableMode : availableColorModes) {
1257                 if (mode == availableMode) {
1258                     return true;
1259                 }
1260             }
1261         }
1262         return false;
1263     }
1264 
1265     /**
1266      * Convenience method to start {@link #mCds}.
1267      */
startService()1268     private void startService() {
1269         Secure.putIntForUser(mContext.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, mUserId);
1270 
1271         InstrumentationRegistry.getInstrumentation().runOnMainSync(
1272                 () -> mCds.onBootPhase(SystemService.PHASE_BOOT_COMPLETED));
1273         // onUserChanged cancels running animations, and should be called in handler thread
1274         mCds.mHandler.runWithScissors(() -> mCds.onUserChanged(mUserId), 1000);
1275     }
1276 
1277     /**
1278      * Convenience method for asserting whether Night display should be activated.
1279      *
1280      * @param activated the expected activated state of Night display
1281      */
assertActivated(boolean activated)1282     private void assertActivated(boolean activated) {
1283         assertWithMessage("Incorrect Night display activated state")
1284                 .that(mBinderService.isNightDisplayActivated())
1285                 .isEqualTo(activated);
1286     }
1287 
1288     /**
1289      * Convenience method for asserting that the active color mode matches expectation.
1290      *
1291      * @param mode the expected active color mode.
1292      */
assertActiveColorMode(int mode)1293     private void assertActiveColorMode(int mode) {
1294         assertWithMessage("Unexpected color mode setting")
1295                 .that(mBinderService.getColorMode())
1296                 .isEqualTo(mode);
1297     }
1298 
1299     /**
1300      * Convenience method for asserting that the user chosen color mode matches expectation.
1301      *
1302      * @param mode the expected color mode setting.
1303      */
assertUserColorMode(int mode)1304     private void assertUserColorMode(int mode) {
1305         final int actualMode = System.getIntForUser(mContext.getContentResolver(),
1306                 System.DISPLAY_COLOR_MODE, -1, mUserId);
1307         assertWithMessage("Unexpected color mode setting")
1308                 .that(actualMode)
1309                 .isEqualTo(mode);
1310     }
1311 
1312     /**
1313      * Convenience method for asserting that the DWB active status matches expectation.
1314      *
1315      * @param enabled the expected active status.
1316      */
assertDwbActive(boolean enabled)1317     private void assertDwbActive(boolean enabled) {
1318         assertWithMessage("Incorrect Display White Balance state")
1319                 .that(mCds.mDisplayWhiteBalanceTintController.isActivated())
1320                 .isEqualTo(enabled);
1321     }
1322 
1323     /**
1324      * Convenience for making a {@link LocalTime} instance with an offset relative to now.
1325      *
1326      * @param offsetMinutes the offset relative to now (in minutes)
1327      * @return the LocalTime instance
1328      */
getLocalTimeRelativeToNow(int offsetMinutes)1329     private static LocalTime getLocalTimeRelativeToNow(int offsetMinutes) {
1330         final Calendar c = Calendar.getInstance();
1331         c.add(Calendar.MINUTE, offsetMinutes);
1332         return LocalTime.of(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
1333     }
1334 
1335     /**
1336      * Convenience for making a {@link TwilightState} instance with sunrise/sunset relative to now.
1337      *
1338      * @param sunsetOffset the offset relative to now for sunset (in minutes)
1339      * @param sunriseOffset the offset relative to now for sunrise (in minutes)
1340      * @return the TwilightState instance
1341      */
getTwilightStateRelativeToNow(int sunsetOffset, int sunriseOffset)1342     private static TwilightState getTwilightStateRelativeToNow(int sunsetOffset,
1343             int sunriseOffset) {
1344         final LocalTime sunset = getLocalTimeRelativeToNow(sunsetOffset);
1345         final LocalTime sunrise = getLocalTimeRelativeToNow(sunriseOffset);
1346 
1347         final LocalDateTime now = LocalDateTime.now();
1348         final ZoneId zoneId = ZoneId.systemDefault();
1349 
1350         long sunsetMillis = ColorDisplayService.getDateTimeBefore(sunset, now)
1351                 .atZone(zoneId)
1352                 .toInstant()
1353                 .toEpochMilli();
1354         long sunriseMillis = ColorDisplayService.getDateTimeBefore(sunrise, now)
1355                 .atZone(zoneId)
1356                 .toInstant()
1357                 .toEpochMilli();
1358         if (sunsetMillis < sunriseMillis) {
1359             sunsetMillis = ColorDisplayService.getDateTimeAfter(sunset, now)
1360                     .atZone(zoneId)
1361                     .toInstant()
1362                     .toEpochMilli();
1363         } else {
1364             sunriseMillis = ColorDisplayService.getDateTimeAfter(sunrise, now)
1365                     .atZone(zoneId)
1366                     .toInstant()
1367                     .toEpochMilli();
1368         }
1369 
1370         return new TwilightState(sunriseMillis, sunsetMillis);
1371     }
1372 
1373     private static class MockTwilightManager implements TwilightManager {
1374 
1375         private final Map<TwilightListener, Handler> mListeners = new HashMap<>();
1376         private TwilightState mTwilightState;
1377 
1378         /**
1379          * Updates the TwilightState and notifies any registered listeners.
1380          *
1381          * @param state the new TwilightState to use
1382          */
setTwilightState(TwilightState state)1383         void setTwilightState(TwilightState state) {
1384             synchronized (mListeners) {
1385                 mTwilightState = state;
1386 
1387                 final CountDownLatch latch = new CountDownLatch(mListeners.size());
1388                 for (Map.Entry<TwilightListener, Handler> entry : mListeners.entrySet()) {
1389                     entry.getValue().post(new Runnable() {
1390                         @Override
1391                         public void run() {
1392                             entry.getKey().onTwilightStateChanged(state);
1393                             latch.countDown();
1394                         }
1395                     });
1396                 }
1397 
1398                 try {
1399                     latch.await(5, TimeUnit.SECONDS);
1400                 } catch (InterruptedException e) {
1401                     throw new RuntimeException(e);
1402                 }
1403             }
1404         }
1405 
1406         @Override
registerListener(@onNull TwilightListener listener, @NonNull Handler handler)1407         public void registerListener(@NonNull TwilightListener listener, @NonNull Handler handler) {
1408             synchronized (mListeners) {
1409                 mListeners.put(listener, handler);
1410             }
1411         }
1412 
1413         @Override
unregisterListener(@onNull TwilightListener listener)1414         public void unregisterListener(@NonNull TwilightListener listener) {
1415             synchronized (mListeners) {
1416                 mListeners.remove(listener);
1417             }
1418         }
1419 
1420         @Override
getLastTwilightState()1421         public TwilightState getLastTwilightState() {
1422             return mTwilightState;
1423         }
1424     }
1425 }
1426