1 /*
2  * Copyright (C) 2018 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 package com.android.server;
17 
18 import static androidx.test.InstrumentationRegistry.getContext;
19 
20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
24 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
26 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
27 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
28 import static com.android.server.DeviceIdleController.LIGHT_STATE_ACTIVE;
29 import static com.android.server.DeviceIdleController.LIGHT_STATE_IDLE;
30 import static com.android.server.DeviceIdleController.LIGHT_STATE_IDLE_MAINTENANCE;
31 import static com.android.server.DeviceIdleController.LIGHT_STATE_INACTIVE;
32 import static com.android.server.DeviceIdleController.LIGHT_STATE_OVERRIDE;
33 import static com.android.server.DeviceIdleController.LIGHT_STATE_PRE_IDLE;
34 import static com.android.server.DeviceIdleController.LIGHT_STATE_WAITING_FOR_NETWORK;
35 import static com.android.server.DeviceIdleController.MSG_REPORT_STATIONARY_STATUS;
36 import static com.android.server.DeviceIdleController.MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR;
37 import static com.android.server.DeviceIdleController.MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR;
38 import static com.android.server.DeviceIdleController.STATE_ACTIVE;
39 import static com.android.server.DeviceIdleController.STATE_IDLE;
40 import static com.android.server.DeviceIdleController.STATE_IDLE_MAINTENANCE;
41 import static com.android.server.DeviceIdleController.STATE_IDLE_PENDING;
42 import static com.android.server.DeviceIdleController.STATE_INACTIVE;
43 import static com.android.server.DeviceIdleController.STATE_LOCATING;
44 import static com.android.server.DeviceIdleController.STATE_QUICK_DOZE_DELAY;
45 import static com.android.server.DeviceIdleController.STATE_SENSING;
46 import static com.android.server.DeviceIdleController.lightStateToString;
47 import static com.android.server.DeviceIdleController.stateToString;
48 
49 import static org.junit.Assert.assertEquals;
50 import static org.junit.Assert.assertFalse;
51 import static org.junit.Assert.assertTrue;
52 import static org.junit.Assert.fail;
53 import static org.mockito.ArgumentMatchers.any;
54 import static org.mockito.ArgumentMatchers.anyBoolean;
55 import static org.mockito.ArgumentMatchers.anyInt;
56 import static org.mockito.ArgumentMatchers.anyLong;
57 import static org.mockito.ArgumentMatchers.anyString;
58 import static org.mockito.ArgumentMatchers.argThat;
59 import static org.mockito.ArgumentMatchers.eq;
60 import static org.mockito.ArgumentMatchers.longThat;
61 import static org.mockito.Mockito.atLeastOnce;
62 import static org.mockito.Mockito.never;
63 import static org.mockito.Mockito.reset;
64 import static org.mockito.Mockito.timeout;
65 import static org.mockito.Mockito.verify;
66 
67 import android.app.ActivityManagerInternal;
68 import android.app.AlarmManager;
69 import android.app.IActivityManager;
70 import android.content.Context;
71 import android.content.Intent;
72 import android.hardware.Sensor;
73 import android.hardware.SensorEvent;
74 import android.hardware.SensorEventListener;
75 import android.hardware.SensorManager;
76 import android.hardware.TriggerEvent;
77 import android.hardware.TriggerEventListener;
78 import android.location.LocationManager;
79 import android.location.LocationProvider;
80 import android.net.ConnectivityManager;
81 import android.net.NetworkInfo;
82 import android.os.Handler;
83 import android.os.Looper;
84 import android.os.Message;
85 import android.os.PowerManager;
86 import android.os.PowerManagerInternal;
87 import android.os.PowerSaveState;
88 import android.os.SystemClock;
89 import android.provider.DeviceConfig;
90 
91 import androidx.test.runner.AndroidJUnit4;
92 
93 import com.android.server.deviceidle.ConstraintController;
94 import com.android.server.net.NetworkPolicyManagerInternal;
95 import com.android.server.wm.ActivityTaskManagerInternal;
96 
97 import org.junit.After;
98 import org.junit.Before;
99 import org.junit.Test;
100 import org.junit.runner.RunWith;
101 import org.mockito.ArgumentCaptor;
102 import org.mockito.ArgumentMatchers;
103 import org.mockito.InOrder;
104 import org.mockito.Mock;
105 import org.mockito.MockitoSession;
106 import org.mockito.invocation.InvocationOnMock;
107 import org.mockito.quality.Strictness;
108 import org.mockito.stubbing.Answer;
109 
110 import java.util.concurrent.Executor;
111 
112 /**
113  * Tests for {@link com.android.server.DeviceIdleController}.
114  */
115 @RunWith(AndroidJUnit4.class)
116 public class DeviceIdleControllerTest {
117     private DeviceIdleController mDeviceIdleController;
118     private DeviceIdleController.MyHandler mHandler;
119     private AnyMotionDetectorForTest mAnyMotionDetector;
120     private AppStateTrackerForTest mAppStateTracker;
121     private DeviceIdleController.Constants mConstants;
122     private InjectorForTest mInjector;
123 
124     private MockitoSession mMockingSession;
125     @Mock
126     private AlarmManager mAlarmManager;
127     @Mock
128     private ConnectivityManager mConnectivityManager;
129     @Mock
130     private IActivityManager mIActivityManager;
131     @Mock
132     private LocationManager mLocationManager;
133     @Mock
134     private PowerManager mPowerManager;
135     @Mock
136     private PowerManager.WakeLock mWakeLock;
137     @Mock
138     private PowerManagerInternal mPowerManagerInternal;
139     @Mock
140     private Sensor mMotionSensor;
141     @Mock
142     private SensorManager mSensorManager;
143 
144     class InjectorForTest extends DeviceIdleController.Injector {
145         ConnectivityManager connectivityManager;
146         LocationManager locationManager;
147         ConstraintController constraintController;
148         // Freeze time for testing.
149         long nowElapsed;
150 
InjectorForTest(Context ctx)151         InjectorForTest(Context ctx) {
152             super(ctx);
153             nowElapsed = SystemClock.elapsedRealtime();
154         }
155 
156         @Override
getAlarmManager()157         AlarmManager getAlarmManager() {
158             return mAlarmManager;
159         }
160 
161         @Override
getAnyMotionDetector(Handler handler, SensorManager sm, AnyMotionDetector.DeviceIdleCallback callback, float angleThreshold)162         AnyMotionDetector getAnyMotionDetector(Handler handler, SensorManager sm,
163                 AnyMotionDetector.DeviceIdleCallback callback, float angleThreshold) {
164             return mAnyMotionDetector;
165         }
166 
167         @Override
getAppStateTracker(Context ctx, Looper loop)168         AppStateTrackerImpl getAppStateTracker(Context ctx, Looper loop) {
169             return mAppStateTracker;
170         }
171 
172         @Override
getConnectivityManager()173         ConnectivityManager getConnectivityManager() {
174             return connectivityManager;
175         }
176 
177         @Override
getElapsedRealtime()178         long getElapsedRealtime() {
179             return nowElapsed;
180         }
181 
182         @Override
getLocationManager()183         LocationManager getLocationManager() {
184             return locationManager;
185         }
186 
187         @Override
getHandler(DeviceIdleController controller)188         DeviceIdleController.MyHandler getHandler(DeviceIdleController controller) {
189             if (mHandler == null) {
190                 mHandler = controller.new MyHandler(getContext().getMainLooper());
191                 spyOn(mHandler);
192                 doNothing().when(mHandler).handleMessage(argThat((message) ->
193                         message.what != MSG_REPORT_STATIONARY_STATUS
194                         && message.what != MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR
195                         && message.what != MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR));
196                 doAnswer(new Answer<Boolean>() {
197                     @Override
198                     public Boolean answer(InvocationOnMock invocation) throws Throwable {
199                         Message msg = invocation.getArgument(0);
200                         mHandler.handleMessage(msg);
201                         return true;
202                     }
203                 }).when(mHandler).sendMessageDelayed(
204                         argThat((message) -> message.what == MSG_REPORT_STATIONARY_STATUS
205                                 || message.what == MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR
206                                 || message.what == MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR),
207                         anyLong());
208             }
209 
210             return mHandler;
211         }
212 
213         @Override
getMotionSensor()214         Sensor getMotionSensor() {
215             return mMotionSensor;
216         }
217 
218         @Override
getPowerManager()219         PowerManager getPowerManager() {
220             return mPowerManager;
221         }
222 
223         @Override
getSensorManager()224         SensorManager getSensorManager() {
225             return mSensorManager;
226         }
227 
228         @Override
getConstraintController( Handler handler, DeviceIdleInternal localService)229         ConstraintController getConstraintController(
230                 Handler handler, DeviceIdleInternal localService) {
231             return constraintController;
232         }
233 
234         @Override
useMotionSensor()235         boolean useMotionSensor() {
236             return true;
237         }
238     }
239 
240     private class AnyMotionDetectorForTest extends AnyMotionDetector {
241         boolean isMonitoring = false;
242 
AnyMotionDetectorForTest()243         AnyMotionDetectorForTest() {
244             super(mPowerManager, mock(Handler.class), mSensorManager,
245                     mock(DeviceIdleCallback.class), 0.5f);
246         }
247 
248         @Override
hasSensor()249         public boolean hasSensor() {
250             return true;
251         }
252 
253         @Override
checkForAnyMotion()254         public void checkForAnyMotion() {
255             isMonitoring = true;
256         }
257 
258         @Override
stop()259         public void stop() {
260             isMonitoring = false;
261         }
262     }
263 
264     private class AppStateTrackerForTest extends AppStateTrackerImpl {
AppStateTrackerForTest(Context ctx, Looper looper)265         AppStateTrackerForTest(Context ctx, Looper looper) {
266             super(ctx, looper);
267         }
268 
269         @Override
onSystemServicesReady()270         public void onSystemServicesReady() {
271             // Do nothing.
272         }
273 
274         @Override
injectIActivityManager()275         IActivityManager injectIActivityManager() {
276             return mIActivityManager;
277         }
278     }
279 
280     private class StationaryListenerForTest implements DeviceIdleInternal.StationaryListener {
281         boolean motionExpected = false;
282         boolean isStationary = false;
283 
284         @Override
onDeviceStationaryChanged(boolean isStationary)285         public void onDeviceStationaryChanged(boolean isStationary) {
286             if (isStationary == motionExpected) {
287                 fail("Unexpected device stationary status: " + isStationary);
288             }
289             this.isStationary = isStationary;
290         }
291     }
292 
293     @Before
setUp()294     public void setUp() {
295         mMockingSession = mockitoSession()
296                 .initMocks(this)
297                 .strictness(Strictness.LENIENT)
298                 .spyStatic(DeviceConfig.class)
299                 .spyStatic(LocalServices.class)
300                 .startMocking();
301         spyOn(getContext());
302         doReturn(null).when(getContext()).registerReceiver(any(), any());
303         doReturn(mock(ActivityManagerInternal.class))
304                 .when(() -> LocalServices.getService(ActivityManagerInternal.class));
305         doReturn(mock(ActivityTaskManagerInternal.class))
306                 .when(() -> LocalServices.getService(ActivityTaskManagerInternal.class));
307         doReturn(mock(AlarmManagerInternal.class))
308                 .when(() -> LocalServices.getService(AlarmManagerInternal.class));
309         doReturn(mPowerManagerInternal)
310                 .when(() -> LocalServices.getService(PowerManagerInternal.class));
311         when(mPowerManagerInternal.getLowPowerState(anyInt()))
312                 .thenReturn(mock(PowerSaveState.class));
313         doReturn(mock(NetworkPolicyManagerInternal.class))
314                 .when(() -> LocalServices.getService(NetworkPolicyManagerInternal.class));
315         doAnswer((Answer<Void>) invocationOnMock -> null)
316                 .when(() -> DeviceConfig.addOnPropertiesChangedListener(
317                         anyString(), any(Executor.class),
318                         any(DeviceConfig.OnPropertiesChangedListener.class)));
319         doAnswer((Answer<DeviceConfig.Properties>) invocationOnMock
320                 -> mock(DeviceConfig.Properties.class))
321                 .when(() -> DeviceConfig.getProperties(
322                         anyString(), ArgumentMatchers.<String>any()));
323         when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock);
324         doNothing().when(mWakeLock).acquire();
325         doNothing().when(mAlarmManager).set(anyInt(), anyLong(), anyString(), any(), any());
326         doNothing().when(mAlarmManager).setExact(anyInt(), anyLong(), anyString(), any(), any());
327         doNothing().when(mAlarmManager)
328                 .setWindow(anyInt(), anyLong(), anyLong(), anyString(), any(), any());
329         doReturn(mock(Sensor.class)).when(mSensorManager)
330                 .getDefaultSensor(eq(Sensor.TYPE_SIGNIFICANT_MOTION), eq(true));
331         doReturn(true).when(mSensorManager).registerListener(any(), any(), anyInt());
332         mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper());
333         mAnyMotionDetector = new AnyMotionDetectorForTest();
334         mInjector = new InjectorForTest(getContext());
335 
336         mDeviceIdleController = new DeviceIdleController(getContext(), mInjector);
337         spyOn(mDeviceIdleController);
338         doNothing().when(mDeviceIdleController).publishBinderService(any(), any());
339         mDeviceIdleController.onStart();
340         mDeviceIdleController.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
341         mDeviceIdleController.setDeepEnabledForTest(true);
342         mDeviceIdleController.setLightEnabledForTest(true);
343 
344         // Get the same Constants object that mDeviceIdleController got.
345         mConstants = mInjector.getConstants(mDeviceIdleController);
346     }
347 
348     @After
tearDown()349     public void tearDown() {
350         if (mMockingSession != null) {
351             mMockingSession.finishMocking();
352         }
353         // DeviceIdleController adds these to LocalServices in the constructor, so we have to remove
354         // them after each test, otherwise, subsequent tests will fail.
355         LocalServices.removeServiceForTest(AppStateTracker.class);
356         LocalServices.removeServiceForTest(DeviceIdleInternal.class);
357         LocalServices.removeServiceForTest(PowerAllowlistInternal.class);
358     }
359 
360     @Test
testUpdateInteractivityLocked()361     public void testUpdateInteractivityLocked() {
362         doReturn(false).when(mPowerManager).isInteractive();
363         mDeviceIdleController.updateInteractivityLocked();
364         assertFalse(mDeviceIdleController.isScreenOn());
365 
366         // Make sure setting false when screen is already off doesn't change anything.
367         doReturn(false).when(mPowerManager).isInteractive();
368         mDeviceIdleController.updateInteractivityLocked();
369         assertFalse(mDeviceIdleController.isScreenOn());
370 
371         // Test changing from screen off to screen on.
372         doReturn(true).when(mPowerManager).isInteractive();
373         mDeviceIdleController.updateInteractivityLocked();
374         assertTrue(mDeviceIdleController.isScreenOn());
375 
376         // Make sure setting true when screen is already on doesn't change anything.
377         doReturn(true).when(mPowerManager).isInteractive();
378         mDeviceIdleController.updateInteractivityLocked();
379         assertTrue(mDeviceIdleController.isScreenOn());
380 
381         // Test changing from screen on to screen off.
382         doReturn(false).when(mPowerManager).isInteractive();
383         mDeviceIdleController.updateInteractivityLocked();
384         assertFalse(mDeviceIdleController.isScreenOn());
385     }
386 
387     @Test
testUpdateChargingLocked()388     public void testUpdateChargingLocked() {
389         mDeviceIdleController.updateChargingLocked(false);
390         assertFalse(mDeviceIdleController.isCharging());
391 
392         // Make sure setting false when charging is already off doesn't change anything.
393         mDeviceIdleController.updateChargingLocked(false);
394         assertFalse(mDeviceIdleController.isCharging());
395 
396         // Test changing from charging off to charging on.
397         mDeviceIdleController.updateChargingLocked(true);
398         assertTrue(mDeviceIdleController.isCharging());
399 
400         // Make sure setting true when charging is already on doesn't change anything.
401         mDeviceIdleController.updateChargingLocked(true);
402         assertTrue(mDeviceIdleController.isCharging());
403 
404         // Test changing from charging on to charging off.
405         mDeviceIdleController.updateChargingLocked(false);
406         assertFalse(mDeviceIdleController.isCharging());
407     }
408 
409     @Test
testUpdateConnectivityState()410     public void testUpdateConnectivityState() {
411         // No connectivity service
412         final boolean isConnected = mDeviceIdleController.isNetworkConnected();
413         mInjector.connectivityManager = null;
414         mDeviceIdleController.updateConnectivityState(null);
415         assertEquals(isConnected, mDeviceIdleController.isNetworkConnected());
416 
417         // No active network info
418         mInjector.connectivityManager = mConnectivityManager;
419         doReturn(null).when(mConnectivityManager).getActiveNetworkInfo();
420         mDeviceIdleController.updateConnectivityState(null);
421         assertFalse(mDeviceIdleController.isNetworkConnected());
422 
423         // Active network info says connected.
424         final NetworkInfo ani = mock(NetworkInfo.class);
425         doReturn(ani).when(mConnectivityManager).getActiveNetworkInfo();
426         doReturn(true).when(ani).isConnected();
427         mDeviceIdleController.updateConnectivityState(null);
428         assertTrue(mDeviceIdleController.isNetworkConnected());
429 
430         // Active network info says not connected.
431         doReturn(false).when(ani).isConnected();
432         mDeviceIdleController.updateConnectivityState(null);
433         assertFalse(mDeviceIdleController.isNetworkConnected());
434 
435         // Wrong intent passed (false).
436         Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
437         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 3);
438         doReturn(true).when(ani).isConnected();
439         doReturn(1).when(ani).getType();
440         mDeviceIdleController.updateConnectivityState(intent);
441         // Wrong intent means we shouldn't update the connected state.
442         assertFalse(mDeviceIdleController.isNetworkConnected());
443 
444         // Intent says connected.
445         doReturn(1).when(ani).getType();
446         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1);
447         intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
448         mDeviceIdleController.updateConnectivityState(intent);
449         assertTrue(mDeviceIdleController.isNetworkConnected());
450 
451         // Wrong intent passed (true).
452         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 3);
453         // Wrong intent means we shouldn't update the connected state.
454         assertTrue(mDeviceIdleController.isNetworkConnected());
455 
456         // Intent says not connected.
457         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1);
458         intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
459         mDeviceIdleController.updateConnectivityState(intent);
460         assertFalse(mDeviceIdleController.isNetworkConnected());
461     }
462 
463     @Test
testUpdateQuickDozeFlagLocked()464     public void testUpdateQuickDozeFlagLocked() {
465         mDeviceIdleController.updateQuickDozeFlagLocked(false);
466         assertFalse(mDeviceIdleController.isQuickDozeEnabled());
467 
468         // Make sure setting false when quick doze is already off doesn't change anything.
469         mDeviceIdleController.updateQuickDozeFlagLocked(false);
470         assertFalse(mDeviceIdleController.isQuickDozeEnabled());
471 
472         // Test changing from quick doze off to quick doze on.
473         mDeviceIdleController.updateQuickDozeFlagLocked(true);
474         assertTrue(mDeviceIdleController.isQuickDozeEnabled());
475 
476         // Make sure setting true when quick doze is already on doesn't change anything.
477         mDeviceIdleController.updateQuickDozeFlagLocked(true);
478         assertTrue(mDeviceIdleController.isQuickDozeEnabled());
479 
480         // Test changing from quick doze on to quick doze off.
481         mDeviceIdleController.updateQuickDozeFlagLocked(false);
482         assertFalse(mDeviceIdleController.isQuickDozeEnabled());
483     }
484 
485     @Test
testStateActiveToStateInactive_ConditionsNotMet()486     public void testStateActiveToStateInactive_ConditionsNotMet() {
487         mDeviceIdleController.becomeActiveLocked("testing", 0);
488         verifyStateConditions(STATE_ACTIVE);
489 
490         // State should stay ACTIVE with screen on and charging.
491         setChargingOn(true);
492         setScreenOn(true);
493 
494         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
495         verifyStateConditions(STATE_ACTIVE);
496 
497         // State should stay ACTIVE with charging on.
498         setChargingOn(true);
499         setScreenOn(false);
500 
501         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
502         verifyStateConditions(STATE_ACTIVE);
503 
504         // State should stay ACTIVE with screen on.
505         // Note the different operation order here makes sure the state doesn't change before test.
506         setScreenOn(true);
507         setChargingOn(false);
508 
509         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
510         verifyStateConditions(STATE_ACTIVE);
511 
512         mConstants.WAIT_FOR_UNLOCK = false;
513         setScreenLocked(true);
514         setScreenOn(true);
515         setChargingOn(false);
516 
517         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
518         verifyStateConditions(STATE_ACTIVE);
519 
520         setScreenLocked(false);
521         setScreenOn(true);
522         setChargingOn(false);
523 
524         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
525         verifyStateConditions(STATE_ACTIVE);
526 
527         mConstants.WAIT_FOR_UNLOCK = true;
528         setScreenLocked(false);
529         setScreenOn(true);
530         setChargingOn(false);
531 
532         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
533         verifyStateConditions(STATE_ACTIVE);
534     }
535 
536     @Test
testLightStateActiveToLightStateInactive_ConditionsNotMet()537     public void testLightStateActiveToLightStateInactive_ConditionsNotMet() {
538         mDeviceIdleController.becomeActiveLocked("testing", 0);
539         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
540 
541         // State should stay ACTIVE with screen on and charging.
542         setChargingOn(true);
543         setScreenOn(true);
544 
545         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
546         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
547 
548         // State should stay ACTIVE with charging on.
549         setChargingOn(true);
550         setScreenOn(false);
551 
552         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
553         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
554 
555         // State should stay ACTIVE with screen on.
556         // Note the different operation order here makes sure the state doesn't change before test.
557         setScreenOn(true);
558         setChargingOn(false);
559 
560         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
561         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
562     }
563 
564     @Test
testStateActiveToStateInactive_ConditionsMet()565     public void testStateActiveToStateInactive_ConditionsMet() {
566         mDeviceIdleController.becomeActiveLocked("testing", 0);
567         verifyStateConditions(STATE_ACTIVE);
568 
569         setAlarmSoon(false);
570         setChargingOn(false);
571         setScreenOn(false);
572 
573         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
574         verifyStateConditions(STATE_INACTIVE);
575         verify(mDeviceIdleController)
576                 .scheduleAlarmLocked(eq(mConstants.INACTIVE_TIMEOUT), eq(false));
577     }
578 
579     @Test
testStateActiveToStateInactive_UpcomingAlarm()580     public void testStateActiveToStateInactive_UpcomingAlarm() {
581         final long timeUntilAlarm = mConstants.MIN_TIME_TO_ALARM / 2;
582         // Set an upcoming alarm that will prevent full idle.
583         doReturn(mInjector.getElapsedRealtime() + timeUntilAlarm)
584                 .when(mAlarmManager).getNextWakeFromIdleTime();
585 
586         InOrder inOrder = inOrder(mDeviceIdleController);
587 
588         enterDeepState(STATE_ACTIVE);
589         setQuickDozeEnabled(false);
590         setChargingOn(false);
591         setScreenOn(false);
592 
593         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
594         verifyStateConditions(STATE_INACTIVE);
595         inOrder.verify(mDeviceIdleController)
596                 .scheduleAlarmLocked(eq(timeUntilAlarm + mConstants.INACTIVE_TIMEOUT), eq(false));
597 
598         enterDeepState(STATE_ACTIVE);
599         setQuickDozeEnabled(true);
600         setChargingOn(false);
601         setScreenOn(false);
602 
603         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
604         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
605         inOrder.verify(mDeviceIdleController).scheduleAlarmLocked(
606                 eq(timeUntilAlarm + mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false));
607     }
608 
609     @Test
testLightStateActiveToLightStateInactive_ConditionsMet()610     public void testLightStateActiveToLightStateInactive_ConditionsMet() {
611         mDeviceIdleController.becomeActiveLocked("testing", 0);
612         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
613 
614         setChargingOn(false);
615         setScreenOn(false);
616 
617         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
618         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
619     }
620 
621     @Test
testTransitionFromAnyStateToStateQuickDozeDelay()622     public void testTransitionFromAnyStateToStateQuickDozeDelay() {
623         setAlarmSoon(false);
624         InOrder inOrder = inOrder(mDeviceIdleController);
625 
626         enterDeepState(STATE_ACTIVE);
627         setQuickDozeEnabled(true);
628         setChargingOn(false);
629         setScreenOn(false);
630         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
631         inOrder.verify(mDeviceIdleController)
632                 .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false));
633 
634         enterDeepState(STATE_INACTIVE);
635         setQuickDozeEnabled(true);
636         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
637         inOrder.verify(mDeviceIdleController)
638                 .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false));
639 
640         enterDeepState(STATE_IDLE_PENDING);
641         setQuickDozeEnabled(true);
642         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
643         inOrder.verify(mDeviceIdleController)
644                 .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false));
645 
646         enterDeepState(STATE_SENSING);
647         setQuickDozeEnabled(true);
648         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
649         inOrder.verify(mDeviceIdleController)
650                 .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false));
651 
652         enterDeepState(STATE_LOCATING);
653         setQuickDozeEnabled(true);
654         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
655         inOrder.verify(mDeviceIdleController)
656                 .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false));
657 
658         // IDLE should stay as IDLE.
659         enterDeepState(STATE_IDLE);
660         // Clear out any alarm setting from the order before checking for this section.
661         inOrder.verify(mDeviceIdleController, atLeastOnce())
662                 .scheduleAlarmLocked(anyLong(), anyBoolean());
663         setQuickDozeEnabled(true);
664         verifyStateConditions(STATE_IDLE);
665         inOrder.verify(mDeviceIdleController, never()).scheduleAlarmLocked(anyLong(), anyBoolean());
666 
667         // IDLE_MAINTENANCE should stay as IDLE_MAINTENANCE.
668         enterDeepState(STATE_IDLE_MAINTENANCE);
669         // Clear out any alarm setting from the order before checking for this section.
670         inOrder.verify(mDeviceIdleController, atLeastOnce())
671                 .scheduleAlarmLocked(anyLong(), anyBoolean());
672         setQuickDozeEnabled(true);
673         verifyStateConditions(STATE_IDLE_MAINTENANCE);
674         inOrder.verify(mDeviceIdleController, never()).scheduleAlarmLocked(anyLong(), anyBoolean());
675 
676         // State is already QUICK_DOZE_DELAY. No work should be done.
677         enterDeepState(STATE_QUICK_DOZE_DELAY);
678         // Clear out any alarm setting from the order before checking for this section.
679         inOrder.verify(mDeviceIdleController, atLeastOnce())
680                 .scheduleAlarmLocked(anyLong(), anyBoolean());
681         setQuickDozeEnabled(true);
682         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
683         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
684         inOrder.verify(mDeviceIdleController, never()).scheduleAlarmLocked(anyLong(), anyBoolean());
685     }
686 
687     @Test
testStepIdleStateLocked_InvalidStates()688     public void testStepIdleStateLocked_InvalidStates() {
689         mDeviceIdleController.becomeActiveLocked("testing", 0);
690         mDeviceIdleController.stepIdleStateLocked("testing");
691         // mDeviceIdleController.stepIdleStateLocked doesn't handle the ACTIVE case, so the state
692         // should stay as ACTIVE.
693         verifyStateConditions(STATE_ACTIVE);
694     }
695 
696     @Test
testStepIdleStateLocked_ValidStates_QuickDoze()697     public void testStepIdleStateLocked_ValidStates_QuickDoze() {
698         setAlarmSoon(false);
699 
700         // Quick doze should go directly into IDLE.
701         enterDeepState(STATE_QUICK_DOZE_DELAY);
702         mDeviceIdleController.stepIdleStateLocked("testing");
703         verifyStateConditions(STATE_IDLE);
704 
705         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
706 
707         mDeviceIdleController.stepIdleStateLocked("testing");
708         verifyStateConditions(STATE_IDLE_MAINTENANCE);
709 
710         mDeviceIdleController.stepIdleStateLocked("testing");
711         verifyStateConditions(STATE_IDLE);
712 
713         mDeviceIdleController.stepIdleStateLocked("testing");
714         verifyStateConditions(STATE_IDLE_MAINTENANCE);
715     }
716 
717     @Test
testStepIdleStateLocked_ValidStates_WithWakeFromIdleAlarmSoon()718     public void testStepIdleStateLocked_ValidStates_WithWakeFromIdleAlarmSoon() {
719         enterDeepState(STATE_ACTIVE);
720         // Return that there's an alarm coming soon.
721         setAlarmSoon(true);
722         mDeviceIdleController.stepIdleStateLocked("testing");
723         verifyStateConditions(STATE_ACTIVE);
724 
725         // Everything besides ACTIVE should end up as INACTIVE since the screen would be off.
726 
727         enterDeepState(STATE_INACTIVE);
728         setAlarmSoon(true);
729         mDeviceIdleController.stepIdleStateLocked("testing");
730         verifyStateConditions(STATE_INACTIVE);
731 
732         enterDeepState(STATE_IDLE_PENDING);
733         setAlarmSoon(true);
734         mDeviceIdleController.stepIdleStateLocked("testing");
735         verifyStateConditions(STATE_INACTIVE);
736 
737         enterDeepState(STATE_SENSING);
738         setAlarmSoon(true);
739         mDeviceIdleController.stepIdleStateLocked("testing");
740         verifyStateConditions(STATE_INACTIVE);
741 
742         enterDeepState(STATE_LOCATING);
743         setAlarmSoon(true);
744         mDeviceIdleController.stepIdleStateLocked("testing");
745         verifyStateConditions(STATE_INACTIVE);
746 
747         // With quick doze enabled, we should end up in QUICK_DOZE_DELAY instead of INACTIVE.
748         enterDeepState(STATE_QUICK_DOZE_DELAY);
749         setQuickDozeEnabled(true);
750         setAlarmSoon(true);
751         mDeviceIdleController.stepIdleStateLocked("testing");
752         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
753 
754         // With quick doze disabled, we should end up in INACTIVE instead of QUICK_DOZE_DELAY.
755         enterDeepState(STATE_QUICK_DOZE_DELAY);
756         setQuickDozeEnabled(false);
757         setAlarmSoon(true);
758         mDeviceIdleController.stepIdleStateLocked("testing");
759         verifyStateConditions(STATE_INACTIVE);
760 
761         enterDeepState(STATE_IDLE);
762         setAlarmSoon(true);
763         mDeviceIdleController.stepIdleStateLocked("testing");
764         verifyStateConditions(STATE_INACTIVE);
765 
766         enterDeepState(STATE_IDLE_MAINTENANCE);
767         setAlarmSoon(true);
768         mDeviceIdleController.stepIdleStateLocked("testing");
769         verifyStateConditions(STATE_INACTIVE);
770     }
771 
772     @Test
testStepIdleStateLocked_ValidStates_NoLocationManager()773     public void testStepIdleStateLocked_ValidStates_NoLocationManager() {
774         mInjector.locationManager = null;
775         // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
776         setAlarmSoon(false);
777         // Set state to INACTIVE.
778         mDeviceIdleController.becomeActiveLocked("testing", 0);
779         setChargingOn(false);
780         setScreenOn(false);
781         verifyStateConditions(STATE_INACTIVE);
782 
783         mDeviceIdleController.stepIdleStateLocked("testing");
784         verifyStateConditions(STATE_IDLE_PENDING);
785 
786         mDeviceIdleController.stepIdleStateLocked("testing");
787         verifyStateConditions(STATE_SENSING);
788 
789         mDeviceIdleController.stepIdleStateLocked("testing");
790         // No location manager, so SENSING should go straight to IDLE.
791         verifyStateConditions(STATE_IDLE);
792 
793         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
794 
795         mDeviceIdleController.stepIdleStateLocked("testing");
796         verifyStateConditions(STATE_IDLE_MAINTENANCE);
797 
798         mDeviceIdleController.stepIdleStateLocked("testing");
799         verifyStateConditions(STATE_IDLE);
800 
801         mDeviceIdleController.stepIdleStateLocked("testing");
802         verifyStateConditions(STATE_IDLE_MAINTENANCE);
803     }
804 
805     @Test
testStepIdleStateLocked_ValidStates_WithLocationManager_NoProviders()806     public void testStepIdleStateLocked_ValidStates_WithLocationManager_NoProviders() {
807         // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
808         setAlarmSoon(false);
809         // Set state to INACTIVE.
810         mDeviceIdleController.becomeActiveLocked("testing", 0);
811         setChargingOn(false);
812         setScreenOn(false);
813         verifyStateConditions(STATE_INACTIVE);
814 
815         mDeviceIdleController.stepIdleStateLocked("testing");
816         verifyStateConditions(STATE_IDLE_PENDING);
817 
818         mDeviceIdleController.stepIdleStateLocked("testing");
819         verifyStateConditions(STATE_SENSING);
820 
821         mDeviceIdleController.stepIdleStateLocked("testing");
822         // Location manager exists but there isn't a network or GPS provider,
823         // so SENSING should go straight to IDLE.
824         verifyStateConditions(STATE_IDLE);
825 
826         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
827 
828         mDeviceIdleController.stepIdleStateLocked("testing");
829         verifyStateConditions(STATE_IDLE_MAINTENANCE);
830 
831         mDeviceIdleController.stepIdleStateLocked("testing");
832         verifyStateConditions(STATE_IDLE);
833 
834         mDeviceIdleController.stepIdleStateLocked("testing");
835         verifyStateConditions(STATE_IDLE_MAINTENANCE);
836     }
837 
838     @Test
testStepIdleStateLocked_ValidStates_WithLocationManager_WithProviders()839     public void testStepIdleStateLocked_ValidStates_WithLocationManager_WithProviders() {
840         mInjector.locationManager = mLocationManager;
841         doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(anyString());
842         // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
843         setAlarmSoon(false);
844         // Set state to INACTIVE.
845         mDeviceIdleController.becomeActiveLocked("testing", 0);
846         setChargingOn(false);
847         setScreenOn(false);
848         verifyStateConditions(STATE_INACTIVE);
849 
850         mDeviceIdleController.stepIdleStateLocked("testing");
851         verifyStateConditions(STATE_IDLE_PENDING);
852 
853         mDeviceIdleController.stepIdleStateLocked("testing");
854         verifyStateConditions(STATE_SENSING);
855 
856         mDeviceIdleController.stepIdleStateLocked("testing");
857         // Location manager exists with a provider, so SENSING should go to LOCATING.
858         verifyStateConditions(STATE_LOCATING);
859 
860         mDeviceIdleController.stepIdleStateLocked("testing");
861         verifyStateConditions(STATE_IDLE);
862 
863         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
864 
865         mDeviceIdleController.stepIdleStateLocked("testing");
866         verifyStateConditions(STATE_IDLE_MAINTENANCE);
867 
868         mDeviceIdleController.stepIdleStateLocked("testing");
869         verifyStateConditions(STATE_IDLE);
870 
871         mDeviceIdleController.stepIdleStateLocked("testing");
872         verifyStateConditions(STATE_IDLE_MAINTENANCE);
873     }
874 
875     @Test
testLightStepIdleStateLocked_InvalidStates()876     public void testLightStepIdleStateLocked_InvalidStates() {
877         mDeviceIdleController.becomeActiveLocked("testing", 0);
878         mDeviceIdleController.stepLightIdleStateLocked("testing");
879         // stepLightIdleStateLocked doesn't handle the ACTIVE case, so the state
880         // should stay as ACTIVE.
881         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
882     }
883 
884     /**
885      * Make sure stepLightIdleStateLocked doesn't change state when the state is
886      * LIGHT_STATE_OVERRIDE.
887      */
888     @Test
testLightStepIdleStateLocked_Overriden()889     public void testLightStepIdleStateLocked_Overriden() {
890         enterLightState(LIGHT_STATE_OVERRIDE);
891         mDeviceIdleController.stepLightIdleStateLocked("testing");
892         verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
893     }
894 
895     @Test
testLightStepIdleStateLocked_ValidStates_NoActiveOps_NetworkConnected()896     public void testLightStepIdleStateLocked_ValidStates_NoActiveOps_NetworkConnected() {
897         setNetworkConnected(true);
898         mDeviceIdleController.setJobsActive(false);
899         mDeviceIdleController.setAlarmsActive(false);
900         mDeviceIdleController.setActiveIdleOpsForTest(0);
901 
902         // Set state to INACTIVE.
903         mDeviceIdleController.becomeActiveLocked("testing", 0);
904         setChargingOn(false);
905         setScreenOn(false);
906         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
907 
908         // No active ops means INACTIVE should go straight to IDLE.
909         mDeviceIdleController.stepLightIdleStateLocked("testing");
910         verifyLightStateConditions(LIGHT_STATE_IDLE);
911 
912         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
913 
914         mDeviceIdleController.stepLightIdleStateLocked("testing");
915         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
916 
917         mDeviceIdleController.stepLightIdleStateLocked("testing");
918         verifyLightStateConditions(LIGHT_STATE_IDLE);
919 
920         mDeviceIdleController.stepLightIdleStateLocked("testing");
921         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
922     }
923 
924     @Test
testLightStepIdleStateLocked_ValidStates_ActiveOps_NetworkConnected()925     public void testLightStepIdleStateLocked_ValidStates_ActiveOps_NetworkConnected() {
926         setNetworkConnected(true);
927         // Set state to INACTIVE.
928         mDeviceIdleController.becomeActiveLocked("testing", 0);
929         setChargingOn(false);
930         setScreenOn(false);
931         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
932 
933         // Active ops means INACTIVE should go to PRE_IDLE to wait.
934         mDeviceIdleController.setJobsActive(true);
935         mDeviceIdleController.setAlarmsActive(true);
936         mDeviceIdleController.setActiveIdleOpsForTest(1);
937         mDeviceIdleController.stepLightIdleStateLocked("testing");
938         verifyLightStateConditions(LIGHT_STATE_PRE_IDLE);
939 
940         // Even with active ops, PRE_IDLE should go to IDLE.
941         mDeviceIdleController.stepLightIdleStateLocked("testing");
942         verifyLightStateConditions(LIGHT_STATE_IDLE);
943 
944         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
945 
946         mDeviceIdleController.stepLightIdleStateLocked("testing");
947         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
948 
949         mDeviceIdleController.stepLightIdleStateLocked("testing");
950         verifyLightStateConditions(LIGHT_STATE_IDLE);
951 
952         mDeviceIdleController.stepLightIdleStateLocked("testing");
953         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
954     }
955 
956     @Test
testLightStepIdleStateLocked_ValidStates_NoActiveOps_NoNetworkConnected()957     public void testLightStepIdleStateLocked_ValidStates_NoActiveOps_NoNetworkConnected() {
958         setNetworkConnected(false);
959         mDeviceIdleController.setJobsActive(false);
960         mDeviceIdleController.setAlarmsActive(false);
961         mDeviceIdleController.setActiveIdleOpsForTest(0);
962 
963         // Set state to INACTIVE.
964         mDeviceIdleController.becomeActiveLocked("testing", 0);
965         setChargingOn(false);
966         setScreenOn(false);
967         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
968 
969         // No active ops means INACTIVE should go straight to IDLE.
970         mDeviceIdleController.stepLightIdleStateLocked("testing");
971         verifyLightStateConditions(LIGHT_STATE_IDLE);
972 
973         // Should cycle between IDLE, WAITING_FOR_NETWORK, and IDLE_MAINTENANCE now.
974 
975         mDeviceIdleController.stepLightIdleStateLocked("testing");
976         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
977 
978         mDeviceIdleController.stepLightIdleStateLocked("testing");
979         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
980 
981         mDeviceIdleController.stepLightIdleStateLocked("testing");
982         verifyLightStateConditions(LIGHT_STATE_IDLE);
983 
984         mDeviceIdleController.stepLightIdleStateLocked("testing");
985         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
986 
987         mDeviceIdleController.stepLightIdleStateLocked("testing");
988         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
989     }
990 
991     @Test
testLightStepIdleStateLocked_ValidStates_ActiveOps_NoNetworkConnected()992     public void testLightStepIdleStateLocked_ValidStates_ActiveOps_NoNetworkConnected() {
993         setNetworkConnected(false);
994         // Set state to INACTIVE.
995         mDeviceIdleController.becomeActiveLocked("testing", 0);
996         setChargingOn(false);
997         setScreenOn(false);
998         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
999 
1000         // Active ops means INACTIVE should go to PRE_IDLE to wait.
1001         mDeviceIdleController.setJobsActive(true);
1002         mDeviceIdleController.setAlarmsActive(true);
1003         mDeviceIdleController.setActiveIdleOpsForTest(1);
1004         mDeviceIdleController.stepLightIdleStateLocked("testing");
1005         verifyLightStateConditions(LIGHT_STATE_PRE_IDLE);
1006 
1007         // Even with active ops, PRE_IDLE should go to IDLE.
1008         mDeviceIdleController.stepLightIdleStateLocked("testing");
1009         verifyLightStateConditions(LIGHT_STATE_IDLE);
1010 
1011         // Should cycle between IDLE, WAITING_FOR_NETWORK, and IDLE_MAINTENANCE now.
1012 
1013         mDeviceIdleController.stepLightIdleStateLocked("testing");
1014         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
1015 
1016         mDeviceIdleController.stepLightIdleStateLocked("testing");
1017         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
1018 
1019         mDeviceIdleController.stepLightIdleStateLocked("testing");
1020         verifyLightStateConditions(LIGHT_STATE_IDLE);
1021 
1022         mDeviceIdleController.stepLightIdleStateLocked("testing");
1023         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
1024 
1025         mDeviceIdleController.stepLightIdleStateLocked("testing");
1026         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
1027     }
1028 
1029     @Test
testLightIdleAlarmUnaffectedByMotion()1030     public void testLightIdleAlarmUnaffectedByMotion() {
1031         setNetworkConnected(true);
1032         mDeviceIdleController.setJobsActive(false);
1033         mDeviceIdleController.setAlarmsActive(false);
1034         mDeviceIdleController.setActiveIdleOpsForTest(0);
1035         spyOn(mDeviceIdleController);
1036 
1037         InOrder inOrder = inOrder(mDeviceIdleController);
1038 
1039         // Set state to INACTIVE.
1040         mDeviceIdleController.becomeActiveLocked("testing", 0);
1041         setChargingOn(false);
1042         setScreenOn(false);
1043         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1044 
1045         // No active ops means INACTIVE should go straight to IDLE.
1046         mDeviceIdleController.stepLightIdleStateLocked("testing");
1047         verifyLightStateConditions(LIGHT_STATE_IDLE);
1048         inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
1049                 longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT),
1050                 longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX));
1051 
1052         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
1053 
1054         mDeviceIdleController.stepLightIdleStateLocked("testing");
1055         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
1056         inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
1057                 longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET),
1058                 longThat(l -> l == mConstants.FLEX_TIME_SHORT));
1059 
1060         mDeviceIdleController.stepLightIdleStateLocked("testing");
1061         verifyLightStateConditions(LIGHT_STATE_IDLE);
1062         inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
1063                 longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT),
1064                 longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX));
1065 
1066         mDeviceIdleController.stepLightIdleStateLocked("testing");
1067         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
1068         inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
1069                 longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET),
1070                 longThat(l -> l == mConstants.FLEX_TIME_SHORT));
1071 
1072         // Test that motion doesn't reset the idle timeout.
1073         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1074 
1075         mDeviceIdleController.stepLightIdleStateLocked("testing");
1076         verifyLightStateConditions(LIGHT_STATE_IDLE);
1077         inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
1078                 longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT),
1079                 longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX));
1080     }
1081 
1082     ///////////////// EXIT conditions ///////////////////
1083 
1084     @Test
testExitMaintenanceEarlyIfNeededLocked_deep_noActiveOps()1085     public void testExitMaintenanceEarlyIfNeededLocked_deep_noActiveOps() {
1086         mDeviceIdleController.setJobsActive(false);
1087         mDeviceIdleController.setAlarmsActive(false);
1088         mDeviceIdleController.setActiveIdleOpsForTest(0);
1089 
1090         // This method should only change things if in IDLE_MAINTENANCE or PRE_IDLE states.
1091 
1092         enterDeepState(STATE_ACTIVE);
1093         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1094         verifyStateConditions(STATE_ACTIVE);
1095 
1096         enterDeepState(STATE_INACTIVE);
1097         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1098         verifyStateConditions(STATE_INACTIVE);
1099 
1100         enterDeepState(STATE_IDLE_PENDING);
1101         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1102         verifyStateConditions(STATE_IDLE_PENDING);
1103 
1104         enterDeepState(STATE_SENSING);
1105         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1106         verifyStateConditions(STATE_SENSING);
1107 
1108         enterDeepState(STATE_LOCATING);
1109         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1110         verifyStateConditions(STATE_LOCATING);
1111 
1112         enterDeepState(STATE_IDLE);
1113         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1114         verifyStateConditions(STATE_IDLE);
1115 
1116         enterDeepState(STATE_IDLE_MAINTENANCE);
1117         // Going into IDLE_MAINTENANCE increments the active idle op count.
1118         mDeviceIdleController.setActiveIdleOpsForTest(0);
1119         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1120         verifyStateConditions(STATE_IDLE);
1121 
1122         enterDeepState(STATE_QUICK_DOZE_DELAY);
1123         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1124         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1125     }
1126 
1127     @Test
testExitMaintenanceEarlyIfNeededLocked_deep_activeJobs()1128     public void testExitMaintenanceEarlyIfNeededLocked_deep_activeJobs() {
1129         mDeviceIdleController.setJobsActive(true);
1130         mDeviceIdleController.setAlarmsActive(false);
1131         mDeviceIdleController.setActiveIdleOpsForTest(0);
1132 
1133         // This method should only change things if in IDLE_MAINTENANCE or PRE_IDLE states.
1134 
1135         enterDeepState(STATE_ACTIVE);
1136         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1137         verifyStateConditions(STATE_ACTIVE);
1138 
1139         enterDeepState(STATE_INACTIVE);
1140         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1141         verifyStateConditions(STATE_INACTIVE);
1142 
1143         enterDeepState(STATE_IDLE_PENDING);
1144         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1145         verifyStateConditions(STATE_IDLE_PENDING);
1146 
1147         enterDeepState(STATE_SENSING);
1148         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1149         verifyStateConditions(STATE_SENSING);
1150 
1151         enterDeepState(STATE_LOCATING);
1152         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1153         verifyStateConditions(STATE_LOCATING);
1154 
1155         enterDeepState(STATE_IDLE);
1156         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1157         verifyStateConditions(STATE_IDLE);
1158 
1159         enterDeepState(STATE_IDLE_MAINTENANCE);
1160         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1161         verifyStateConditions(STATE_IDLE_MAINTENANCE);
1162 
1163         enterDeepState(STATE_QUICK_DOZE_DELAY);
1164         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1165         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1166     }
1167 
1168     @Test
testExitMaintenanceEarlyIfNeededLocked_deep_activeAlarms()1169     public void testExitMaintenanceEarlyIfNeededLocked_deep_activeAlarms() {
1170         mDeviceIdleController.setJobsActive(false);
1171         mDeviceIdleController.setAlarmsActive(true);
1172         mDeviceIdleController.setActiveIdleOpsForTest(0);
1173 
1174         // This method should only change things if in IDLE_MAINTENANCE or PRE_IDLE states.
1175 
1176         enterDeepState(STATE_ACTIVE);
1177         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1178         verifyStateConditions(STATE_ACTIVE);
1179 
1180         enterDeepState(STATE_INACTIVE);
1181         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1182         verifyStateConditions(STATE_INACTIVE);
1183 
1184         enterDeepState(STATE_IDLE_PENDING);
1185         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1186         verifyStateConditions(STATE_IDLE_PENDING);
1187 
1188         enterDeepState(STATE_SENSING);
1189         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1190         verifyStateConditions(STATE_SENSING);
1191 
1192         enterDeepState(STATE_LOCATING);
1193         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1194         verifyStateConditions(STATE_LOCATING);
1195 
1196         enterDeepState(STATE_IDLE);
1197         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1198         verifyStateConditions(STATE_IDLE);
1199 
1200         enterDeepState(STATE_IDLE_MAINTENANCE);
1201         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1202         verifyStateConditions(STATE_IDLE_MAINTENANCE);
1203 
1204         enterDeepState(STATE_QUICK_DOZE_DELAY);
1205         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1206         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1207     }
1208 
1209     @Test
testExitMaintenanceEarlyIfNeededLocked_deep_activeOps()1210     public void testExitMaintenanceEarlyIfNeededLocked_deep_activeOps() {
1211         mDeviceIdleController.setJobsActive(false);
1212         mDeviceIdleController.setAlarmsActive(false);
1213         mDeviceIdleController.setActiveIdleOpsForTest(1);
1214 
1215         // This method should only change things if in IDLE_MAINTENANCE or PRE_IDLE states.
1216 
1217         enterDeepState(STATE_ACTIVE);
1218         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1219         verifyStateConditions(STATE_ACTIVE);
1220 
1221         enterDeepState(STATE_INACTIVE);
1222         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1223         verifyStateConditions(STATE_INACTIVE);
1224 
1225         enterDeepState(STATE_IDLE_PENDING);
1226         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1227         verifyStateConditions(STATE_IDLE_PENDING);
1228 
1229         enterDeepState(STATE_SENSING);
1230         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1231         verifyStateConditions(STATE_SENSING);
1232 
1233         enterDeepState(STATE_LOCATING);
1234         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1235         verifyStateConditions(STATE_LOCATING);
1236 
1237         enterDeepState(STATE_IDLE);
1238         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1239         verifyStateConditions(STATE_IDLE);
1240 
1241         enterDeepState(STATE_IDLE_MAINTENANCE);
1242         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1243         verifyStateConditions(STATE_IDLE_MAINTENANCE);
1244 
1245         enterDeepState(STATE_QUICK_DOZE_DELAY);
1246         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1247         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1248     }
1249 
1250     @Test
testExitMaintenanceEarlyIfNeededLocked_light_noActiveOps()1251     public void testExitMaintenanceEarlyIfNeededLocked_light_noActiveOps() {
1252         mDeviceIdleController.setJobsActive(false);
1253         mDeviceIdleController.setAlarmsActive(false);
1254         mDeviceIdleController.setActiveIdleOpsForTest(0);
1255 
1256         // This method should only change things if in IDLE_MAINTENANCE or PRE_IDLE states.
1257 
1258         enterLightState(LIGHT_STATE_ACTIVE);
1259         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1260         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1261 
1262         enterLightState(LIGHT_STATE_INACTIVE);
1263         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1264         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1265 
1266         enterLightState(LIGHT_STATE_PRE_IDLE);
1267         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1268         verifyLightStateConditions(LIGHT_STATE_IDLE);
1269 
1270         enterLightState(LIGHT_STATE_IDLE);
1271         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1272         verifyLightStateConditions(LIGHT_STATE_IDLE);
1273 
1274         enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
1275         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1276         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
1277 
1278         enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
1279         // Going into IDLE_MAINTENANCE increments the active idle op count.
1280         mDeviceIdleController.setActiveIdleOpsForTest(0);
1281         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1282         verifyLightStateConditions(LIGHT_STATE_IDLE);
1283 
1284         enterLightState(LIGHT_STATE_OVERRIDE);
1285         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1286         verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
1287     }
1288 
1289     @Test
testExitMaintenanceEarlyIfNeededLocked_light_activeJobs()1290     public void testExitMaintenanceEarlyIfNeededLocked_light_activeJobs() {
1291         mDeviceIdleController.setJobsActive(true);
1292         mDeviceIdleController.setAlarmsActive(false);
1293         mDeviceIdleController.setActiveIdleOpsForTest(0);
1294 
1295         // This method should only change things if in IDLE_MAINTENANCE or PRE_IDLE states.
1296 
1297         enterLightState(LIGHT_STATE_ACTIVE);
1298         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1299         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1300 
1301         enterLightState(LIGHT_STATE_INACTIVE);
1302         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1303         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1304 
1305         enterLightState(LIGHT_STATE_PRE_IDLE);
1306         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1307         verifyLightStateConditions(LIGHT_STATE_PRE_IDLE);
1308 
1309         enterLightState(LIGHT_STATE_IDLE);
1310         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1311         verifyLightStateConditions(LIGHT_STATE_IDLE);
1312 
1313         enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
1314         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1315         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
1316 
1317         enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
1318         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1319         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
1320 
1321         enterLightState(LIGHT_STATE_OVERRIDE);
1322         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1323         verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
1324     }
1325 
1326     @Test
testExitMaintenanceEarlyIfNeededLocked_light_activeAlarms()1327     public void testExitMaintenanceEarlyIfNeededLocked_light_activeAlarms() {
1328         mDeviceIdleController.setJobsActive(false);
1329         mDeviceIdleController.setAlarmsActive(true);
1330         mDeviceIdleController.setActiveIdleOpsForTest(0);
1331 
1332         // This method should only change things if in IDLE_MAINTENANCE or PRE_IDLE states.
1333 
1334         enterLightState(LIGHT_STATE_ACTIVE);
1335         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1336         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1337 
1338         enterLightState(LIGHT_STATE_INACTIVE);
1339         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1340         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1341 
1342         enterLightState(LIGHT_STATE_PRE_IDLE);
1343         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1344         verifyLightStateConditions(LIGHT_STATE_PRE_IDLE);
1345 
1346         enterLightState(LIGHT_STATE_IDLE);
1347         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1348         verifyLightStateConditions(LIGHT_STATE_IDLE);
1349 
1350         enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
1351         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1352         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
1353 
1354         enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
1355         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1356         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
1357 
1358         enterLightState(LIGHT_STATE_OVERRIDE);
1359         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1360         verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
1361     }
1362 
1363     @Test
testExitMaintenanceEarlyIfNeededLocked_light_activeOps()1364     public void testExitMaintenanceEarlyIfNeededLocked_light_activeOps() {
1365         mDeviceIdleController.setJobsActive(false);
1366         mDeviceIdleController.setAlarmsActive(false);
1367         mDeviceIdleController.setActiveIdleOpsForTest(1);
1368 
1369         // This method should only change things if in IDLE_MAINTENANCE or PRE_IDLE states.
1370 
1371         enterLightState(LIGHT_STATE_ACTIVE);
1372         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1373         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1374 
1375         enterLightState(LIGHT_STATE_INACTIVE);
1376         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1377         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1378 
1379         enterLightState(LIGHT_STATE_PRE_IDLE);
1380         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1381         verifyLightStateConditions(LIGHT_STATE_PRE_IDLE);
1382 
1383         enterLightState(LIGHT_STATE_IDLE);
1384         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1385         verifyLightStateConditions(LIGHT_STATE_IDLE);
1386 
1387         enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
1388         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1389         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
1390 
1391         enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
1392         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1393         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
1394 
1395         enterLightState(LIGHT_STATE_OVERRIDE);
1396         mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
1397         verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
1398     }
1399 
1400     @Test
testHandleMotionDetectedLocked_deep_quickDoze_off()1401     public void testHandleMotionDetectedLocked_deep_quickDoze_off() {
1402         enterDeepState(STATE_ACTIVE);
1403         setQuickDozeEnabled(false);
1404         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1405         verifyStateConditions(STATE_ACTIVE);
1406 
1407         // Anything that wasn't ACTIVE before motion detection should end up in the INACTIVE state.
1408 
1409         enterDeepState(STATE_INACTIVE);
1410         setQuickDozeEnabled(false);
1411         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1412         verifyStateConditions(STATE_INACTIVE);
1413 
1414         enterDeepState(STATE_IDLE_PENDING);
1415         setQuickDozeEnabled(false);
1416         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1417         verifyStateConditions(STATE_INACTIVE);
1418 
1419         enterDeepState(STATE_SENSING);
1420         setQuickDozeEnabled(false);
1421         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1422         verifyStateConditions(STATE_INACTIVE);
1423 
1424         enterDeepState(STATE_LOCATING);
1425         setQuickDozeEnabled(false);
1426         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1427         verifyStateConditions(STATE_INACTIVE);
1428 
1429         enterDeepState(STATE_IDLE);
1430         setQuickDozeEnabled(false);
1431         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1432         verifyStateConditions(STATE_INACTIVE);
1433 
1434         enterDeepState(STATE_IDLE_MAINTENANCE);
1435         setQuickDozeEnabled(false);
1436         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1437         verifyStateConditions(STATE_INACTIVE);
1438 
1439         enterDeepState(STATE_QUICK_DOZE_DELAY);
1440         setQuickDozeEnabled(false);
1441         // Disabling quick doze doesn't immediately change the state as coming out is harder than
1442         // going in.
1443         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1444         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1445         verifyStateConditions(STATE_INACTIVE);
1446     }
1447 
1448     @Test
testHandleMotionDetectedLocked_deep_quickDoze_on()1449     public void testHandleMotionDetectedLocked_deep_quickDoze_on() {
1450         enterDeepState(STATE_ACTIVE);
1451         setQuickDozeEnabled(true);
1452         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1453         verifyStateConditions(STATE_ACTIVE);
1454 
1455         // Anything that wasn't ACTIVE before motion detection should end up in the
1456         // QUICK_DOZE_DELAY state since quick doze is enabled.
1457 
1458         enterDeepState(STATE_INACTIVE);
1459         setQuickDozeEnabled(true);
1460         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1461         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1462 
1463         enterDeepState(STATE_IDLE_PENDING);
1464         setQuickDozeEnabled(true);
1465         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1466         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1467 
1468         enterDeepState(STATE_SENSING);
1469         setQuickDozeEnabled(true);
1470         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1471         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1472 
1473         enterDeepState(STATE_LOCATING);
1474         setQuickDozeEnabled(true);
1475         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1476         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1477 
1478         enterDeepState(STATE_IDLE);
1479         setQuickDozeEnabled(true);
1480         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1481         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1482 
1483         enterDeepState(STATE_IDLE_MAINTENANCE);
1484         setQuickDozeEnabled(true);
1485         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1486         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1487 
1488         enterDeepState(STATE_QUICK_DOZE_DELAY);
1489         setQuickDozeEnabled(true);
1490         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1491         verifyStateConditions(STATE_QUICK_DOZE_DELAY);
1492     }
1493 
1494     @Test
testHandleMotionDetectedLocked_light()1495     public void testHandleMotionDetectedLocked_light() {
1496         enterLightState(LIGHT_STATE_ACTIVE);
1497         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1498         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1499 
1500         // Motion shouldn't affect light idle, so LIGHT states should stay as they were except for
1501         // OVERRIDE. OVERRIDE means deep was active, so if motion was detected,
1502         // LIGHT_STATE_OVERRIDE should end up as LIGHT_STATE_INACTIVE.
1503 
1504         enterLightState(LIGHT_STATE_INACTIVE);
1505         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1506         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1507 
1508         enterLightState(LIGHT_STATE_PRE_IDLE);
1509         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1510         verifyLightStateConditions(LIGHT_STATE_PRE_IDLE);
1511 
1512         enterLightState(LIGHT_STATE_IDLE);
1513         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1514         verifyLightStateConditions(LIGHT_STATE_IDLE);
1515 
1516         enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
1517         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1518         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
1519 
1520         enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
1521         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1522         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
1523 
1524         enterLightState(LIGHT_STATE_OVERRIDE);
1525         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
1526         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1527     }
1528 
1529     @Test
testBecomeActiveLocked_deep()1530     public void testBecomeActiveLocked_deep() {
1531         // becomeActiveLocked should put everything into ACTIVE.
1532 
1533         enterDeepState(STATE_ACTIVE);
1534         mDeviceIdleController.becomeActiveLocked("test", 1000);
1535         verifyStateConditions(STATE_ACTIVE);
1536 
1537         enterDeepState(STATE_INACTIVE);
1538         mDeviceIdleController.becomeActiveLocked("test", 1000);
1539         verifyStateConditions(STATE_ACTIVE);
1540 
1541         enterDeepState(STATE_IDLE_PENDING);
1542         mDeviceIdleController.becomeActiveLocked("test", 1000);
1543         verifyStateConditions(STATE_ACTIVE);
1544 
1545         enterDeepState(STATE_SENSING);
1546         mDeviceIdleController.becomeActiveLocked("test", 1000);
1547         verifyStateConditions(STATE_ACTIVE);
1548 
1549         enterDeepState(STATE_LOCATING);
1550         mDeviceIdleController.becomeActiveLocked("test", 1000);
1551         verifyStateConditions(STATE_ACTIVE);
1552 
1553         enterDeepState(STATE_IDLE);
1554         mDeviceIdleController.becomeActiveLocked("test", 1000);
1555         verifyStateConditions(STATE_ACTIVE);
1556 
1557         enterDeepState(STATE_IDLE_MAINTENANCE);
1558         mDeviceIdleController.becomeActiveLocked("test", 1000);
1559         verifyStateConditions(STATE_ACTIVE);
1560 
1561         enterDeepState(STATE_QUICK_DOZE_DELAY);
1562         mDeviceIdleController.becomeActiveLocked("test", 1000);
1563         verifyStateConditions(STATE_ACTIVE);
1564     }
1565 
1566     @Test
testBecomeActiveLocked_light()1567     public void testBecomeActiveLocked_light() {
1568         // becomeActiveLocked should put everything into ACTIVE.
1569 
1570         enterLightState(LIGHT_STATE_ACTIVE);
1571         mDeviceIdleController.becomeActiveLocked("test", 1000);
1572         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1573 
1574         enterLightState(LIGHT_STATE_INACTIVE);
1575         mDeviceIdleController.becomeActiveLocked("test", 1000);
1576         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1577 
1578         enterLightState(LIGHT_STATE_PRE_IDLE);
1579         mDeviceIdleController.becomeActiveLocked("test", 1000);
1580         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1581 
1582         enterLightState(LIGHT_STATE_IDLE);
1583         mDeviceIdleController.becomeActiveLocked("test", 1000);
1584         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1585 
1586         enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
1587         mDeviceIdleController.becomeActiveLocked("test", 1000);
1588         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1589 
1590         enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
1591         mDeviceIdleController.becomeActiveLocked("test", 1000);
1592         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1593 
1594         enterLightState(LIGHT_STATE_OVERRIDE);
1595         mDeviceIdleController.becomeActiveLocked("test", 1000);
1596         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1597     }
1598 
1599     /** Test based on b/119058625. */
1600     @Test
testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOn_ScreenThenMotion()1601     public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOn_ScreenThenMotion() {
1602         mConstants.WAIT_FOR_UNLOCK = true;
1603         enterDeepState(STATE_IDLE);
1604         reset(mAlarmManager);
1605         spyOn(mDeviceIdleController);
1606 
1607         mDeviceIdleController.keyguardShowingLocked(true);
1608         setScreenOn(true);
1609         // With WAIT_FOR_UNLOCK = true and the screen locked, turning the screen on by itself
1610         // shouldn't bring the device out of deep IDLE.
1611         verifyStateConditions(STATE_IDLE);
1612         mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
1613         // Motion should bring the device out of Doze. Since the screen is still locked (albeit
1614         // on), the states should go back into INACTIVE.
1615         verifyStateConditions(STATE_INACTIVE);
1616         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1617         verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1618         verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
1619     }
1620 
1621     /** Test based on b/119058625. */
1622     @Test
testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOff_ScreenThenMotion()1623     public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOff_ScreenThenMotion() {
1624         mConstants.WAIT_FOR_UNLOCK = true;
1625         enterDeepState(STATE_IDLE);
1626         reset(mAlarmManager);
1627         spyOn(mDeviceIdleController);
1628 
1629         mDeviceIdleController.keyguardShowingLocked(false);
1630         setScreenOn(true);
1631         // With WAIT_FOR_UNLOCK = true and the screen unlocked, turning the screen on by itself
1632         // should bring the device out of deep IDLE.
1633         verifyStateConditions(STATE_ACTIVE);
1634         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1635         verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1636         verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
1637     }
1638 
1639     /** Test based on b/119058625. */
1640     @Test
testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOn_MotionThenScreen()1641     public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOn_MotionThenScreen() {
1642         mConstants.WAIT_FOR_UNLOCK = true;
1643         enterDeepState(STATE_IDLE);
1644         reset(mAlarmManager);
1645         spyOn(mDeviceIdleController);
1646 
1647         InOrder alarmManagerInOrder = inOrder(mAlarmManager);
1648         InOrder controllerInOrder = inOrder(mDeviceIdleController);
1649 
1650         mDeviceIdleController.keyguardShowingLocked(true);
1651         mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
1652         // The screen is still off, so motion should result in the INACTIVE state.
1653         verifyStateConditions(STATE_INACTIVE);
1654         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1655         alarmManagerInOrder.verify(mAlarmManager)
1656                 .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1657         controllerInOrder.verify(mDeviceIdleController)
1658                 .scheduleReportActiveLocked(anyString(), anyInt());
1659 
1660         setScreenOn(true);
1661         // With WAIT_FOR_UNLOCK = true and the screen locked, turning the screen on by itself
1662         // shouldn't bring the device all the way to ACTIVE.
1663         verifyStateConditions(STATE_INACTIVE);
1664         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1665         alarmManagerInOrder.verify(mAlarmManager, never()).cancel(
1666                 eq(mDeviceIdleController.mDeepAlarmListener));
1667 
1668         // User finally unlocks the device. Device should be fully active.
1669         mDeviceIdleController.keyguardShowingLocked(false);
1670         verifyStateConditions(STATE_ACTIVE);
1671         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1672         alarmManagerInOrder.verify(mAlarmManager)
1673                 .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1674         controllerInOrder.verify(mDeviceIdleController)
1675                 .scheduleReportActiveLocked(anyString(), anyInt());
1676     }
1677 
1678     /** Test based on b/119058625. */
1679     @Test
testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOff_MotionThenScreen()1680     public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOff_MotionThenScreen() {
1681         mConstants.WAIT_FOR_UNLOCK = true;
1682         enterDeepState(STATE_IDLE);
1683         reset(mAlarmManager);
1684         spyOn(mDeviceIdleController);
1685 
1686         InOrder alarmManagerInOrder = inOrder(mAlarmManager);
1687         InOrder controllerInOrder = inOrder(mDeviceIdleController);
1688 
1689         mDeviceIdleController.keyguardShowingLocked(false);
1690         mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
1691         // The screen is still off, so motion should result in the INACTIVE state.
1692         verifyStateConditions(STATE_INACTIVE);
1693         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1694         alarmManagerInOrder.verify(mAlarmManager)
1695                 .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1696         controllerInOrder.verify(mDeviceIdleController)
1697                 .scheduleReportActiveLocked(anyString(), anyInt());
1698 
1699         setScreenOn(true);
1700         // With WAIT_FOR_UNLOCK = true and the screen unlocked, turning the screen on by itself
1701         // should bring the device out of deep IDLE.
1702         verifyStateConditions(STATE_ACTIVE);
1703         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1704         alarmManagerInOrder.verify(mAlarmManager)
1705                 .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1706         controllerInOrder.verify(mDeviceIdleController)
1707                 .scheduleReportActiveLocked(anyString(), anyInt());
1708     }
1709 
1710     @Test
testExitNotifiesDependencies_WaitForUnlockOff_Screen()1711     public void testExitNotifiesDependencies_WaitForUnlockOff_Screen() {
1712         mConstants.WAIT_FOR_UNLOCK = false;
1713         enterDeepState(STATE_IDLE);
1714         reset(mAlarmManager);
1715         spyOn(mDeviceIdleController);
1716 
1717         setScreenOn(true);
1718         // With WAIT_FOR_UNLOCK = false and the screen locked, turning the screen on by itself
1719         // should bring the device out of deep IDLE.
1720         verifyStateConditions(STATE_ACTIVE);
1721         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1722         verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1723         verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
1724     }
1725 
1726     @Test
testExitNotifiesDependencies_WaitForUnlockOff_MotionThenScreen()1727     public void testExitNotifiesDependencies_WaitForUnlockOff_MotionThenScreen() {
1728         mConstants.WAIT_FOR_UNLOCK = false;
1729         enterDeepState(STATE_IDLE);
1730         reset(mAlarmManager);
1731         spyOn(mDeviceIdleController);
1732 
1733         InOrder alarmManagerInOrder = inOrder(mAlarmManager);
1734         InOrder controllerInOrder = inOrder(mDeviceIdleController);
1735 
1736         mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
1737         // The screen is still off, so motion should result in the INACTIVE state.
1738         verifyStateConditions(STATE_INACTIVE);
1739         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
1740         alarmManagerInOrder.verify(mAlarmManager)
1741                 .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1742         controllerInOrder.verify(mDeviceIdleController)
1743                 .scheduleReportActiveLocked(anyString(), anyInt());
1744 
1745         setScreenOn(true);
1746         // With WAIT_FOR_UNLOCK = false and the screen locked, turning the screen on by itself
1747         // should bring the device out of deep IDLE.
1748         verifyStateConditions(STATE_ACTIVE);
1749         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
1750         alarmManagerInOrder.verify(mAlarmManager)
1751                 .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
1752         controllerInOrder.verify(mDeviceIdleController)
1753                 .scheduleReportActiveLocked(anyString(), anyInt());
1754     }
1755 
1756     @Test
testStepToIdleMode()1757     public void testStepToIdleMode() {
1758         float delta = mDeviceIdleController.MIN_PRE_IDLE_FACTOR_CHANGE;
1759         for (int mode = PowerManager.PRE_IDLE_TIMEOUT_MODE_NORMAL;
1760                 mode <= PowerManager.PRE_IDLE_TIMEOUT_MODE_LONG;
1761                 mode++) {
1762             int ret = mDeviceIdleController.setPreIdleTimeoutMode(mode);
1763             if (mode == PowerManager.PRE_IDLE_TIMEOUT_MODE_NORMAL) {
1764                 assertEquals("setPreIdleTimeoutMode: " + mode + " failed.",
1765                         mDeviceIdleController.SET_IDLE_FACTOR_RESULT_IGNORED, ret);
1766             } else {
1767                 assertEquals("setPreIdleTimeoutMode: " + mode + " failed.",
1768                         mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK, ret);
1769             }
1770             //TODO(b/123045185): Mocked Handler of DeviceIdleController to make message loop
1771             //workable in this test class
1772             float expectedfactor = mDeviceIdleController.getPreIdleTimeoutByMode(mode);
1773             float curfactor = mDeviceIdleController.getPreIdleTimeoutFactor();
1774             assertEquals("Pre idle time factor of mode [" + mode + "].",
1775                     expectedfactor, curfactor, delta);
1776             mDeviceIdleController.resetPreIdleTimeoutMode();
1777 
1778             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_INACTIVE);
1779             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_IDLE_PENDING);
1780 
1781             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_SENSING);
1782             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_LOCATING);
1783             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_QUICK_DOZE_DELAY);
1784             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_IDLE_MAINTENANCE);
1785             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_IDLE);
1786             checkMaybeDoAnImmediateMaintenance(expectedfactor);
1787         }
1788         float curfactor = mDeviceIdleController.getPreIdleTimeoutFactor();
1789         assertEquals("Pre idle time factor of mode default.",
1790                 1.0f, curfactor, delta);
1791     }
1792 
1793     @Test
testStationaryDetection_QuickDozeOff()1794     public void testStationaryDetection_QuickDozeOff() {
1795         setQuickDozeEnabled(false);
1796         enterDeepState(STATE_IDLE);
1797         // Regular progression through states, so time should have increased appropriately.
1798         mInjector.nowElapsed += mConstants.IDLE_AFTER_INACTIVE_TIMEOUT + mConstants.SENSING_TIMEOUT
1799                 + mConstants.LOCATING_TIMEOUT;
1800 
1801         StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
1802 
1803         mDeviceIdleController.registerStationaryListener(stationaryListener);
1804 
1805         // Go to IDLE_MAINTENANCE
1806         mDeviceIdleController.stepIdleStateLocked("testing");
1807 
1808         // Back to IDLE
1809         mDeviceIdleController.stepIdleStateLocked("testing");
1810         assertTrue(stationaryListener.isStationary);
1811 
1812         // Test motion
1813         stationaryListener.motionExpected = true;
1814         mDeviceIdleController.mMotionListener.onTrigger(null);
1815         assertFalse(stationaryListener.isStationary);
1816     }
1817 
1818     @Test
testStationaryDetection_QuickDozeOn_NoMotion()1819     public void testStationaryDetection_QuickDozeOn_NoMotion() {
1820         // Short timeout for testing.
1821         mConstants.MOTION_INACTIVE_TIMEOUT = 6000L;
1822         doReturn(Sensor.REPORTING_MODE_ONE_SHOT).when(mMotionSensor).getReportingMode();
1823         doReturn(true).when(mSensorManager)
1824                 .requestTriggerSensor(eq(mDeviceIdleController.mMotionListener), eq(mMotionSensor));
1825         setAlarmSoon(false);
1826         enterDeepState(STATE_QUICK_DOZE_DELAY);
1827         mDeviceIdleController.stepIdleStateLocked("testing");
1828         verifyStateConditions(STATE_IDLE);
1829         // Quick doze progression through states, so time should have increased appropriately.
1830         mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
1831         final ArgumentCaptor<AlarmManager.OnAlarmListener> motionAlarmListener = ArgumentCaptor
1832                 .forClass(AlarmManager.OnAlarmListener.class);
1833         final ArgumentCaptor<AlarmManager.OnAlarmListener> motionRegistrationAlarmListener =
1834                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
1835         doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
1836                 eq("DeviceIdleController.motion"), motionAlarmListener.capture(), any());
1837         doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
1838                 eq("DeviceIdleController.motion_registration"),
1839                 motionRegistrationAlarmListener.capture(), any());
1840 
1841         StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
1842         spyOn(stationaryListener);
1843         InOrder inOrder = inOrder(stationaryListener);
1844 
1845         stationaryListener.motionExpected = true;
1846         mDeviceIdleController.registerStationaryListener(stationaryListener);
1847         inOrder.verify(stationaryListener, timeout(1000L).times(1))
1848                 .onDeviceStationaryChanged(eq(false));
1849         assertFalse(stationaryListener.isStationary);
1850 
1851         // Go to IDLE_MAINTENANCE
1852         mDeviceIdleController.stepIdleStateLocked("testing");
1853 
1854         mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
1855 
1856         // Back to IDLE
1857         mDeviceIdleController.stepIdleStateLocked("testing");
1858 
1859         // Now enough time has passed.
1860         mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT;
1861         stationaryListener.motionExpected = false;
1862         motionAlarmListener.getValue().onAlarm();
1863         inOrder.verify(stationaryListener, timeout(1000L).times(1))
1864                 .onDeviceStationaryChanged(eq(true));
1865         assertTrue(stationaryListener.isStationary);
1866 
1867         stationaryListener.motionExpected = true;
1868         mDeviceIdleController.mMotionListener.onTrigger(null);
1869         inOrder.verify(stationaryListener, timeout(1000L).times(1))
1870                 .onDeviceStationaryChanged(eq(false));
1871         assertFalse(stationaryListener.isStationary);
1872 
1873         // Since we're in quick doze, the device shouldn't stop idling.
1874         verifyStateConditions(STATE_IDLE);
1875 
1876         // Go to IDLE_MAINTENANCE
1877         mDeviceIdleController.stepIdleStateLocked("testing");
1878 
1879         motionRegistrationAlarmListener.getValue().onAlarm();
1880         mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
1881 
1882         // Back to IDLE
1883         stationaryListener.motionExpected = false;
1884         mDeviceIdleController.stepIdleStateLocked("testing");
1885         verify(mSensorManager,
1886                 timeout(mConstants.MOTION_INACTIVE_TIMEOUT).times(2))
1887                 .requestTriggerSensor(eq(mDeviceIdleController.mMotionListener), eq(mMotionSensor));
1888 
1889         // Now enough time has passed.
1890         mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT;
1891         motionAlarmListener.getValue().onAlarm();
1892         inOrder.verify(stationaryListener,
1893                 timeout(mConstants.MOTION_INACTIVE_TIMEOUT).times(1))
1894                 .onDeviceStationaryChanged(eq(true));
1895         assertTrue(stationaryListener.isStationary);
1896     }
1897 
1898     @Test
testStationaryDetection_QuickDozeOn_OneShot()1899     public void testStationaryDetection_QuickDozeOn_OneShot() {
1900         // Short timeout for testing.
1901         mConstants.MOTION_INACTIVE_TIMEOUT = 6000L;
1902         doReturn(Sensor.REPORTING_MODE_ONE_SHOT).when(mMotionSensor).getReportingMode();
1903         setAlarmSoon(false);
1904         enterDeepState(STATE_QUICK_DOZE_DELAY);
1905         mDeviceIdleController.stepIdleStateLocked("testing");
1906         verifyStateConditions(STATE_IDLE);
1907         // Quick doze progression through states, so time should have increased appropriately.
1908         mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
1909         final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListener = ArgumentCaptor
1910                 .forClass(AlarmManager.OnAlarmListener.class);
1911         doNothing().when(mAlarmManager).setWindow(
1912                 anyInt(), anyLong(), anyLong(), eq("DeviceIdleController.motion"), any(), any());
1913         doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
1914                 eq("DeviceIdleController.motion_registration"),
1915                 alarmListener.capture(), any());
1916         ArgumentCaptor<TriggerEventListener> listenerCaptor =
1917                 ArgumentCaptor.forClass(TriggerEventListener.class);
1918 
1919         StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
1920         spyOn(stationaryListener);
1921         InOrder inOrder = inOrder(stationaryListener, mSensorManager);
1922 
1923         stationaryListener.motionExpected = true;
1924         mDeviceIdleController.registerStationaryListener(stationaryListener);
1925         inOrder.verify(stationaryListener, timeout(1000L).times(1))
1926                 .onDeviceStationaryChanged(eq(false));
1927         assertFalse(stationaryListener.isStationary);
1928         inOrder.verify(mSensorManager)
1929                 .requestTriggerSensor(listenerCaptor.capture(), eq(mMotionSensor));
1930         final TriggerEventListener listener = listenerCaptor.getValue();
1931 
1932         // Trigger motion
1933         listener.onTrigger(mock(TriggerEvent.class));
1934         inOrder.verify(stationaryListener, timeout(1000L).times(1))
1935                 .onDeviceStationaryChanged(eq(false));
1936 
1937         // Make sure the listener is re-registered.
1938         alarmListener.getValue().onAlarm();
1939         inOrder.verify(mSensorManager).requestTriggerSensor(eq(listener), eq(mMotionSensor));
1940     }
1941 
1942     @Test
testStationaryDetection_QuickDozeOn_MultiShot()1943     public void testStationaryDetection_QuickDozeOn_MultiShot() {
1944         // Short timeout for testing.
1945         mConstants.MOTION_INACTIVE_TIMEOUT = 6000L;
1946         doReturn(Sensor.REPORTING_MODE_CONTINUOUS).when(mMotionSensor).getReportingMode();
1947         setAlarmSoon(false);
1948         enterDeepState(STATE_QUICK_DOZE_DELAY);
1949         mDeviceIdleController.stepIdleStateLocked("testing");
1950         verifyStateConditions(STATE_IDLE);
1951         // Quick doze progression through states, so time should have increased appropriately.
1952         mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
1953         final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListener = ArgumentCaptor
1954                 .forClass(AlarmManager.OnAlarmListener.class);
1955         doNothing().when(mAlarmManager).setWindow(
1956                 anyInt(), anyLong(), anyLong(), eq("DeviceIdleController.motion"), any(), any());
1957         doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
1958                 eq("DeviceIdleController.motion_registration"),
1959                 alarmListener.capture(), any());
1960         ArgumentCaptor<SensorEventListener> listenerCaptor =
1961                 ArgumentCaptor.forClass(SensorEventListener.class);
1962 
1963         StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
1964         spyOn(stationaryListener);
1965         InOrder inOrder = inOrder(stationaryListener, mSensorManager);
1966 
1967         stationaryListener.motionExpected = true;
1968         mDeviceIdleController.registerStationaryListener(stationaryListener);
1969         inOrder.verify(stationaryListener, timeout(1000L).times(1))
1970                 .onDeviceStationaryChanged(eq(false));
1971         assertFalse(stationaryListener.isStationary);
1972         inOrder.verify(mSensorManager)
1973                 .registerListener(listenerCaptor.capture(), eq(mMotionSensor),
1974                         eq(SensorManager.SENSOR_DELAY_NORMAL));
1975         final SensorEventListener listener = listenerCaptor.getValue();
1976 
1977         // Trigger motion
1978         listener.onSensorChanged(mock(SensorEvent.class));
1979         inOrder.verify(stationaryListener, timeout(1000L).times(1))
1980                 .onDeviceStationaryChanged(eq(false));
1981 
1982         // Make sure the listener is re-registered.
1983         alarmListener.getValue().onAlarm();
1984         inOrder.verify(mSensorManager)
1985                 .registerListener(eq(listener), eq(mMotionSensor),
1986                         eq(SensorManager.SENSOR_DELAY_NORMAL));
1987     }
1988 
enterDeepState(int state)1989     private void enterDeepState(int state) {
1990         switch (state) {
1991             case STATE_ACTIVE:
1992                 setScreenOn(true);
1993                 mDeviceIdleController.becomeActiveLocked("testing", 0);
1994                 break;
1995             case STATE_QUICK_DOZE_DELAY:
1996                 // Start off from ACTIVE in case we're already past the desired state.
1997                 enterDeepState(STATE_ACTIVE);
1998                 setQuickDozeEnabled(true);
1999                 setScreenOn(false);
2000                 setChargingOn(false);
2001                 mDeviceIdleController.becomeInactiveIfAppropriateLocked();
2002                 break;
2003             case STATE_LOCATING:
2004                 mInjector.locationManager = mLocationManager;
2005                 doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(
2006                         anyString());
2007                 // Fallthrough to step loop.
2008             case STATE_IDLE_PENDING:
2009             case STATE_SENSING:
2010             case STATE_IDLE:
2011             case STATE_IDLE_MAINTENANCE:
2012                 // Make sure the controller doesn't think there's a wake-from-idle alarm coming
2013                 // soon.
2014                 setAlarmSoon(false);
2015             case STATE_INACTIVE:
2016                 // Start off from ACTIVE in case we're already past the desired state.
2017                 enterDeepState(STATE_ACTIVE);
2018                 setQuickDozeEnabled(false);
2019                 setScreenOn(false);
2020                 setChargingOn(false);
2021                 mDeviceIdleController.becomeInactiveIfAppropriateLocked();
2022                 int count = 0;
2023                 while (mDeviceIdleController.getState() != state) {
2024                     // Stepping through each state ensures that the proper features are turned
2025                     // on/off.
2026                     mDeviceIdleController.stepIdleStateLocked("testing");
2027                     count++;
2028                     if (count > 10) {
2029                         fail("Infinite loop. Check test configuration. Currently at " +
2030                                 stateToString(mDeviceIdleController.getState()));
2031                     }
2032                 }
2033                 break;
2034             default:
2035                 fail("Unknown deep state " + stateToString(state));
2036         }
2037     }
2038 
enterLightState(int lightState)2039     private void enterLightState(int lightState) {
2040         switch (lightState) {
2041             case LIGHT_STATE_ACTIVE:
2042                 setScreenOn(true);
2043                 mDeviceIdleController.becomeActiveLocked("testing", 0);
2044                 break;
2045             case LIGHT_STATE_INACTIVE:
2046             case LIGHT_STATE_IDLE:
2047             case LIGHT_STATE_IDLE_MAINTENANCE:
2048                 // Start off from ACTIVE in case we're already past the desired state.
2049                 enterLightState(LIGHT_STATE_ACTIVE);
2050                 setScreenOn(false);
2051                 setChargingOn(false);
2052                 int count = 0;
2053                 mDeviceIdleController.becomeInactiveIfAppropriateLocked();
2054                 while (mDeviceIdleController.getLightState() != lightState) {
2055                     // Stepping through each state ensures that the proper features are turned
2056                     // on/off.
2057                     mDeviceIdleController.stepLightIdleStateLocked("testing");
2058 
2059                     count++;
2060                     if (count > 10) {
2061                         fail("Infinite loop. Check test configuration. Currently at " +
2062                                 lightStateToString(mDeviceIdleController.getLightState()));
2063                     }
2064                 }
2065                 break;
2066             case LIGHT_STATE_PRE_IDLE:
2067             case LIGHT_STATE_WAITING_FOR_NETWORK:
2068             case LIGHT_STATE_OVERRIDE:
2069                 setScreenOn(false);
2070                 setChargingOn(false);
2071                 mDeviceIdleController.setLightStateForTest(lightState);
2072                 break;
2073             default:
2074                 fail("Unknown light state " + lightStateToString(lightState));
2075         }
2076     }
2077 
setChargingOn(boolean on)2078     private void setChargingOn(boolean on) {
2079         mDeviceIdleController.updateChargingLocked(on);
2080     }
2081 
setScreenLocked(boolean locked)2082     private void setScreenLocked(boolean locked) {
2083         mDeviceIdleController.keyguardShowingLocked(locked);
2084     }
2085 
setScreenOn(boolean on)2086     private void setScreenOn(boolean on) {
2087         doReturn(on).when(mPowerManager).isInteractive();
2088         mDeviceIdleController.updateInteractivityLocked();
2089     }
2090 
setNetworkConnected(boolean connected)2091     private void setNetworkConnected(boolean connected) {
2092         mInjector.connectivityManager = mConnectivityManager;
2093         final NetworkInfo ani = mock(NetworkInfo.class);
2094         doReturn(connected).when(ani).isConnected();
2095         doReturn(ani).when(mConnectivityManager).getActiveNetworkInfo();
2096         mDeviceIdleController.updateConnectivityState(null);
2097     }
2098 
setQuickDozeEnabled(boolean on)2099     private void setQuickDozeEnabled(boolean on) {
2100         mDeviceIdleController.updateQuickDozeFlagLocked(on);
2101     }
2102 
setAlarmSoon(boolean isSoon)2103     private void setAlarmSoon(boolean isSoon) {
2104         if (isSoon) {
2105             doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2)
2106                     .when(mAlarmManager).getNextWakeFromIdleTime();
2107         } else {
2108             doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime();
2109         }
2110     }
2111 
verifyStateConditions(int expectedState)2112     private void verifyStateConditions(int expectedState) {
2113         int curState = mDeviceIdleController.getState();
2114         assertEquals(
2115                 "Expected " + stateToString(expectedState) + " but was " + stateToString(curState),
2116                 expectedState, curState);
2117 
2118         switch (expectedState) {
2119             case STATE_ACTIVE:
2120                 assertFalse(mDeviceIdleController.mMotionListener.isActive());
2121                 assertFalse(mAnyMotionDetector.isMonitoring);
2122                 break;
2123             case STATE_INACTIVE:
2124                 assertFalse(mDeviceIdleController.mMotionListener.isActive());
2125                 assertFalse(mAnyMotionDetector.isMonitoring);
2126                 assertFalse(mDeviceIdleController.isCharging());
2127                 assertFalse(mDeviceIdleController.isScreenOn()
2128                         && !mDeviceIdleController.isKeyguardShowing());
2129                 break;
2130             case STATE_IDLE_PENDING:
2131                 assertEquals(
2132                         mDeviceIdleController.hasMotionSensor(),
2133                         mDeviceIdleController.mMotionListener.isActive());
2134                 assertFalse(mAnyMotionDetector.isMonitoring);
2135                 assertFalse(mDeviceIdleController.isCharging());
2136                 assertFalse(mDeviceIdleController.isScreenOn()
2137                         && !mDeviceIdleController.isKeyguardShowing());
2138                 break;
2139             case STATE_SENSING:
2140                 assertEquals(
2141                         mDeviceIdleController.hasMotionSensor(),
2142                         mDeviceIdleController.mMotionListener.isActive());
2143                 assertEquals(
2144                         mDeviceIdleController.hasMotionSensor(),
2145                         mAnyMotionDetector.isMonitoring);
2146                 assertFalse(mDeviceIdleController.isCharging());
2147                 assertFalse(mDeviceIdleController.isScreenOn()
2148                         && !mDeviceIdleController.isKeyguardShowing());
2149                 break;
2150             case STATE_LOCATING:
2151                 assertEquals(
2152                         mDeviceIdleController.hasMotionSensor(),
2153                         mDeviceIdleController.mMotionListener.isActive());
2154                 assertFalse(mDeviceIdleController.isCharging());
2155                 assertFalse(mDeviceIdleController.isScreenOn()
2156                         && !mDeviceIdleController.isKeyguardShowing());
2157                 break;
2158             case STATE_IDLE:
2159                 if (mDeviceIdleController.hasMotionSensor()) {
2160                     assertTrue(mDeviceIdleController.mMotionListener.isActive()
2161                         // If quick doze is enabled, the motion listener should NOT be active.
2162                         || mDeviceIdleController.isQuickDozeEnabled());
2163                 }
2164                 assertFalse(mAnyMotionDetector.isMonitoring);
2165                 assertFalse(mDeviceIdleController.isCharging());
2166                 assertFalse(mDeviceIdleController.isScreenOn()
2167                         && !mDeviceIdleController.isKeyguardShowing());
2168                 // Light state should be OVERRIDE at this point.
2169                 verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
2170                 break;
2171             case STATE_IDLE_MAINTENANCE:
2172                 if (mDeviceIdleController.hasMotionSensor()) {
2173                     assertTrue(mDeviceIdleController.mMotionListener.isActive()
2174                         // If quick doze is enabled, the motion listener should NOT be active.
2175                         || mDeviceIdleController.isQuickDozeEnabled());
2176                 }
2177                 assertFalse(mAnyMotionDetector.isMonitoring);
2178                 assertFalse(mDeviceIdleController.isCharging());
2179                 assertFalse(mDeviceIdleController.isScreenOn()
2180                         && !mDeviceIdleController.isKeyguardShowing());
2181                 break;
2182             case STATE_QUICK_DOZE_DELAY:
2183                 // If quick doze is enabled, the motion listener should NOT be active.
2184                 assertFalse(mDeviceIdleController.mMotionListener.isActive());
2185                 assertFalse(mAnyMotionDetector.isMonitoring);
2186                 assertFalse(mDeviceIdleController.isCharging());
2187                 assertFalse(mDeviceIdleController.isScreenOn()
2188                         && !mDeviceIdleController.isKeyguardShowing());
2189                 break;
2190             default:
2191                 fail("Conditions for " + stateToString(expectedState) + " unknown.");
2192         }
2193     }
2194 
verifyLightStateConditions(int expectedLightState)2195     private void verifyLightStateConditions(int expectedLightState) {
2196         int curLightState = mDeviceIdleController.getLightState();
2197         assertEquals(
2198                 "Expected " + lightStateToString(expectedLightState)
2199                         + " but was " + lightStateToString(curLightState),
2200                 expectedLightState, curLightState);
2201 
2202         switch (expectedLightState) {
2203             case LIGHT_STATE_ACTIVE:
2204                 assertTrue(
2205                         mDeviceIdleController.isCharging() || mDeviceIdleController.isScreenOn()
2206                                 // Or there's an alarm coming up soon.
2207                                 || SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM
2208                                 > mAlarmManager.getNextWakeFromIdleTime());
2209                 break;
2210             case LIGHT_STATE_INACTIVE:
2211             case LIGHT_STATE_PRE_IDLE:
2212             case LIGHT_STATE_IDLE:
2213             case LIGHT_STATE_WAITING_FOR_NETWORK:
2214             case LIGHT_STATE_IDLE_MAINTENANCE:
2215             case LIGHT_STATE_OVERRIDE:
2216                 assertFalse(mDeviceIdleController.isCharging());
2217                 assertFalse(mDeviceIdleController.isScreenOn()
2218                         && !mDeviceIdleController.isKeyguardShowing());
2219                 break;
2220             default:
2221                 fail("Conditions for " + lightStateToString(expectedLightState) + " unknown.");
2222         }
2223     }
2224 
checkNextAlarmTimeWithNewPreIdleFactor(float factor, int state)2225     private void checkNextAlarmTimeWithNewPreIdleFactor(float factor, int state) {
2226         final long errorTolerance = 1000;
2227         enterDeepState(state);
2228         long now = SystemClock.elapsedRealtime();
2229         long alarm = mDeviceIdleController.getNextAlarmTime();
2230         if (state == STATE_INACTIVE || state == STATE_IDLE_PENDING) {
2231             int ret = mDeviceIdleController.setPreIdleTimeoutFactor(factor);
2232             if (Float.compare(factor, 1.0f) == 0) {
2233                 assertEquals("setPreIdleTimeoutMode: " + factor + " failed.",
2234                         mDeviceIdleController.SET_IDLE_FACTOR_RESULT_IGNORED, ret);
2235             } else {
2236                 assertEquals("setPreIdleTimeoutMode: " + factor + " failed.",
2237                         mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK, ret);
2238             }
2239             if (ret == mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK) {
2240                 long newAlarm = mDeviceIdleController.getNextAlarmTime();
2241                 long newDelay = (long) ((alarm - now) * factor);
2242                 assertTrue("setPreIdleTimeoutFactor: " + factor,
2243                         Math.abs(newDelay - (newAlarm - now)) <  errorTolerance);
2244                 mDeviceIdleController.resetPreIdleTimeoutMode();
2245                 newAlarm = mDeviceIdleController.getNextAlarmTime();
2246                 assertTrue("resetPreIdleTimeoutMode from: " + factor,
2247                         Math.abs(newAlarm - alarm) < errorTolerance);
2248                 mDeviceIdleController.setPreIdleTimeoutFactor(factor);
2249                 now = SystemClock.elapsedRealtime();
2250                 enterDeepState(state);
2251                 newAlarm = mDeviceIdleController.getNextAlarmTime();
2252                 assertTrue("setPreIdleTimeoutFactor: " + factor + " before step to idle",
2253                         Math.abs(newDelay - (newAlarm - now)) <  errorTolerance);
2254                 mDeviceIdleController.resetPreIdleTimeoutMode();
2255             }
2256         } else {
2257             mDeviceIdleController.setPreIdleTimeoutFactor(factor);
2258             long newAlarm = mDeviceIdleController.getNextAlarmTime();
2259             assertTrue("setPreIdleTimeoutFactor: " + factor
2260                     + " shounld not change next alarm" ,
2261                     (newAlarm == alarm));
2262             mDeviceIdleController.resetPreIdleTimeoutMode();
2263         }
2264     }
2265 
checkMaybeDoAnImmediateMaintenance(float factor)2266     private void checkMaybeDoAnImmediateMaintenance(float factor) {
2267         int ret = mDeviceIdleController.setPreIdleTimeoutFactor(factor);
2268         final long minuteInMillis = 60 * 1000;
2269         if (Float.compare(factor, 1.0f) == 0) {
2270             assertEquals("setPreIdleTimeoutMode: " + factor + " failed.",
2271                     mDeviceIdleController.SET_IDLE_FACTOR_RESULT_IGNORED, ret);
2272         } else {
2273             assertEquals("setPreIdleTimeoutMode: " + factor + " failed.",
2274                     mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK, ret);
2275         }
2276         if (ret == mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK) {
2277             enterDeepState(STATE_IDLE);
2278             long now = SystemClock.elapsedRealtime();
2279             long alarm = mDeviceIdleController.getNextAlarmTime();
2280             mDeviceIdleController.setIdleStartTimeForTest(
2281                     now - (long) (mConstants.IDLE_TIMEOUT * 0.6));
2282             long newAlarm = mDeviceIdleController.getNextAlarmTime();
2283             assertTrue("maintenance not reschedule IDLE_TIMEOUT * 0.6",
2284                     newAlarm == alarm);
2285             mDeviceIdleController.setIdleStartTimeForTest(
2286                     now - (long) (mConstants.IDLE_TIMEOUT * 1.2));
2287             newAlarm = mDeviceIdleController.getNextAlarmTime();
2288             assertTrue("maintenance not reschedule IDLE_TIMEOUT * 1.2",
2289                     (newAlarm - now) < minuteInMillis);
2290             mDeviceIdleController.resetPreIdleTimeoutMode();
2291         }
2292     }
2293 }
2294