1 /*
2  * Copyright (C) 2016 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.systemui.doze;
18 
19 import static android.content.res.Configuration.UI_MODE_NIGHT_YES;
20 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
21 
22 import static com.android.systemui.doze.DozeMachine.State.DOZE;
23 import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
24 import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_DOCKED;
25 import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
26 import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
27 import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING_BRIGHT;
28 import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
29 import static com.android.systemui.doze.DozeMachine.State.DOZE_SUSPEND_TRIGGERS;
30 import static com.android.systemui.doze.DozeMachine.State.FINISH;
31 import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
32 import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
33 
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.assertFalse;
36 import static org.junit.Assert.assertTrue;
37 import static org.mockito.ArgumentMatchers.any;
38 import static org.mockito.ArgumentMatchers.anyInt;
39 import static org.mockito.ArgumentMatchers.eq;
40 import static org.mockito.Mockito.doAnswer;
41 import static org.mockito.Mockito.mock;
42 import static org.mockito.Mockito.never;
43 import static org.mockito.Mockito.reset;
44 import static org.mockito.Mockito.times;
45 import static org.mockito.Mockito.verify;
46 import static org.mockito.Mockito.when;
47 
48 import android.app.ActivityManager;
49 import android.content.res.Configuration;
50 import android.hardware.display.AmbientDisplayConfiguration;
51 import android.testing.AndroidTestingRunner;
52 import android.testing.UiThreadTest;
53 import android.view.Display;
54 
55 import androidx.annotation.NonNull;
56 import androidx.test.filters.SmallTest;
57 
58 import com.android.systemui.SysuiTestCase;
59 import com.android.systemui.dock.DockManager;
60 import com.android.systemui.keyguard.WakefulnessLifecycle;
61 import com.android.systemui.settings.UserTracker;
62 import com.android.systemui.statusbar.phone.DozeParameters;
63 import com.android.systemui.util.wakelock.WakeLockFake;
64 
65 import org.junit.Before;
66 import org.junit.Test;
67 import org.junit.runner.RunWith;
68 import org.mockito.Mock;
69 import org.mockito.MockitoAnnotations;
70 
71 @SmallTest
72 @RunWith(AndroidTestingRunner.class)
73 @UiThreadTest
74 public class DozeMachineTest extends SysuiTestCase {
75 
76     DozeMachine mMachine;
77 
78     @Mock
79     private WakefulnessLifecycle mWakefulnessLifecycle;
80     @Mock
81     private DozeLog mDozeLog;
82     @Mock
83     private DockManager mDockManager;
84     @Mock
85     private DozeHost mHost;
86     @Mock
87     private DozeMachine.Part mPartMock;
88     @Mock
89     private DozeMachine.Part mAnotherPartMock;
90     @Mock
91     private UserTracker mUserTracker;
92     private DozeServiceFake mServiceFake;
93     private WakeLockFake mWakeLockFake;
94     private AmbientDisplayConfiguration mAmbientDisplayConfigMock;
95 
96     @Before
setUp()97     public void setUp() {
98         MockitoAnnotations.initMocks(this);
99         mServiceFake = new DozeServiceFake();
100         mWakeLockFake = new WakeLockFake();
101         mAmbientDisplayConfigMock = mock(AmbientDisplayConfiguration.class);
102         when(mDockManager.isDocked()).thenReturn(false);
103         when(mDockManager.isHidden()).thenReturn(false);
104         when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
105 
106         mMachine = new DozeMachine(mServiceFake,
107                 mAmbientDisplayConfigMock,
108                 mWakeLockFake,
109                 mWakefulnessLifecycle,
110                 mDozeLog,
111                 mDockManager,
112                 mHost,
113                 new DozeMachine.Part[]{mPartMock, mAnotherPartMock},
114                 mUserTracker);
115     }
116 
117     @Test
testInitialize_initializesParts()118     public void testInitialize_initializesParts() {
119         mMachine.requestState(INITIALIZED);
120 
121         verify(mPartMock).transitionTo(UNINITIALIZED, INITIALIZED);
122     }
123 
124     @Test
testInitialize_goesToDoze()125     public void testInitialize_goesToDoze() {
126         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false);
127 
128         mMachine.requestState(INITIALIZED);
129 
130         verify(mPartMock).transitionTo(INITIALIZED, DOZE);
131         assertEquals(DOZE, mMachine.getState());
132     }
133 
134     @Test
testInitialize_goesToAod()135     public void testInitialize_goesToAod() {
136         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
137 
138         mMachine.requestState(INITIALIZED);
139 
140         verify(mPartMock).transitionTo(INITIALIZED, DOZE_AOD);
141         assertEquals(DOZE_AOD, mMachine.getState());
142     }
143 
144     @Test
testInitialize_afterDocked_goesToDockedAod()145     public void testInitialize_afterDocked_goesToDockedAod() {
146         when(mDockManager.isDocked()).thenReturn(true);
147 
148         mMachine.requestState(INITIALIZED);
149 
150         verify(mPartMock).transitionTo(INITIALIZED, DOZE_AOD_DOCKED);
151         assertEquals(DOZE_AOD_DOCKED, mMachine.getState());
152     }
153 
154     @Test
testInitialize_afterDockPaused_goesToDoze()155     public void testInitialize_afterDockPaused_goesToDoze() {
156         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
157         when(mDockManager.isDocked()).thenReturn(true);
158         when(mDockManager.isHidden()).thenReturn(true);
159 
160         mMachine.requestState(INITIALIZED);
161 
162         verify(mPartMock).transitionTo(INITIALIZED, DOZE);
163         assertEquals(DOZE, mMachine.getState());
164     }
165 
166     @Test
testInitialize_alwaysOnSuppressed_alwaysOnDisabled_goesToDoze()167     public void testInitialize_alwaysOnSuppressed_alwaysOnDisabled_goesToDoze() {
168         when(mHost.isAlwaysOnSuppressed()).thenReturn(true);
169         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false);
170 
171         mMachine.requestState(INITIALIZED);
172 
173         verify(mPartMock).transitionTo(INITIALIZED, DOZE);
174         assertEquals(DOZE, mMachine.getState());
175     }
176 
177     @Test
testInitialize_alwaysOnSuppressed_alwaysOnEnabled_goesToDoze()178     public void testInitialize_alwaysOnSuppressed_alwaysOnEnabled_goesToDoze() {
179         when(mHost.isAlwaysOnSuppressed()).thenReturn(true);
180         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
181 
182         mMachine.requestState(INITIALIZED);
183 
184         verify(mPartMock).transitionTo(INITIALIZED, DOZE);
185         assertEquals(DOZE, mMachine.getState());
186     }
187 
188     @Test
testInitialize_alwaysOnSuppressed_afterDocked_goesToDoze()189     public void testInitialize_alwaysOnSuppressed_afterDocked_goesToDoze() {
190         when(mHost.isAlwaysOnSuppressed()).thenReturn(true);
191         when(mDockManager.isDocked()).thenReturn(true);
192 
193         mMachine.requestState(INITIALIZED);
194 
195         verify(mPartMock).transitionTo(INITIALIZED, DOZE);
196         assertEquals(DOZE, mMachine.getState());
197     }
198 
199     @Test
testInitialize_alwaysOnSuppressed_alwaysOnDisabled_afterDockPaused_goesToDoze()200     public void testInitialize_alwaysOnSuppressed_alwaysOnDisabled_afterDockPaused_goesToDoze() {
201         when(mHost.isAlwaysOnSuppressed()).thenReturn(true);
202         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false);
203         when(mDockManager.isDocked()).thenReturn(true);
204         when(mDockManager.isHidden()).thenReturn(true);
205 
206         mMachine.requestState(INITIALIZED);
207 
208         verify(mPartMock).transitionTo(INITIALIZED, DOZE);
209         assertEquals(DOZE, mMachine.getState());
210     }
211 
212     @Test
testInitialize_alwaysOnSuppressed_alwaysOnEnabled_afterDockPaused_goesToDoze()213     public void testInitialize_alwaysOnSuppressed_alwaysOnEnabled_afterDockPaused_goesToDoze() {
214         when(mHost.isAlwaysOnSuppressed()).thenReturn(true);
215         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
216         when(mDockManager.isDocked()).thenReturn(true);
217         when(mDockManager.isHidden()).thenReturn(true);
218 
219         mMachine.requestState(INITIALIZED);
220 
221         verify(mPartMock).transitionTo(INITIALIZED, DOZE);
222         assertEquals(DOZE, mMachine.getState());
223     }
224 
225     @Test
testPulseDone_goesToDoze()226     public void testPulseDone_goesToDoze() {
227         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false);
228         mMachine.requestState(INITIALIZED);
229         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
230         mMachine.requestState(DOZE_PULSING);
231 
232         mMachine.requestState(DOZE_PULSE_DONE);
233 
234         verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE);
235         assertEquals(DOZE, mMachine.getState());
236     }
237 
238     @Test
testPulseDone_goesToAoD()239     public void testPulseDone_goesToAoD() {
240         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
241         mMachine.requestState(INITIALIZED);
242         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
243         mMachine.requestState(DOZE_PULSING);
244 
245         mMachine.requestState(DOZE_PULSE_DONE);
246 
247         verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE_AOD);
248         assertEquals(DOZE_AOD, mMachine.getState());
249     }
250 
251     @Test
testPulseDone_alwaysOnSuppressed_goesToSuppressed()252     public void testPulseDone_alwaysOnSuppressed_goesToSuppressed() {
253         when(mHost.isAlwaysOnSuppressed()).thenReturn(true);
254         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
255         mMachine.requestState(INITIALIZED);
256         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
257         mMachine.requestState(DOZE_PULSING);
258 
259         mMachine.requestState(DOZE_PULSE_DONE);
260 
261         verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE);
262         assertEquals(DOZE, mMachine.getState());
263     }
264 
265     @Test
testPulseDone_afterDocked_goesToDockedAoD()266     public void testPulseDone_afterDocked_goesToDockedAoD() {
267         when(mDockManager.isDocked()).thenReturn(true);
268         mMachine.requestState(INITIALIZED);
269         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
270         mMachine.requestState(DOZE_PULSING);
271 
272         mMachine.requestState(DOZE_PULSE_DONE);
273 
274         verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE_AOD_DOCKED);
275         assertEquals(DOZE_AOD_DOCKED, mMachine.getState());
276     }
277 
278     @Test
testPulseDone_whileDockedAoD_staysDockedAod()279     public void testPulseDone_whileDockedAoD_staysDockedAod() {
280         when(mDockManager.isDocked()).thenReturn(true);
281         mMachine.requestState(INITIALIZED);
282         mMachine.requestState(DOZE_AOD_DOCKED);
283 
284         mMachine.requestState(DOZE_PULSE_DONE);
285 
286         verify(mPartMock, never()).transitionTo(DOZE_AOD_DOCKED, DOZE_PULSE_DONE);
287     }
288 
289     @Test
testPulseDone_alwaysOnSuppressed_afterDocked_goesToDoze()290     public void testPulseDone_alwaysOnSuppressed_afterDocked_goesToDoze() {
291         when(mHost.isAlwaysOnSuppressed()).thenReturn(true);
292         when(mDockManager.isDocked()).thenReturn(true);
293         mMachine.requestState(INITIALIZED);
294         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
295         mMachine.requestState(DOZE_PULSING);
296 
297         mMachine.requestState(DOZE_PULSE_DONE);
298 
299         verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE);
300         assertEquals(DOZE, mMachine.getState());
301     }
302 
303     @Test
testPulseDone_afterDockPaused_goesToDoze()304     public void testPulseDone_afterDockPaused_goesToDoze() {
305         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
306         when(mDockManager.isDocked()).thenReturn(true);
307         when(mDockManager.isHidden()).thenReturn(true);
308         mMachine.requestState(INITIALIZED);
309         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
310         mMachine.requestState(DOZE_PULSING);
311 
312         mMachine.requestState(DOZE_PULSE_DONE);
313 
314         verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE);
315         assertEquals(DOZE, mMachine.getState());
316     }
317 
318     @Test
testPulseDone_alwaysOnSuppressed_afterDockPaused_goesToDoze()319     public void testPulseDone_alwaysOnSuppressed_afterDockPaused_goesToDoze() {
320         when(mHost.isAlwaysOnSuppressed()).thenReturn(true);
321         when(mAmbientDisplayConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
322         when(mDockManager.isDocked()).thenReturn(true);
323         when(mDockManager.isHidden()).thenReturn(true);
324         mMachine.requestState(INITIALIZED);
325         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
326         mMachine.requestState(DOZE_PULSING);
327 
328         mMachine.requestState(DOZE_PULSE_DONE);
329 
330         verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE);
331         assertEquals(DOZE, mMachine.getState());
332     }
333 
334     @Test
testFinished_staysFinished()335     public void testFinished_staysFinished() {
336         mMachine.requestState(INITIALIZED);
337         mMachine.requestState(FINISH);
338         reset(mPartMock);
339 
340         mMachine.requestState(DOZE);
341 
342         verify(mPartMock, never()).transitionTo(any(), any());
343         assertEquals(FINISH, mMachine.getState());
344     }
345 
346     @Test
testFinish_finishesService()347     public void testFinish_finishesService() {
348         mMachine.requestState(INITIALIZED);
349 
350         mMachine.requestState(FINISH);
351 
352         assertTrue(mServiceFake.finished);
353     }
354 
355     @Test
testWakeLock_heldInTransition()356     public void testWakeLock_heldInTransition() {
357         doAnswer((inv) -> {
358             assertTrue(mWakeLockFake.isHeld());
359             return null;
360         }).when(mPartMock).transitionTo(any(), any());
361 
362         mMachine.requestState(INITIALIZED);
363     }
364 
365     @Test
testWakeLock_heldInPulseStates()366     public void testWakeLock_heldInPulseStates() {
367         mMachine.requestState(INITIALIZED);
368 
369         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
370         assertTrue(mWakeLockFake.isHeld());
371 
372         mMachine.requestState(DOZE_PULSING);
373         assertTrue(mWakeLockFake.isHeld());
374     }
375 
376     @Test
testWakeLock_notHeldInDozeStates()377     public void testWakeLock_notHeldInDozeStates() {
378         mMachine.requestState(INITIALIZED);
379 
380         mMachine.requestState(DOZE);
381         assertFalse(mWakeLockFake.isHeld());
382 
383         mMachine.requestState(DOZE_AOD);
384         assertFalse(mWakeLockFake.isHeld());
385     }
386 
387     @Test
testWakeLock_releasedAfterPulse()388     public void testWakeLock_releasedAfterPulse() {
389         mMachine.requestState(INITIALIZED);
390 
391         mMachine.requestState(DOZE);
392         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
393         mMachine.requestState(DOZE_PULSING);
394         mMachine.requestState(DOZE_PULSE_DONE);
395 
396         assertFalse(mWakeLockFake.isHeld());
397     }
398 
399     @Test
testPulseDuringPulse_doesntCrash()400     public void testPulseDuringPulse_doesntCrash() {
401         mMachine.requestState(INITIALIZED);
402 
403         mMachine.requestState(DOZE);
404         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
405         mMachine.requestState(DOZE_PULSING);
406         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
407         mMachine.requestState(DOZE_PULSE_DONE);
408     }
409 
410     @Test
testPulsing_dozeSuspendTriggers_pulseDone_doesntCrash()411     public void testPulsing_dozeSuspendTriggers_pulseDone_doesntCrash() {
412         mMachine.requestState(INITIALIZED);
413 
414         mMachine.requestState(DOZE);
415         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
416         mMachine.requestState(DOZE_PULSING);
417         mMachine.requestState(DOZE_SUSPEND_TRIGGERS);
418         mMachine.requestState(DOZE_PULSE_DONE);
419     }
420 
421     @Test
testSuppressingPulse_doesntCrash()422     public void testSuppressingPulse_doesntCrash() {
423         mMachine.requestState(INITIALIZED);
424 
425         mMachine.requestState(DOZE);
426         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
427         mMachine.requestState(DOZE_PULSE_DONE);
428     }
429 
430     @Test
testTransitions_canRequestTransitions()431     public void testTransitions_canRequestTransitions() {
432         mMachine.requestState(INITIALIZED);
433         mMachine.requestState(DOZE);
434         doAnswer(inv -> {
435             mMachine.requestState(DOZE_PULSING);
436             return null;
437         }).when(mPartMock).transitionTo(any(), eq(DOZE_REQUEST_PULSE));
438 
439         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
440 
441         assertEquals(DOZE_PULSING, mMachine.getState());
442     }
443 
444     @Test
testPulseReason_getMatchesRequest()445     public void testPulseReason_getMatchesRequest() {
446         mMachine.requestState(INITIALIZED);
447         mMachine.requestState(DOZE);
448         mMachine.requestPulse(DozeLog.REASON_SENSOR_DOUBLE_TAP);
449 
450         assertEquals(DozeLog.REASON_SENSOR_DOUBLE_TAP, mMachine.getPulseReason());
451     }
452 
453     @Test
testPulseReason_getFromTransition()454     public void testPulseReason_getFromTransition() {
455         mMachine.requestState(INITIALIZED);
456         mMachine.requestState(DOZE);
457         doAnswer(inv -> {
458             DozeMachine.State newState = inv.getArgument(1);
459             if (newState == DOZE_REQUEST_PULSE
460                     || newState == DOZE_PULSING
461                     || newState == DOZE_PULSE_DONE) {
462                 assertEquals(DozeLog.PULSE_REASON_NOTIFICATION, mMachine.getPulseReason());
463             } else {
464                 assertTrue("unexpected state " + newState,
465                         newState == DOZE || newState == DOZE_AOD);
466             }
467             return null;
468         }).when(mPartMock).transitionTo(any(), any());
469 
470         mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
471         mMachine.requestState(DOZE_PULSING);
472         mMachine.requestState(DOZE_PULSE_DONE);
473     }
474 
475     @Test
testWakeUp_wakesUp()476     public void testWakeUp_wakesUp() {
477         mMachine.wakeUp(DozeLog.REASON_SENSOR_PICKUP);
478 
479         assertTrue(mServiceFake.requestedWakeup);
480     }
481 
482     @Test
testDozePulsing_displayRequiresBlanking_screenState()483     public void testDozePulsing_displayRequiresBlanking_screenState() {
484         DozeParameters dozeParameters = mock(DozeParameters.class);
485         when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
486 
487         assertEquals(Display.STATE_OFF, DOZE_REQUEST_PULSE.screenState(dozeParameters));
488     }
489 
490     @Test
testDozePulsing_displayDoesNotRequireBlanking_screenState()491     public void testDozePulsing_displayDoesNotRequireBlanking_screenState() {
492         DozeParameters dozeParameters = mock(DozeParameters.class);
493         when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(false);
494 
495         assertEquals(Display.STATE_ON, DOZE_REQUEST_PULSE.screenState(dozeParameters));
496     }
497 
498     @Test
testTransitionToInitialized_carModeIsEnabled()499     public void testTransitionToInitialized_carModeIsEnabled() {
500         Configuration configuration = configWithCarNightUiMode();
501 
502         mMachine.onConfigurationChanged(configuration);
503         mMachine.requestState(INITIALIZED);
504 
505         verify(mPartMock).transitionTo(UNINITIALIZED, INITIALIZED);
506         verify(mPartMock).transitionTo(INITIALIZED, DOZE_SUSPEND_TRIGGERS);
507         assertEquals(DOZE_SUSPEND_TRIGGERS, mMachine.getState());
508     }
509 
510     @Test
testTransitionToFinish_carModeIsEnabled()511     public void testTransitionToFinish_carModeIsEnabled() {
512         Configuration configuration = configWithCarNightUiMode();
513 
514         mMachine.onConfigurationChanged(configuration);
515         mMachine.requestState(INITIALIZED);
516         mMachine.requestState(FINISH);
517 
518         assertEquals(FINISH, mMachine.getState());
519     }
520 
521     @Test
testDozeToDozeSuspendTriggers_carModeIsEnabled()522     public void testDozeToDozeSuspendTriggers_carModeIsEnabled() {
523         Configuration configuration = configWithCarNightUiMode();
524 
525         mMachine.onConfigurationChanged(configuration);
526         mMachine.requestState(INITIALIZED);
527         mMachine.requestState(DOZE);
528 
529         assertEquals(DOZE_SUSPEND_TRIGGERS, mMachine.getState());
530     }
531 
532     @Test
testDozeAoDToDozeSuspendTriggers_carModeIsEnabled()533     public void testDozeAoDToDozeSuspendTriggers_carModeIsEnabled() {
534         Configuration configuration = configWithCarNightUiMode();
535 
536         mMachine.onConfigurationChanged(configuration);
537         mMachine.requestState(INITIALIZED);
538         mMachine.requestState(DOZE_AOD);
539 
540         assertEquals(DOZE_SUSPEND_TRIGGERS, mMachine.getState());
541     }
542 
543     @Test
testDozePulsingBrightDozeSuspendTriggers_carModeIsEnabled()544     public void testDozePulsingBrightDozeSuspendTriggers_carModeIsEnabled() {
545         Configuration configuration = configWithCarNightUiMode();
546 
547         mMachine.onConfigurationChanged(configuration);
548         mMachine.requestState(INITIALIZED);
549         mMachine.requestState(DOZE_PULSING_BRIGHT);
550 
551         assertEquals(DOZE_SUSPEND_TRIGGERS, mMachine.getState());
552     }
553 
554     @Test
testDozeAodDockedDozeSuspendTriggers_carModeIsEnabled()555     public void testDozeAodDockedDozeSuspendTriggers_carModeIsEnabled() {
556         Configuration configuration = configWithCarNightUiMode();
557 
558         mMachine.onConfigurationChanged(configuration);
559         mMachine.requestState(INITIALIZED);
560         mMachine.requestState(DOZE_AOD_DOCKED);
561 
562         assertEquals(DOZE_SUSPEND_TRIGGERS, mMachine.getState());
563     }
564 
565     @Test
testOnConfigurationChanged_propagatesUiModeTypeToParts()566     public void testOnConfigurationChanged_propagatesUiModeTypeToParts() {
567         Configuration newConfig = configWithCarNightUiMode();
568 
569         mMachine.onConfigurationChanged(newConfig);
570 
571         verify(mPartMock).onUiModeTypeChanged(UI_MODE_TYPE_CAR);
572         verify(mAnotherPartMock).onUiModeTypeChanged(UI_MODE_TYPE_CAR);
573     }
574 
575     @Test
testOnConfigurationChanged_propagatesOnlyUiModeChangesToParts()576     public void testOnConfigurationChanged_propagatesOnlyUiModeChangesToParts() {
577         Configuration newConfig = configWithCarNightUiMode();
578 
579         mMachine.onConfigurationChanged(newConfig);
580         mMachine.onConfigurationChanged(newConfig);
581 
582         verify(mPartMock, times(1)).onUiModeTypeChanged(UI_MODE_TYPE_CAR);
583         verify(mAnotherPartMock, times(1)).onUiModeTypeChanged(UI_MODE_TYPE_CAR);
584     }
585 
586     @Test
testDozeSuppressTriggers_screenState()587     public void testDozeSuppressTriggers_screenState() {
588         assertEquals(Display.STATE_OFF, DOZE_SUSPEND_TRIGGERS.screenState(null));
589     }
590 
591     @NonNull
configWithCarNightUiMode()592     private Configuration configWithCarNightUiMode() {
593         Configuration configuration = Configuration.EMPTY;
594         configuration.uiMode = UI_MODE_TYPE_CAR | UI_MODE_NIGHT_YES;
595         return configuration;
596     }
597 }
598