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