1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car;
18 
19 import static android.content.pm.UserInfo.FLAG_EPHEMERAL;
20 import static android.content.pm.UserInfo.FLAG_GUEST;
21 import static android.os.UserHandle.USER_SYSTEM;
22 
23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.junit.Assert.fail;
28 import static org.mockito.ArgumentMatchers.anyInt;
29 import static org.mockito.ArgumentMatchers.anyString;
30 import static org.mockito.ArgumentMatchers.eq;
31 import static org.mockito.ArgumentMatchers.notNull;
32 import static org.mockito.Mockito.never;
33 import static org.mockito.Mockito.times;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.when;
36 
37 import static java.lang.annotation.ElementType.METHOD;
38 import static java.lang.annotation.RetentionPolicy.RUNTIME;
39 
40 import android.annotation.Nullable;
41 import android.app.ActivityManager;
42 import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
43 import android.car.hardware.power.ICarPowerStateListener;
44 import android.car.userlib.CarUserManagerHelper;
45 import android.content.Context;
46 import android.content.pm.UserInfo;
47 import android.content.res.Resources;
48 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
49 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam;
50 import android.os.RemoteException;
51 import android.os.UserManager;
52 import android.test.suitebuilder.annotation.SmallTest;
53 import android.util.Log;
54 
55 import androidx.test.platform.app.InstrumentationRegistry;
56 
57 import com.android.car.hal.PowerHalService;
58 import com.android.car.hal.PowerHalService.PowerState;
59 import com.android.car.systeminterface.DisplayInterface;
60 import com.android.car.systeminterface.IOInterface;
61 import com.android.car.systeminterface.SystemInterface;
62 import com.android.car.systeminterface.SystemStateInterface;
63 import com.android.car.systeminterface.WakeLockInterface;
64 import com.android.car.test.utils.TemporaryDirectory;
65 
66 import org.junit.After;
67 import org.junit.Before;
68 import org.junit.Rule;
69 import org.junit.Test;
70 import org.junit.rules.TestRule;
71 import org.junit.rules.TestWatcher;
72 import org.junit.runner.Description;
73 import org.junit.runner.RunWith;
74 import org.mockito.Mock;
75 import org.mockito.MockitoSession;
76 import org.mockito.junit.MockitoJUnitRunner;
77 import org.mockito.quality.Strictness;
78 
79 import java.io.File;
80 import java.io.IOException;
81 import java.lang.annotation.Retention;
82 import java.lang.annotation.Target;
83 import java.lang.reflect.Method;
84 import java.time.Duration;
85 import java.util.concurrent.CompletableFuture;
86 import java.util.concurrent.Semaphore;
87 import java.util.concurrent.TimeUnit;
88 
89 @SmallTest
90 @RunWith(MockitoJUnitRunner.class)
91 public class CarPowerManagementServiceTest {
92     private static final String TAG = CarPowerManagementServiceTest.class.getSimpleName();
93     private static final long WAIT_TIMEOUT_MS = 2000;
94     private static final long WAIT_TIMEOUT_LONG_MS = 5000;
95     private static final int NO_USER_INFO_FLAGS = 0;
96     private static final String NEW_GUEST_NAME = "NewestGuestInTheBlock";
97 
98     private final MockDisplayInterface mDisplayInterface = new MockDisplayInterface();
99     private final MockSystemStateInterface mSystemStateInterface = new MockSystemStateInterface();
100     private final MockWakeLockInterface mWakeLockInterface = new MockWakeLockInterface();
101     private final MockIOInterface mIOInterface = new MockIOInterface();
102     private final PowerSignalListener mPowerSignalListener = new PowerSignalListener();
103     private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
104 
105     private MockitoSession mSession;
106 
107     private MockedPowerHalService mPowerHal;
108     private SystemInterface mSystemInterface;
109     private CarPowerManagementService mService;
110     private CompletableFuture<Void> mFuture;
111 
112     @Mock
113     private CarUserManagerHelper mCarUserManagerHelper;
114     @Mock
115     private UserManager mUserManager;
116     @Mock
117     private Resources mResources;
118 
119     // Wakeup time for the test; it's automatically set based on @WakeupTime annotation
120     private int mWakeupTime;
121 
122     // Value used to set config_disableUserSwitchDuringResume - must be defined before initTest();
123     private boolean mDisableUserSwitchDuringResume;
124 
125     @Rule
126     public final TestRule setWakeupTimeRule = new TestWatcher() {
127         protected void starting(Description description) {
128             final String testName = description.getMethodName();
129             try {
130                 Method testMethod = CarPowerManagementServiceTest.class.getMethod(testName);
131                 WakeupTime wakeupAnnotation = testMethod.getAnnotation(WakeupTime.class);
132                 if (wakeupAnnotation != null) {
133                     mWakeupTime = wakeupAnnotation.value();
134                     Log.d(TAG, "Using annotated wakeup time: " + mWakeupTime);
135                 }
136             } catch (Exception e) {
137                 Log.e(TAG, "Could not infer wakeupTime for " + testName, e);
138             }
139         }
140     };
141 
142     @Before
setUp()143     public void setUp() throws Exception {
144         mSession = mockitoSession()
145                 .strictness(Strictness.LENIENT)
146                 .spyStatic(ActivityManager.class)
147                 .startMocking();
148         mPowerHal = new MockedPowerHalService(true /*isPowerStateSupported*/,
149                 true /*isDeepSleepAllowed*/, true /*isTimedWakeupAllowed*/);
150         mSystemInterface = SystemInterface.Builder.defaultSystemInterface(mContext)
151             .withDisplayInterface(mDisplayInterface)
152             .withSystemStateInterface(mSystemStateInterface)
153             .withWakeLockInterface(mWakeLockInterface)
154             .withIOInterface(mIOInterface).build();
155     }
156 
157     @After
tearDown()158     public void tearDown() throws Exception {
159         if (mService != null) {
160             mService.release();
161         }
162         mIOInterface.tearDown();
163         mSession.finishMocking();
164     }
165 
166     /**
167      * Helper method to create mService and initialize a test case
168      */
initTest()169     private void initTest() throws Exception {
170         when(mResources.getInteger(R.integer.maxGarageModeRunningDurationInSecs))
171                 .thenReturn(900);
172         when(mResources.getBoolean(R.bool.config_disableUserSwitchDuringResume))
173                 .thenReturn(mDisableUserSwitchDuringResume);
174 
175         Log.i(TAG, "initTest(): overridden overlay properties: "
176                 + "config_disableUserSwitchDuringResume="
177                 + mResources.getBoolean(R.bool.config_disableUserSwitchDuringResume)
178                 + ", maxGarageModeRunningDurationInSecs="
179                 + mResources.getInteger(R.integer.maxGarageModeRunningDurationInSecs));
180         mService = new CarPowerManagementService(mContext, mResources, mPowerHal,
181                 mSystemInterface, mCarUserManagerHelper, mUserManager, NEW_GUEST_NAME);
182         mService.init();
183         CarPowerManagementService.setShutdownPrepareTimeout(0);
184         mPowerHal.setSignalListener(mPowerSignalListener);
185         if (mWakeupTime > 0) {
186             registerListenerToService();
187             mService.scheduleNextWakeupTime(mWakeupTime);
188         }
189         assertStateReceived(MockedPowerHalService.SET_WAIT_FOR_VHAL, 0);
190     }
191 
192     @Test
testBootComplete()193     public void testBootComplete() throws Exception {
194         initTest();
195     }
196 
197     @Test
testDisplayOn()198     public void testDisplayOn() throws Exception {
199         // start with display off
200         mSystemInterface.setDisplayState(false);
201         mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
202         initTest();
203         // Transition to ON state
204         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
205 
206         // display should be turned on as it started with off state.
207         assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
208     }
209 
210     @Test
testShutdown()211     public void testShutdown() throws Exception {
212         initTest();
213 
214         // Transition to ON state
215         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
216         assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
217 
218         mPowerHal.setCurrentPowerState(
219                 new PowerState(
220                         VehicleApPowerStateReq.SHUTDOWN_PREPARE,
221                         VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY));
222         // Since modules have to manually schedule next wakeup, we should not schedule next wakeup
223         // To test module behavior, we need to actually implement mock listener module.
224         assertStateReceived(PowerHalService.SET_SHUTDOWN_START, 0);
225         assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isFalse();
226         mPowerSignalListener.waitForShutdown(WAIT_TIMEOUT_MS);
227         mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
228     }
229 
230     @Test
testSuspend()231     public void testSuspend() throws Exception {
232         initTest();
233 
234         // Start in the ON state
235         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
236         assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
237         // Request suspend
238         mPowerHal.setCurrentPowerState(
239                 new PowerState(
240                         VehicleApPowerStateReq.SHUTDOWN_PREPARE,
241                         VehicleApPowerStateShutdownParam.CAN_SLEEP));
242         // Verify suspend
243         assertStateReceivedForShutdownOrSleepWithPostpone(
244                 PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
245     }
246 
247     @Test
testShutdownOnSuspend()248     public void testShutdownOnSuspend() throws Exception {
249         initTest();
250 
251         // Start in the ON state
252         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
253         assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
254         // Tell it to shutdown
255         mService.requestShutdownOnNextSuspend();
256         // Request suspend
257         mPowerHal.setCurrentPowerState(
258                 new PowerState(
259                         VehicleApPowerStateReq.SHUTDOWN_PREPARE,
260                         VehicleApPowerStateShutdownParam.CAN_SLEEP));
261         // Verify shutdown
262         assertStateReceivedForShutdownOrSleepWithPostpone(
263                 PowerHalService.SET_SHUTDOWN_START, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
264         mPowerSignalListener.waitForShutdown(WAIT_TIMEOUT_MS);
265         // Send the finished signal
266         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
267         mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
268         // Cancel the shutdown
269         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.CANCEL_SHUTDOWN, 0));
270         assertStateReceivedForShutdownOrSleepWithPostpone(
271                 PowerHalService.SET_SHUTDOWN_CANCELLED, WAIT_TIMEOUT_LONG_MS, 0);
272 
273         // Request suspend again
274         mPowerHal.setCurrentPowerState(
275                 new PowerState(
276                         VehicleApPowerStateReq.SHUTDOWN_PREPARE,
277                         VehicleApPowerStateShutdownParam.CAN_SLEEP));
278         // Verify suspend
279         assertStateReceivedForShutdownOrSleepWithPostpone(
280                 PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
281     }
282 
283     @Test
testShutdownCancel()284     public void testShutdownCancel() throws Exception {
285         initTest();
286 
287         // Start in the ON state
288         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
289         assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
290         // Start shutting down
291         mPowerHal.setCurrentPowerState(
292                 new PowerState(
293                         VehicleApPowerStateReq.SHUTDOWN_PREPARE,
294                         VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY));
295         assertStateReceivedForShutdownOrSleepWithPostpone(
296                 PowerHalService.SET_SHUTDOWN_START, WAIT_TIMEOUT_LONG_MS, 0);
297         // Cancel the shutdown
298         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.CANCEL_SHUTDOWN, 0));
299         assertStateReceivedForShutdownOrSleepWithPostpone(
300                 PowerHalService.SET_SHUTDOWN_CANCELLED, WAIT_TIMEOUT_LONG_MS, 0);
301         // Go to suspend
302         mPowerHal.setCurrentPowerState(
303                 new PowerState(
304                         VehicleApPowerStateReq.SHUTDOWN_PREPARE,
305                         VehicleApPowerStateShutdownParam.CAN_SLEEP));
306         assertStateReceivedForShutdownOrSleepWithPostpone(
307                 PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
308     }
309 
310     @Test
311     @WakeupTime(100)
testShutdownWithProcessing()312     public void testShutdownWithProcessing() throws Exception {
313         initTest();
314         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, 0));
315         assertStateReceivedForShutdownOrSleepWithPostpone(
316                 PowerHalService.SET_SHUTDOWN_START, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
317         mPowerSignalListener.waitForShutdown(WAIT_TIMEOUT_MS);
318         // Send the finished signal
319         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
320         mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
321     }
322 
323     @Test
324     @WakeupTime(100)
testSleepEntryAndWakeup()325     public void testSleepEntryAndWakeup() throws Exception {
326         initTest();
327         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE,
328                 VehicleApPowerStateShutdownParam.CAN_SLEEP));
329         assertStateReceivedForShutdownOrSleepWithPostpone(
330                 PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
331         mPowerSignalListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
332         // Send the finished signal from HAL to CPMS
333         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
334         mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
335         assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
336         mPowerSignalListener.waitForSleepExit(WAIT_TIMEOUT_MS);
337     }
338 
339     @Test
testUserSwitchingOnResume_differentUser()340     public void testUserSwitchingOnResume_differentUser() throws Exception {
341         initTest();
342         setUserInfo(10, NO_USER_INFO_FLAGS);
343         setUserInfo(11, NO_USER_INFO_FLAGS);
344         setCurrentUser(10);
345         setInitialUser(11);
346 
347         suspendAndResumeForUserSwitchingTests();
348 
349         verifyUserSwitched(11);
350     }
351 
352     @Test
testUserSwitchingOnResume_sameUser()353     public void testUserSwitchingOnResume_sameUser() throws Exception {
354         initTest();
355         setUserInfo(10, NO_USER_INFO_FLAGS);
356         setInitialUser(10);
357         setCurrentUser(10);
358 
359         suspendAndResumeForUserSwitchingTests();
360 
361         verifyUserNotSwitched();
362     }
363 
364     @Test
testUserSwitchingOnResume_differentEphemeralUser()365     public void testUserSwitchingOnResume_differentEphemeralUser() throws Exception {
366         initTest();
367         setUserInfo(10, NO_USER_INFO_FLAGS);
368         setUserInfo(11, FLAG_EPHEMERAL);
369         setCurrentUser(10);
370         setInitialUser(11);
371 
372         suspendAndResumeForUserSwitchingTests();
373 
374         verifyUserSwitched(11);
375     }
376 
377     @Test
testUserSwitchingOnResume_sameGuest()378     public void testUserSwitchingOnResume_sameGuest() throws Exception {
379         initTest();
380         setUserInfo(10, "ElGuesto", FLAG_GUEST | FLAG_EPHEMERAL);
381         setInitialUser(10);
382         setCurrentUser(10);
383         expectGuestMarkedForDeletionOk(10);
384         expectNewGuestCreated(11);
385 
386         suspendAndResumeForUserSwitchingTests();
387 
388         verifyUserRemoved(10);
389         verifyUserSwitched(11);
390     }
391 
392     @Test
testUserSwitchingOnResume_differentGuest()393     public void testUserSwitchingOnResume_differentGuest() throws Exception {
394         initTest();
395         setUserInfo(11, "ElGuesto", FLAG_GUEST | FLAG_EPHEMERAL);
396         setInitialUser(11);
397         setCurrentUser(10);
398         expectGuestMarkedForDeletionOk(11);
399         expectNewGuestCreated(12);
400 
401         suspendAndResumeForUserSwitchingTests();
402 
403         verifyUserRemoved(11);
404         verifyUserSwitched(12);
405     }
406 
407     @Test
testUserSwitchingOnResume_guestCreationFailed()408     public void testUserSwitchingOnResume_guestCreationFailed() throws Exception {
409         initTest();
410         setUserInfo(10, "ElGuesto", FLAG_GUEST | FLAG_EPHEMERAL);
411         setInitialUser(10);
412         setCurrentUser(10);
413         expectGuestMarkedForDeletionOk(10);
414         expectNewGuestCreationFailed("ElGuesto");
415 
416         suspendAndResumeForUserSwitchingTests();
417 
418         verifyUserNotSwitched();
419         verifyUserNotRemoved(10);
420     }
421 
422     @Test
testUserSwitchingOnResume_differentPersistentGuest()423     public void testUserSwitchingOnResume_differentPersistentGuest() throws Exception {
424         initTest();
425         setUserInfo(11, "ElGuesto", FLAG_GUEST);
426         setInitialUser(11);
427         setCurrentUser(10);
428         expectGuestMarkedForDeletionOk(11);
429         expectNewGuestCreated(12);
430 
431         suspendAndResumeForUserSwitchingTests();
432 
433         verifyUserRemoved(11);
434         verifyUserSwitched(12);
435     }
436 
437     @Test
testUserSwitchingOnResume_preDeleteGuestFail()438     public void testUserSwitchingOnResume_preDeleteGuestFail() throws Exception {
439         initTest();
440         setUserInfo(10, "ElGuesto", FLAG_GUEST | FLAG_EPHEMERAL);
441         setInitialUser(10);
442         setCurrentUser(10);
443         expectGuestMarkedForDeletionFail(10);
444 
445         suspendAndResumeForUserSwitchingTests();
446 
447         verifyUserNotSwitched();
448         verifyNoGuestCreated();
449     }
450 
451     @Test
testUserSwitchingOnResume_systemUser()452     public void testUserSwitchingOnResume_systemUser() throws Exception {
453         initTest();
454         setInitialUser(USER_SYSTEM);
455         setCurrentUser(10);
456 
457         suspendAndResumeForUserSwitchingTests();
458 
459         verifyUserNotSwitched();
460     }
461 
462     @Test
testUserSwitchingOnResume_disabledByOEM_differentUser()463     public void testUserSwitchingOnResume_disabledByOEM_differentUser() throws Exception {
464         disableUserSwitchingDuringResume();
465         initTest();
466         setUserInfo(10, NO_USER_INFO_FLAGS);
467         setUserInfo(11, NO_USER_INFO_FLAGS);
468         setCurrentUser(10);
469         setInitialUser(11);
470 
471         suspendAndResumeForUserSwitchingTests();
472 
473         verifyUserNotSwitched();
474     }
475 
476     @Test
testUserSwitchingOnResume_disabledByOEM_sameUser()477     public void testUserSwitchingOnResume_disabledByOEM_sameUser() throws Exception {
478         disableUserSwitchingDuringResume();
479         initTest();
480         setUserInfo(10, NO_USER_INFO_FLAGS);
481         setInitialUser(10);
482         setCurrentUser(10);
483 
484         suspendAndResumeForUserSwitchingTests();
485 
486         verifyUserNotSwitched();
487     }
488 
489     @Test
testUserSwitchingOnResume_disabledByOEM_differentEphemeralUser()490     public void testUserSwitchingOnResume_disabledByOEM_differentEphemeralUser() throws Exception {
491         disableUserSwitchingDuringResume();
492         initTest();
493         setUserInfo(10, NO_USER_INFO_FLAGS);
494         setUserInfo(11, FLAG_EPHEMERAL);
495         setCurrentUser(10);
496         setInitialUser(11);
497 
498         suspendAndResumeForUserSwitchingTests();
499 
500         verifyUserNotSwitched();
501     }
502 
503     @Test
testUserSwitchingOnResume_disabledByOEM_sameGuest()504     public void testUserSwitchingOnResume_disabledByOEM_sameGuest() throws Exception {
505         disableUserSwitchingDuringResume();
506         initTest();
507         setUserInfo(10, "ElGuesto", FLAG_GUEST | FLAG_EPHEMERAL);
508         setInitialUser(10);
509         setCurrentUser(10);
510         expectGuestMarkedForDeletionOk(10);
511         expectNewGuestCreated(11);
512 
513         suspendAndResumeForUserSwitchingTests();
514 
515         verifyUserRemoved(10);
516         verifyUserSwitched(11);
517 
518     }
519 
520     @Test
testUserSwitchingOnResume_disabledByOEM_differentGuest()521     public void testUserSwitchingOnResume_disabledByOEM_differentGuest() throws Exception {
522         disableUserSwitchingDuringResume();
523         initTest();
524         setUserInfo(11, "ElGuesto", FLAG_GUEST | FLAG_EPHEMERAL);
525         setInitialUser(11);
526         setCurrentUser(10);
527         expectGuestMarkedForDeletionOk(11);
528         expectNewGuestCreated(12);
529 
530         suspendAndResumeForUserSwitchingTests();
531 
532         verifyUserRemoved(11);
533         verifyUserSwitched(12);
534     }
535 
536     @Test
testUserSwitchingOnResume_disabledByOEM_guestCreationFailed()537     public void testUserSwitchingOnResume_disabledByOEM_guestCreationFailed() throws Exception {
538         disableUserSwitchingDuringResume();
539         initTest();
540         initTest();
541         setUserInfo(10, "ElGuesto", FLAG_GUEST | FLAG_EPHEMERAL);
542         setInitialUser(10);
543         setCurrentUser(10);
544         expectGuestMarkedForDeletionOk(10);
545         expectNewGuestCreationFailed("ElGuesto");
546 
547         suspendAndResumeForUserSwitchingTests();
548 
549         verifyUserNotSwitched();
550         verifyUserNotRemoved(10);
551     }
552 
553     @Test
testUserSwitchingOnResume_disabledByOEM_differentPersistentGuest()554     public void testUserSwitchingOnResume_disabledByOEM_differentPersistentGuest()
555             throws Exception {
556         disableUserSwitchingDuringResume();
557         initTest();
558         setUserInfo(11, "ElGuesto", FLAG_GUEST);
559         setInitialUser(11);
560         setCurrentUser(10);
561         expectGuestMarkedForDeletionOk(11);
562         expectNewGuestCreated(12);
563 
564         suspendAndResumeForUserSwitchingTests();
565 
566         verifyUserRemoved(11);
567         verifyUserSwitched(12);
568     }
569 
570     @Test
testUserSwitchingOnResume_disabledByOEM_preDeleteGuestFail()571     public void testUserSwitchingOnResume_disabledByOEM_preDeleteGuestFail() throws Exception {
572         disableUserSwitchingDuringResume();
573         initTest();
574         setUserInfo(10, "ElGuesto", FLAG_GUEST | FLAG_EPHEMERAL);
575         setInitialUser(10);
576         setCurrentUser(10);
577         expectGuestMarkedForDeletionFail(10);
578 
579         suspendAndResumeForUserSwitchingTests();
580 
581         verifyUserNotSwitched();
582         verifyNoGuestCreated();
583     }
584 
585     @Test
testUserSwitchingOnResume_disabledByOEM_systemUser()586     public void testUserSwitchingOnResume_disabledByOEM_systemUser() throws Exception {
587         disableUserSwitchingDuringResume();
588         initTest();
589         setInitialUser(USER_SYSTEM);
590         setCurrentUser(10);
591 
592         suspendAndResumeForUserSwitchingTests();
593 
594         verifyUserNotSwitched();
595     }
596 
suspendAndResumeForUserSwitchingTests()597     private void suspendAndResumeForUserSwitchingTests() throws Exception {
598         Log.d(TAG, "suspend()");
599         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE,
600                 VehicleApPowerStateShutdownParam.CAN_SLEEP));
601         assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isFalse();
602         assertStateReceivedForShutdownOrSleepWithPostpone(
603                 PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
604         mPowerSignalListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
605 
606         // Send the finished signal
607         Log.d(TAG, "resume()");
608         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
609         mSystemStateInterface.setWakeupCausedByTimer(true);
610         mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
611         assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
612         mPowerSignalListener.waitForSleepExit(WAIT_TIMEOUT_MS);
613         mService.scheduleNextWakeupTime(mWakeupTime);
614         // second processing after wakeup
615         assertThat(mDisplayInterface.getDisplayState()).isFalse();
616 
617         mService.setStateForTesting(/* isBooting= */ false, /* isResuming= */ true);
618 
619         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.ON, 0));
620         assertThat(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS)).isTrue();
621         // Should wait until Handler has finished ON processing.
622         CarServiceUtils.runOnLooperSync(mService.getHandlerThread().getLooper(), () -> { });
623         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE,
624                 VehicleApPowerStateShutdownParam.CAN_SLEEP));
625         assertStateReceivedForShutdownOrSleepWithPostpone(
626                 PowerHalService.SET_DEEP_SLEEP_ENTRY, WAIT_TIMEOUT_LONG_MS, mWakeupTime);
627         mPowerSignalListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
628         mPowerHal.setCurrentPowerState(new PowerState(VehicleApPowerStateReq.FINISHED, 0));
629         // PM will shutdown system as it was not woken-up due timer and it is not power on.
630         mSystemStateInterface.setWakeupCausedByTimer(false);
631         mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
632         // Since we just woke up from shutdown, wake up time will be 0
633         assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
634         assertThat(mDisplayInterface.getDisplayState()).isFalse();
635     }
636 
registerListenerToService()637     private void registerListenerToService() {
638         ICarPowerStateListener listenerToService = new ICarPowerStateListener.Stub() {
639             @Override
640             public void onStateChanged(int state) throws RemoteException {
641                 if (state == CarPowerStateListener.SHUTDOWN_ENTER
642                         || state == CarPowerStateListener.SUSPEND_ENTER) {
643                     mFuture = new CompletableFuture<>();
644                     mFuture.whenComplete((res, ex) -> {
645                         if (ex == null) {
646                             mService.finished(this);
647                         }
648                     });
649                 } else {
650                     mFuture = null;
651                 }
652             }
653         };
654         mService.registerListener(listenerToService);
655     }
656 
assertStateReceived(int expectedState, int expectedParam)657     private void assertStateReceived(int expectedState, int expectedParam) throws Exception {
658         int[] state = mPowerHal.waitForSend(WAIT_TIMEOUT_MS);
659         assertThat(state[0]).isEqualTo(expectedState);
660         assertThat(state[1]).isEqualTo(expectedParam);
661     }
662 
assertStateReceivedForShutdownOrSleepWithPostpone( int lastState, long timeoutMs, int expectedParamForShutdownOrSuspend)663     private void assertStateReceivedForShutdownOrSleepWithPostpone(
664             int lastState, long timeoutMs, int expectedParamForShutdownOrSuspend) throws Exception {
665         while (true) {
666             if (mFuture != null && !mFuture.isDone()) {
667                 mFuture.complete(null);
668             }
669             int[] state = mPowerHal.waitForSend(timeoutMs);
670             if (state[0] == PowerHalService.SET_SHUTDOWN_POSTPONE) {
671                 continue;
672             }
673             if (state[0] == lastState) {
674                 assertThat(state[1]).isEqualTo(expectedParamForShutdownOrSuspend);
675                 return;
676             }
677         }
678     }
679 
waitForSemaphore(Semaphore semaphore, long timeoutMs)680     private static void waitForSemaphore(Semaphore semaphore, long timeoutMs)
681             throws InterruptedException {
682         if (!semaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
683             throw new IllegalStateException("timeout");
684         }
685     }
686 
setInitialUser(int userId)687     private void setInitialUser(int userId) {
688         when(mCarUserManagerHelper.getInitialUser()).thenReturn(userId);
689     }
690 
setCurrentUser(int userId)691     private void setCurrentUser(int userId) {
692         when(ActivityManager.getCurrentUser()).thenReturn(userId);
693     }
694 
setUserInfo(int userId, int flags)695     private void setUserInfo(int userId, int flags) {
696         setUserInfo(userId, /* name= */ null, flags);
697     }
698 
setUserInfo(int userId, @Nullable String name, int flags)699     private void setUserInfo(int userId, @Nullable String name, int flags) {
700         final UserInfo userInfo = new UserInfo();
701         userInfo.id = userId;
702         userInfo.name = name;
703         userInfo.flags = flags;
704         Log.v(TAG, "UM.getUserInfo("  + userId + ") will return " + userInfo.toFullString());
705         when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
706     }
707 
verifyUserNotSwitched()708     private void verifyUserNotSwitched() {
709         verify(mCarUserManagerHelper, never()).switchToUserId(anyInt());
710     }
711 
verifyUserSwitched(int userId)712     private void verifyUserSwitched(int userId) {
713         verify(mCarUserManagerHelper, times(1)).switchToUserId(userId);
714     }
715 
verifyNoGuestCreated()716     private void verifyNoGuestCreated() {
717         verify(mUserManager, never()).createGuest(notNull(), anyString());
718     }
719 
expectGuestMarkedForDeletionOk(int userId)720     private void expectGuestMarkedForDeletionOk(int userId) {
721         when(mUserManager.markGuestForDeletion(userId)).thenReturn(true);
722     }
723 
expectGuestMarkedForDeletionFail(int userId)724     private void expectGuestMarkedForDeletionFail(int userId) {
725         when(mUserManager.markGuestForDeletion(userId)).thenReturn(false);
726     }
727 
expectNewGuestCreated(int userId)728     private void expectNewGuestCreated(int userId) {
729         final UserInfo userInfo = new UserInfo();
730         userInfo.id = userId;
731         userInfo.name = NEW_GUEST_NAME;
732         when(mUserManager.createGuest(notNull(), eq(NEW_GUEST_NAME))).thenReturn(userInfo);
733     }
734 
expectNewGuestCreationFailed(String name)735     private void expectNewGuestCreationFailed(String name) {
736         when(mUserManager.createGuest(notNull(), eq(name))).thenReturn(null);
737     }
738 
verifyUserRemoved(int userId)739     private void verifyUserRemoved(int userId) {
740         verify(mUserManager, times(1)).removeUser(userId);
741     }
742 
verifyUserNotRemoved(int userId)743     private void verifyUserNotRemoved(int userId) {
744         verify(mUserManager, never()).removeUser(userId);
745     }
746 
disableUserSwitchingDuringResume()747     private void disableUserSwitchingDuringResume() {
748         mDisableUserSwitchDuringResume = true;
749     }
750 
751     private static final class MockDisplayInterface implements DisplayInterface {
752         private boolean mDisplayOn = true;
753         private final Semaphore mDisplayStateWait = new Semaphore(0);
754 
755         @Override
setDisplayBrightness(int brightness)756         public void setDisplayBrightness(int brightness) {}
757 
758         @Override
setDisplayState(boolean on)759         public synchronized void setDisplayState(boolean on) {
760             mDisplayOn = on;
761             mDisplayStateWait.release();
762         }
763 
getDisplayState()764         public synchronized boolean getDisplayState() {
765             return mDisplayOn;
766         }
767 
waitForDisplayStateChange(long timeoutMs)768         public boolean waitForDisplayStateChange(long timeoutMs) throws Exception {
769             waitForSemaphore(mDisplayStateWait, timeoutMs);
770             return mDisplayOn;
771         }
772 
773         @Override
startDisplayStateMonitoring(CarPowerManagementService service)774         public void startDisplayStateMonitoring(CarPowerManagementService service) {}
775 
776         @Override
stopDisplayStateMonitoring()777         public void stopDisplayStateMonitoring() {}
778 
779         @Override
refreshDisplayBrightness()780         public void refreshDisplayBrightness() {}
781 
782         @Override
reconfigureSecondaryDisplays()783         public void reconfigureSecondaryDisplays() {}
784     }
785 
786     private static final class MockSystemStateInterface implements SystemStateInterface {
787         private final Semaphore mShutdownWait = new Semaphore(0);
788         private final Semaphore mSleepWait = new Semaphore(0);
789         private final Semaphore mSleepExitWait = new Semaphore(0);
790         private boolean mWakeupCausedByTimer = false;
791 
792         @Override
shutdown()793         public void shutdown() {
794             mShutdownWait.release();
795         }
796 
waitForShutdown(long timeoutMs)797         public void waitForShutdown(long timeoutMs) throws Exception {
798             waitForSemaphore(mShutdownWait, timeoutMs);
799         }
800 
801         @Override
enterDeepSleep()802         public boolean enterDeepSleep() {
803             mSleepWait.release();
804             try {
805                 mSleepExitWait.acquire();
806             } catch (InterruptedException e) {
807             }
808             return true;
809         }
810 
waitForSleepEntryAndWakeup(long timeoutMs)811         public void waitForSleepEntryAndWakeup(long timeoutMs) throws Exception {
812             waitForSemaphore(mSleepWait, timeoutMs);
813             mSleepExitWait.release();
814         }
815 
816         @Override
scheduleActionForBootCompleted(Runnable action, Duration delay)817         public void scheduleActionForBootCompleted(Runnable action, Duration delay) {}
818 
819         @Override
isWakeupCausedByTimer()820         public boolean isWakeupCausedByTimer() {
821             Log.i(TAG, "isWakeupCausedByTimer:" + mWakeupCausedByTimer);
822             return mWakeupCausedByTimer;
823         }
824 
setWakeupCausedByTimer(boolean set)825         public synchronized void setWakeupCausedByTimer(boolean set) {
826             mWakeupCausedByTimer = set;
827         }
828 
829         @Override
isSystemSupportingDeepSleep()830         public boolean isSystemSupportingDeepSleep() {
831             return true;
832         }
833     }
834 
835     private static final class MockWakeLockInterface implements WakeLockInterface {
836 
837         @Override
releaseAllWakeLocks()838         public void releaseAllWakeLocks() {}
839 
840         @Override
switchToPartialWakeLock()841         public void switchToPartialWakeLock() {}
842 
843         @Override
switchToFullWakeLock()844         public void switchToFullWakeLock() {}
845     }
846 
847     private static final class MockIOInterface implements IOInterface {
848         private TemporaryDirectory mFilesDir;
849 
850         @Override
getSystemCarDir()851         public File getSystemCarDir() {
852             if (mFilesDir == null) {
853                 try {
854                     mFilesDir = new TemporaryDirectory(TAG);
855                 } catch (IOException e) {
856                     Log.e(TAG, "failed to create temporary directory", e);
857                     fail("failed to create temporary directory. exception was: " + e);
858                 }
859             }
860             return mFilesDir.getDirectory();
861         }
862 
tearDown()863         public void tearDown() {
864             if (mFilesDir != null) {
865                 try {
866                     mFilesDir.close();
867                 } catch (Exception e) {
868                     Log.w(TAG, "could not remove temporary directory", e);
869                 }
870             }
871         }
872     }
873 
874     private class PowerSignalListener implements MockedPowerHalService.SignalListener {
875         private final Semaphore mShutdownWait = new Semaphore(0);
876         private final Semaphore mSleepEntryWait = new Semaphore(0);
877         private final Semaphore mSleepExitWait = new Semaphore(0);
878 
waitForSleepExit(long timeoutMs)879         public void waitForSleepExit(long timeoutMs) throws Exception {
880             waitForSemaphore(mSleepExitWait, timeoutMs);
881         }
882 
waitForShutdown(long timeoutMs)883         public void waitForShutdown(long timeoutMs) throws Exception {
884             waitForSemaphore(mShutdownWait, timeoutMs);
885         }
886 
waitForSleepEntry(long timeoutMs)887         public void waitForSleepEntry(long timeoutMs) throws Exception {
888             waitForSemaphore(mSleepEntryWait, timeoutMs);
889         }
890 
891         @Override
sendingSignal(int signal)892         public void sendingSignal(int signal) {
893             if (signal == PowerHalService.SET_SHUTDOWN_START) {
894                 mShutdownWait.release();
895                 return;
896             }
897             if (signal == PowerHalService.SET_DEEP_SLEEP_ENTRY) {
898                 mSleepEntryWait.release();
899                 return;
900             }
901             if (signal == PowerHalService.SET_DEEP_SLEEP_EXIT) {
902                 mSleepExitWait.release();
903                 return;
904             }
905         }
906     }
907 
908     @Retention(RUNTIME)
909     @Target({METHOD})
910     public static @interface WakeupTime {
value()911         int value();
912     }
913 }
914