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