1 /* 2 * Copyright (C) 2015 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.car.power; 17 18 import static com.google.common.truth.Truth.assertThat; 19 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.fail; 22 23 import android.car.Car; 24 import android.car.feature.Flags; 25 import android.car.hardware.power.CarPowerManager; 26 import android.car.hardware.power.CarPowerPolicy; 27 import android.car.hardware.power.CarPowerPolicyFilter; 28 import android.car.hardware.power.ICarPowerPolicyListener; 29 import android.car.hardware.power.ICarPowerStateListener; 30 import android.car.hardware.power.PowerComponent; 31 import android.car.hardware.property.VehicleHalStatusCode; 32 import android.car.test.mocks.JavaMockitoHelper; 33 import android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification; 34 import android.hardware.automotive.vehicle.VehicleApPowerStateConfigFlag; 35 import android.hardware.automotive.vehicle.VehicleApPowerStateReport; 36 import android.hardware.automotive.vehicle.VehicleApPowerStateReq; 37 import android.hardware.automotive.vehicle.VehicleApPowerStateReqIndex; 38 import android.hardware.automotive.vehicle.VehicleApPowerStateShutdownParam; 39 import android.hardware.automotive.vehicle.VehiclePropValue; 40 import android.hardware.automotive.vehicle.VehicleProperty; 41 import android.hardware.automotive.vehicle.VehiclePropertyAccess; 42 import android.hardware.automotive.vehicle.VehiclePropertyChangeMode; 43 import android.os.Handler; 44 import android.os.Looper; 45 import android.os.ServiceSpecificException; 46 import android.os.SystemClock; 47 import android.util.SparseBooleanArray; 48 import android.view.Display; 49 50 import androidx.test.ext.junit.runners.AndroidJUnit4; 51 import androidx.test.filters.MediumTest; 52 53 import com.android.car.MockedCarTestBase; 54 import com.android.car.hal.test.AidlMockedVehicleHal.VehicleHalPropertyHandler; 55 import com.android.car.hal.test.AidlVehiclePropValueBuilder; 56 import com.android.car.systeminterface.SystemInterface; 57 import com.android.car.systeminterface.SystemStateInterface; 58 import com.android.car.systeminterface.test.DisplayInterfaceEmptyImpl; 59 import com.android.car.user.CarUserService; 60 import com.android.internal.annotations.GuardedBy; 61 62 import com.google.android.collect.Lists; 63 64 import org.junit.Test; 65 import org.junit.runner.RunWith; 66 import org.mockito.Mockito; 67 68 import java.time.Duration; 69 import java.util.Arrays; 70 import java.util.LinkedList; 71 import java.util.Objects; 72 import java.util.concurrent.CountDownLatch; 73 import java.util.concurrent.Semaphore; 74 import java.util.concurrent.TimeUnit; 75 import java.util.concurrent.atomic.AtomicBoolean; 76 77 @RunWith(AndroidJUnit4.class) 78 @MediumTest 79 public class CarPowerManagementServiceTest extends MockedCarTestBase { 80 81 private static final int STATE_POLLING_INTERVAL_MS = 1; // Milliseconds 82 private static final int STATE_TRANSITION_MAX_WAIT_MS = 5 * STATE_POLLING_INTERVAL_MS; 83 private static final int TEST_SHUTDOWN_TIMEOUT_MS = 100 * STATE_POLLING_INTERVAL_MS; 84 private static final int POLICY_APPLICATION_TIMEOUT_MS = 10_000; 85 private static final String POWER_POLICY_S2R = "system_power_policy_suspend_prep"; 86 87 private final PowerStatePropertyHandler mPowerStateHandler = new PowerStatePropertyHandler(); 88 private final MockDisplayInterface mMockDisplayInterface = new MockDisplayInterface(); 89 private final SystemStateInterfaceForSuspend mMockSystemStateInterface = 90 new SystemStateInterfaceForSuspend(); 91 92 @Override getSystemInterfaceBuilder()93 protected SystemInterface.Builder getSystemInterfaceBuilder() { 94 SystemInterface.Builder builder = super.getSystemInterfaceBuilder(); 95 return builder.withDisplayInterface(mMockDisplayInterface) 96 .withSystemStateInterface(mMockSystemStateInterface); 97 } 98 99 @Override configureMockedHal()100 protected void configureMockedHal() { 101 addAidlProperty(VehicleProperty.AP_POWER_STATE_REQ, mPowerStateHandler) 102 .setConfigArray(Lists.newArrayList( 103 VehicleApPowerStateConfigFlag.ENABLE_DEEP_SLEEP_FLAG 104 | VehicleApPowerStateConfigFlag.ENABLE_HIBERNATION_FLAG)) 105 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE).build(); 106 addAidlProperty(VehicleProperty.AP_POWER_STATE_REPORT, mPowerStateHandler) 107 .setAccess(VehiclePropertyAccess.WRITE) 108 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE).build(); 109 } 110 111 @Override configureResourceOverrides(MockResources resources)112 protected void configureResourceOverrides(MockResources resources) { 113 super.configureResourceOverrides(resources); 114 resources.overrideResource(com.android.car.R.integer.config_maxSuspendWaitDuration, 10000); 115 } 116 117 /********************************************************************************************** 118 * Test immediate shutdown 119 **********************************************************************************************/ 120 @Test testImmediateShutdownFromWaitForVhal()121 public void testImmediateShutdownFromWaitForVhal() throws Exception { 122 assertWaitForVhal(); 123 mPowerStateHandler.sendStateAndCheckResponse( 124 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 125 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY, 126 VehicleApPowerStateReport.SHUTDOWN_START); 127 } 128 129 @Test testImmediateShutdownFromWaitForVhal_ErrorCodeFromVhal()130 public void testImmediateShutdownFromWaitForVhal_ErrorCodeFromVhal() throws Exception { 131 // The exceptions from VHAL should be handled in PowerHalService and not propagated. 132 133 assertWaitForVhal(); 134 135 mPowerStateHandler.setStatus(VehicleHalStatusCode.STATUS_TRY_AGAIN); 136 137 mPowerStateHandler.sendStateAndExpectNoResponse( 138 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 139 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 140 141 mPowerStateHandler.setStatus(VehicleHalStatusCode.STATUS_ACCESS_DENIED); 142 143 mPowerStateHandler.sendStateAndExpectNoResponse( 144 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 145 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 146 147 mPowerStateHandler.setStatus(VehicleHalStatusCode.STATUS_NOT_AVAILABLE); 148 149 mPowerStateHandler.sendStateAndExpectNoResponse( 150 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 151 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 152 153 mPowerStateHandler.setStatus(VehicleHalStatusCode.STATUS_INTERNAL_ERROR); 154 155 mPowerStateHandler.sendStateAndExpectNoResponse( 156 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 157 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 158 159 // Clear status code. 160 mPowerStateHandler.setStatus(VehicleHalStatusCode.STATUS_OK); 161 } 162 163 @Test testImmediateShutdownFromOn()164 public void testImmediateShutdownFromOn() throws Exception { 165 assertWaitForVhal(); 166 // Transition to ON state first 167 mPowerStateHandler.sendStateAndCheckResponse( 168 VehicleApPowerStateReq.ON, 169 /* param= */ 0, 170 VehicleApPowerStateReport.ON); 171 // Send immediate shutdown from ON state 172 mPowerStateHandler.sendStateAndCheckResponse( 173 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 174 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY, 175 VehicleApPowerStateReport.SHUTDOWN_START); 176 } 177 178 @Test testImmediateShutdownFromShutdownPrepare()179 public void testImmediateShutdownFromShutdownPrepare() throws Exception { 180 assertWaitForVhal(); 181 registerListenerToFakeGarageMode(); 182 183 // Put device into SHUTDOWN_PREPARE 184 mPowerStateHandler.sendStateAndCheckResponse( 185 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 186 VehicleApPowerStateShutdownParam.CAN_SLEEP, 187 VehicleApPowerStateReport.SHUTDOWN_PREPARE); 188 // Initiate shutdown immediately while in SHUTDOWN_PREPARE 189 mPowerStateHandler.sendStateAndCheckResponse( 190 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 191 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY, 192 VehicleApPowerStateReport.SHUTDOWN_START); 193 } 194 195 @Test testDeepSleepEntryAfterGarageMode()196 public void testDeepSleepEntryAfterGarageMode() throws Exception { 197 assertWaitForVhal(); 198 199 registerListenerToFakeGarageMode(); 200 201 // Put device into SHUTDOWN_PREPARE 202 mPowerStateHandler.sendStateAndCheckResponse( 203 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 204 VehicleApPowerStateShutdownParam.CAN_SLEEP, 205 VehicleApPowerStateReport.SHUTDOWN_PREPARE); 206 207 mPowerStateHandler.waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS, 208 VehicleApPowerStateReport.DEEP_SLEEP_ENTRY); 209 } 210 211 /********************************************************************************************** 212 * Test cancelling of shutdown. 213 **********************************************************************************************/ 214 @Test testCancelShutdownFromShutdownPrepare()215 public void testCancelShutdownFromShutdownPrepare() throws Exception { 216 assertWaitForVhal(); 217 mPowerStateHandler.sendStateAndCheckResponse( 218 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 219 VehicleApPowerStateShutdownParam.CAN_SLEEP, 220 VehicleApPowerStateReport.SHUTDOWN_PREPARE); 221 // Shutdown may only be cancelled from SHUTDOWN_PREPARE 222 mPowerStateHandler.sendStateAndCheckResponse( 223 VehicleApPowerStateReq.CANCEL_SHUTDOWN, 224 /* param= */ 0, 225 VehicleApPowerStateReport.SHUTDOWN_CANCELLED); 226 } 227 228 @Test testCancelShutdownFromWaitForFinish()229 public void testCancelShutdownFromWaitForFinish() throws Exception { 230 assertWaitForVhal(); 231 mPowerStateHandler.sendStateAndCheckResponse( 232 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 233 VehicleApPowerStateShutdownParam.CAN_SLEEP, 234 VehicleApPowerStateReport.DEEP_SLEEP_ENTRY); 235 // After DEEP_SLEEP_ENTRY, we're in WAIT_FOR_FINISH 236 mPowerStateHandler.sendStateAndCheckResponse( 237 VehicleApPowerStateReq.CANCEL_SHUTDOWN, 238 /* param= */ 0, 239 VehicleApPowerStateReport.SHUTDOWN_CANCELLED); 240 } 241 242 /********************************************************************************************** 243 * Test for invalid state transtions 244 **********************************************************************************************/ 245 @Test testInvalidTransitionsFromWaitForVhal()246 public void testInvalidTransitionsFromWaitForVhal() throws Exception { 247 assertWaitForVhal(); 248 mPowerStateHandler.sendStateAndExpectNoResponse(VehicleApPowerStateReq.CANCEL_SHUTDOWN, 0); 249 mPowerStateHandler.sendStateAndExpectNoResponse(VehicleApPowerStateReq.FINISHED, 0); 250 } 251 252 @Test testInvalidTransitionsFromOn()253 public void testInvalidTransitionsFromOn() throws Exception { 254 assertWaitForVhal(); 255 // Transition to ON state first 256 mPowerStateHandler.sendStateAndCheckResponse( 257 VehicleApPowerStateReq.ON, 258 /* param= */ 0, 259 VehicleApPowerStateReport.ON); 260 mPowerStateHandler.sendStateAndExpectNoResponse(VehicleApPowerStateReq.CANCEL_SHUTDOWN, 0); 261 mPowerStateHandler.sendStateAndExpectNoResponse(VehicleApPowerStateReq.FINISHED, 0); 262 } 263 264 @Test testInvalidTransitionsFromPrepareShutdown()265 public void testInvalidTransitionsFromPrepareShutdown() throws Exception { 266 assertWaitForVhal(); 267 registerListenerToFakeGarageMode(); 268 269 // Transition to SHUTDOWN_PREPARE first 270 mPowerStateHandler.sendStateAndCheckResponse( 271 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 272 VehicleApPowerStateShutdownParam.CAN_SLEEP, 273 VehicleApPowerStateReport.SHUTDOWN_PREPARE); 274 // Cannot go back to ON state from here 275 mPowerStateHandler.sendStateAndExpectNoResponse(VehicleApPowerStateReq.ON, 0); 276 // SHUTDOWN_PREPARE should not generate state transitions unless it's an IMMEDIATE_SHUTDOWN 277 mPowerStateHandler.sendStateAndExpectNoResponse( 278 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 279 VehicleApPowerStateShutdownParam.CAN_SLEEP); 280 mPowerStateHandler.sendStateAndExpectNoResponse( 281 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 282 VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY); 283 // Test the FINISH message last, in case SHUTDOWN_PREPARE finishes early and this test 284 // should be failing. 285 mPowerStateHandler.sendStateAndExpectNoResponse(VehicleApPowerStateReq.FINISHED, 0); 286 } 287 288 @Test testInvalidTransitionsFromWaitForFinish()289 public void testInvalidTransitionsFromWaitForFinish() throws Exception { 290 assertWaitForVhal(); 291 mPowerStateHandler.sendStateAndCheckResponse( 292 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 293 VehicleApPowerStateShutdownParam.CAN_SLEEP, 294 VehicleApPowerStateReport.DEEP_SLEEP_ENTRY); 295 mPowerStateHandler.sendStateAndExpectNoResponse( 296 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 297 VehicleApPowerStateShutdownParam.CAN_SLEEP); 298 mPowerStateHandler.sendStateAndExpectNoResponse( 299 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 300 VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY); 301 // TODO: This state may be allowed in the future, if we decide it's necessary 302 mPowerStateHandler.sendStateAndExpectNoResponse( 303 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 304 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 305 } 306 307 @Test testInvalidTransitionsFromWaitForFinish2()308 public void testInvalidTransitionsFromWaitForFinish2() throws Exception { 309 assertWaitForVhal(); 310 mPowerStateHandler.sendStateAndCheckResponse( 311 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 312 VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY, 313 VehicleApPowerStateReport.SHUTDOWN_START); 314 mPowerStateHandler.sendStateAndExpectNoResponse( 315 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 316 VehicleApPowerStateShutdownParam.CAN_SLEEP); 317 mPowerStateHandler.sendStateAndExpectNoResponse( 318 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 319 VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY); 320 // TODO: This state may be allowed in the future, if we decide it's necessary 321 mPowerStateHandler.sendStateAndExpectNoResponse( 322 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 323 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 324 } 325 326 /********************************************************************************************** 327 * Test sleep entry 328 **********************************************************************************************/ 329 // This test also verifies the display state as the device goes in and out of suspend. 330 @Test testSleepEntry()331 public void testSleepEntry() throws Exception { 332 PowerPolicyListener powerPolicyListener = new PowerPolicyListener(POWER_POLICY_S2R); 333 CarPowerPolicyFilter filter = new CarPowerPolicyFilter.Builder() 334 .setComponents(PowerComponent.WIFI).build(); 335 CarPowerManagementService cpms = getCarPowerManagementService(); 336 cpms.addPowerPolicyListener(filter, powerPolicyListener); 337 338 assertWaitForVhal(); 339 mMockDisplayInterface.waitForAllDisplayState(false); 340 mPowerStateHandler.sendStateAndCheckResponse( 341 VehicleApPowerStateReq.ON, 342 /* param= */ 0, 343 VehicleApPowerStateReport.ON); 344 mMockDisplayInterface.waitForAllDisplayState(true); 345 mPowerStateHandler.sendPowerState( 346 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 347 VehicleApPowerStateShutdownParam.CAN_SLEEP); 348 // The state machine should go to SHUTDOWN_PREPARE, but may 349 // quickly transition to SHUTDOWN_POSTPONE. Report success 350 // if we got to SHUTDOWN_PREPARE, even if we're not there now. 351 assertResponseTransient(VehicleApPowerStateReport.SHUTDOWN_PREPARE, 0, true); 352 353 mMockDisplayInterface.waitForAllDisplayState(false); 354 assertResponse(VehicleApPowerStateReport.DEEP_SLEEP_ENTRY, 0, false); 355 mMockDisplayInterface.waitForAllDisplayState(false); 356 mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.FINISHED, 0); 357 powerPolicyListener.waitForPowerPolicy(); 358 assertResponse(VehicleApPowerStateReport.DEEP_SLEEP_EXIT, 0, true); 359 mMockDisplayInterface.waitForAllDisplayState(false); 360 361 cpms.removePowerPolicyListener(powerPolicyListener); 362 } 363 364 @Test testSleepImmediateEntry()365 public void testSleepImmediateEntry() throws Exception { 366 assertWaitForVhal(); 367 mMockDisplayInterface.waitForAllDisplayState(false); 368 mPowerStateHandler.sendStateAndCheckResponse( 369 VehicleApPowerStateReq.ON, 370 /* param= */ 0, 371 VehicleApPowerStateReport.ON); 372 mMockDisplayInterface.waitForAllDisplayState(true); 373 mPowerStateHandler.sendPowerState( 374 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 375 VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY); 376 assertResponseTransient(VehicleApPowerStateReport.DEEP_SLEEP_ENTRY, 0, true); 377 } 378 379 @Test testInvalidPowerStateEvent()380 public void testInvalidPowerStateEvent() throws Exception { 381 assertWaitForVhal(); 382 383 // No param in the event, should be ignored. 384 getAidlMockedVehicleHal().injectEvent( 385 AidlVehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE_REQ) 386 .setTimestamp(SystemClock.elapsedRealtimeNanos()) 387 .addIntValues(0) 388 .build()); 389 390 assertEquals(mPowerStateHandler.getSetWaitSemaphore().availablePermits(), 0); 391 } 392 393 @Test testUnallowedPowerStateEventAtSuspend()394 public void testUnallowedPowerStateEventAtSuspend() throws Exception { 395 PowerPolicyListener powerPolicyListener = new PowerPolicyListener(POWER_POLICY_S2R); 396 CarPowerPolicyFilter filter = new CarPowerPolicyFilter.Builder() 397 .setComponents(PowerComponent.WIFI).build(); 398 CarPowerManagementService cpms = getCarPowerManagementService(); 399 cpms.addPowerPolicyListener(filter, powerPolicyListener); 400 401 assertWaitForVhal(); 402 403 mPowerStateHandler.sendStateAndCheckResponse( 404 VehicleApPowerStateReq.ON, 405 /* param= */ 0, 406 VehicleApPowerStateReport.ON); 407 mMockDisplayInterface.waitForAllDisplayState(true); 408 // Makes the suspend unsuccessful. 409 mMockSystemStateInterface.setExpectedSuspendStatus( 410 SystemStateInterface.SUSPEND_RESULT_RETRY); 411 mPowerStateHandler.sendPowerState( 412 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 413 VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY); 414 415 assertResponse(VehicleApPowerStateReport.DEEP_SLEEP_ENTRY, /* expectedParam= */ 0, 416 /* checkParam= */ false); 417 418 mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.FINISHED, /* param= */ 0); 419 powerPolicyListener.waitForPowerPolicy(); 420 421 // Sends unallowed power state request. 422 mPowerStateHandler.sendPowerState( 423 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 424 VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY); 425 426 // Makes the suspend successful. 427 mMockSystemStateInterface.setExpectedSuspendStatus( 428 SystemStateInterface.SUSPEND_RESULT_SUCCESS); 429 430 assertResponseTransient(VehicleApPowerStateReport.DEEP_SLEEP_EXIT, /* expectedParam= */ 0, 431 /* checkParam= */ true); 432 433 cpms.removePowerPolicyListener(powerPolicyListener); 434 } 435 436 @Test testShutdownPostponeDuringHibernationEnter()437 public void testShutdownPostponeDuringHibernationEnter() throws Exception { 438 testShutdownPostponeWhileListenerPendingInState(CarPowerManager.STATE_HIBERNATION_ENTER, 439 VehicleApPowerStateShutdownParam.CAN_HIBERNATE, 440 VehicleApPowerStateReport.HIBERNATION_ENTRY); 441 } 442 443 @Test testShutdownPostponeDuringShutdownEnter()444 public void testShutdownPostponeDuringShutdownEnter() throws Exception { 445 testShutdownPostponeWhileListenerPendingInState(CarPowerManager.STATE_SHUTDOWN_ENTER, 446 VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY, 447 VehicleApPowerStateReport.SHUTDOWN_START); 448 } 449 450 @Test testShutdownPostponeDuringSuspendEnter()451 public void testShutdownPostponeDuringSuspendEnter() throws Exception { 452 testShutdownPostponeWhileListenerPendingInState(CarPowerManager.STATE_SUSPEND_ENTER, 453 VehicleApPowerStateShutdownParam.CAN_SLEEP, 454 VehicleApPowerStateReport.DEEP_SLEEP_ENTRY); 455 } 456 457 @Test testShutdownPostponeDuringPreShutdownPrepare()458 public void testShutdownPostponeDuringPreShutdownPrepare() throws Exception { 459 testShutdownPostponeWhileListenerPendingInState(CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE, 460 VehicleApPowerStateShutdownParam.CAN_SLEEP, 461 VehicleApPowerStateReport.DEEP_SLEEP_ENTRY); 462 } 463 464 @Test testShutdownPostponeDuringPreShutdownPrepareWithImmediately()465 public void testShutdownPostponeDuringPreShutdownPrepareWithImmediately() throws Exception { 466 testShutdownPostponeWhileListenerPendingInState(CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE, 467 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY, 468 VehicleApPowerStateReport.SHUTDOWN_START); 469 } 470 471 @Test testSleepShutdownFromPreShutdownPrepare()472 public void testSleepShutdownFromPreShutdownPrepare() throws Exception { 473 assertWaitForVhal(); 474 475 registerListenerToFakeGarageMode(); 476 477 AtomicBoolean errorOccurred = new AtomicBoolean(false); 478 479 // Semaphore to signal receive of PRE_SHUTDOWN_PREPARE 480 Semaphore eventWaitSemaphore = new Semaphore(0); 481 // Semaphore to signal completion of PRE_SHUTDOWN_PREPARE 482 Semaphore completionSemaphore = new Semaphore(0); 483 484 CarPowerManagementService cpms = getCarPowerManagementService(); 485 ICarPowerStateListener listener = new ICarPowerStateListener.Stub() { 486 @Override 487 public void onStateChanged(int state, long expirationTimeMs) { 488 if (!CarPowerManagementService.isCompletionAllowed(state)) { 489 return; 490 } 491 492 Handler handler = new Handler(Looper.getMainLooper()); 493 ICarPowerStateListener cpmsListener = this; 494 Runnable completionRunnable = () -> cpms.completeHandlingPowerStateChange(state, 495 cpmsListener); 496 497 if (state == CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE) { 498 new Thread(() -> { 499 try { 500 eventWaitSemaphore.release(); 501 if (completionSemaphore.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS, 502 TimeUnit.MILLISECONDS)) { 503 handler.post(completionRunnable); 504 } else { 505 errorOccurred.set(true); 506 } 507 } catch (InterruptedException e) { 508 errorOccurred.set(true); 509 } 510 completionSemaphore.drainPermits(); 511 }).start(); 512 } else { 513 cpms.completeHandlingPowerStateChange(state, this); 514 } 515 } 516 }; 517 cpms.registerInternalListener(listener); 518 519 mPowerStateHandler.sendPowerState( 520 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 521 VehicleApPowerStateShutdownParam.CAN_SLEEP); 522 523 assertThat(eventWaitSemaphore.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS, 524 TimeUnit.MILLISECONDS)).isTrue(); 525 526 mPowerStateHandler.sendPowerState( 527 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 528 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 529 530 completionSemaphore.release(); 531 532 mPowerStateHandler.waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS, 533 VehicleApPowerStateReport.SHUTDOWN_START); 534 assertThat(errorOccurred.get()).isFalse(); 535 } 536 537 @Test testShutdownImmediatelyFromPreShutdownPrepare()538 public void testShutdownImmediatelyFromPreShutdownPrepare() throws Exception { 539 assertWaitForVhal(); 540 541 registerListenerToFakeGarageMode(); 542 543 AtomicBoolean errorOccurred = new AtomicBoolean(false); 544 545 // Semaphore to signal receive of PRE_SHUTDOWN_PREPARE 546 Semaphore eventWaitSemaphore = new Semaphore(0); 547 // Semaphore to signal completion of PRE_SHUTDOWN_PREPARE 548 Semaphore completionSemaphore = new Semaphore(0); 549 550 CarPowerManagementService cpms = getCarPowerManagementService(); 551 ICarPowerStateListener listener = new ICarPowerStateListener.Stub() { 552 @Override 553 public void onStateChanged(int state, long expirationTimeMs) { 554 if (!CarPowerManagementService.isCompletionAllowed(state)) { 555 return; 556 } 557 558 ICarPowerStateListener cpmsListener = this; 559 560 if (state == CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE) { 561 new Thread(() -> { 562 try { 563 eventWaitSemaphore.release(); 564 if (completionSemaphore.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS, 565 TimeUnit.MILLISECONDS)) { 566 cpms.completeHandlingPowerStateChange(state, cpmsListener); 567 } else { 568 errorOccurred.set(true); 569 } 570 } catch (InterruptedException e) { 571 errorOccurred.set(true); 572 } 573 completionSemaphore.drainPermits(); 574 }).start(); 575 } else { 576 cpms.completeHandlingPowerStateChange(state, this); 577 } 578 } 579 }; 580 cpms.registerInternalListener(listener); 581 582 mPowerStateHandler.sendPowerState( 583 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 584 VehicleApPowerStateShutdownParam.CAN_SLEEP); 585 586 assertThat(eventWaitSemaphore.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS, 587 TimeUnit.MILLISECONDS)).isTrue(); 588 589 mPowerStateHandler.sendPowerState( 590 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 591 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 592 593 completionSemaphore.release(); 594 595 mPowerStateHandler.waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS, 596 VehicleApPowerStateReport.SHUTDOWN_START); 597 assertThat(errorOccurred.get()).isFalse(); 598 } 599 600 @Test testApplyPowerPolicy_vhalPropertyUpdated()601 public void testApplyPowerPolicy_vhalPropertyUpdated() throws Exception { 602 String policyIdWifiOff = "policy_id_wifi_off"; 603 String policyIdWifiOn = "policy_id_wifi_on"; 604 // This is how the other test cases in this file interact w/CPMS, but would it make sense 605 // to just define mService = (CarPowerManagementService) getCarService(Car.POWER_SERVICE)? 606 CarPowerManagementService cpms = getCarPowerManagementService(); 607 cpms.definePowerPolicy(policyIdWifiOff, new String[]{}, new String[]{"WIFI"}); 608 cpms.definePowerPolicy(policyIdWifiOn, new String[]{"WIFI"}, new String[]{}); 609 PowerPolicyListener wifiOffListener = new PowerPolicyListener(policyIdWifiOff); 610 PowerPolicyListener wifiOnListener = new PowerPolicyListener(policyIdWifiOn); 611 CarPowerPolicyFilter filterWifi = new CarPowerPolicyFilter.Builder() 612 .setComponents(PowerComponent.WIFI).build(); 613 cpms.addPowerPolicyListener(filterWifi, wifiOffListener); 614 cpms.addPowerPolicyListener(filterWifi, wifiOnListener); 615 616 cpms.applyPowerPolicy(policyIdWifiOn); 617 wifiOnListener.waitForPowerPolicy(); 618 cpms.applyPowerPolicy(policyIdWifiOff); 619 wifiOffListener.waitForPowerPolicy(); 620 621 if (!Flags.carPowerPolicyRefactoring()) { 622 Mockito.verify((ICarPowerPolicySystemNotification) getMockedPowerManagementDaemon()) 623 .notifyPowerPolicyChange(policyIdWifiOff, /* force= */ false); 624 } 625 } 626 testShutdownPostponeWhileListenerPendingInState(final int targetState, int stateRequestParam, int finalPowerState)627 private void testShutdownPostponeWhileListenerPendingInState(final int targetState, 628 int stateRequestParam, int finalPowerState) throws Exception { 629 assertWaitForVhal(); 630 631 Semaphore notificationSem = new Semaphore(0); 632 633 AtomicBoolean errorOccurred = new AtomicBoolean(false); 634 CarPowerManagementService cpms = getCarPowerManagementService(); 635 636 ICarPowerStateListener listener = new ICarPowerStateListener.Stub() { 637 @Override 638 public void onStateChanged(int state, long expirationTimeMs) { 639 if (!CarPowerManagementService.isCompletionAllowed(state)) { 640 return; 641 } 642 643 ICarPowerStateListener cpmsListener = this; 644 if (state == targetState) { 645 new Thread(() -> { 646 try { 647 if (!notificationSem.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS, 648 TimeUnit.MILLISECONDS)) { 649 errorOccurred.set(true); 650 } 651 cpms.completeHandlingPowerStateChange(state, cpmsListener); 652 } catch (InterruptedException e) { 653 errorOccurred.set(true); 654 } 655 }).start(); 656 } else { 657 cpms.completeHandlingPowerStateChange(state, this); 658 } 659 } 660 }; 661 cpms.registerInternalListener(listener); 662 663 //start shutown prepare 664 mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, 665 stateRequestParam); 666 // wait for SHUTDOWN_POSTPONE 667 mPowerStateHandler.waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS, 668 VehicleApPowerStateReport.SHUTDOWN_POSTPONE); 669 // complete listener 670 notificationSem.release(); 671 672 mPowerStateHandler.waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS, finalPowerState); 673 assertThat(errorOccurred.get()).isFalse(); 674 } 675 676 // Check that 'expectedState' was reached and is the current state. assertResponse(int expectedState, int expectedParam, boolean checkParam)677 private void assertResponse(int expectedState, int expectedParam, boolean checkParam) 678 throws Exception { 679 LinkedList<int[]> setEvents = mPowerStateHandler.waitForStateSetAndGetAll( 680 DEFAULT_WAIT_TIMEOUT_MS, expectedState); 681 int[] last = setEvents.getLast(); 682 assertEquals(expectedState, last[0]); 683 if (checkParam) { 684 assertEquals(expectedParam, last[1]); 685 } 686 } 687 688 // Check that 'expectedState' was reached. (But it's OK if it is not still current.) assertResponseTransient(int expectedState, int expectedParam, boolean checkParam)689 private void assertResponseTransient(int expectedState, int expectedParam, boolean checkParam) 690 throws Exception { 691 LinkedList<int[]> setEvents = mPowerStateHandler.waitForStateSetAndGetAll( 692 DEFAULT_WAIT_TIMEOUT_MS, expectedState); 693 for (int[] aState : setEvents) { 694 if (expectedState != aState[0]) continue; 695 if (checkParam) { 696 assertEquals(expectedParam, aState[1]); 697 } 698 return; // Success 699 } 700 fail("Did not find expected state: " + expectedState); 701 } 702 assertWaitForVhal()703 private void assertWaitForVhal() throws Exception { 704 mPowerStateHandler.waitForSubscription(DEFAULT_WAIT_TIMEOUT_MS); 705 LinkedList<int[]> setEvents = mPowerStateHandler.waitForStateSetAndGetAll( 706 DEFAULT_WAIT_TIMEOUT_MS, VehicleApPowerStateReport.WAIT_FOR_VHAL); 707 int[] first = setEvents.getFirst(); 708 assertEquals(VehicleApPowerStateReport.WAIT_FOR_VHAL, first[0]); 709 assertEquals(0, first[1]); 710 } 711 registerListenerToFakeGarageMode()712 private void registerListenerToFakeGarageMode() { 713 CarPowerManagementService cpms = getCarPowerManagementService(); 714 ICarPowerStateListener listener = new ICarPowerStateListener.Stub() { 715 @Override 716 public void onStateChanged(int state, long expirationTimeMs) { 717 if (CarPowerManagementService.isCompletionAllowed(state)) { 718 // Do not call finished() to stay in shutdown prepare, when Garage Mode is 719 // supposed to be running. 720 if (state == CarPowerManager.STATE_SHUTDOWN_PREPARE 721 && !cpms.garageModeShouldExitImmediately()) { 722 return; 723 } 724 cpms.completeHandlingPowerStateChange(state, this); 725 } 726 } 727 }; 728 cpms.registerInternalListener(listener); 729 } 730 getCarPowerManagementService()731 private CarPowerManagementService getCarPowerManagementService() { 732 CarPowerManagementService cpms = 733 (CarPowerManagementService) getCarService(Car.POWER_SERVICE); 734 if (Flags.carPowerPolicyRefactoring()) { 735 cpms.initializePowerPolicy(); 736 } 737 return cpms; 738 } 739 740 private static final class MockDisplayInterface extends DisplayInterfaceEmptyImpl { 741 private final Object mLock = new Object(); 742 @GuardedBy("mLock") 743 private final SparseBooleanArray mDisplayOn = new SparseBooleanArray(); 744 private final Semaphore mDisplayStateWait = new Semaphore(0); 745 private CarPowerManagementService mCarPowerManagementService; 746 747 @Override init(CarPowerManagementService carPowerManagementService, CarUserService carUserService)748 public void init(CarPowerManagementService carPowerManagementService, 749 CarUserService carUserService) { 750 mCarPowerManagementService = carPowerManagementService; 751 synchronized (mLock) { 752 mDisplayOn.put(Display.DEFAULT_DISPLAY, true); 753 } 754 } 755 756 @Override setDisplayState(int displayId, boolean on)757 public void setDisplayState(int displayId, boolean on) { 758 synchronized (mLock) { 759 mDisplayOn.put(displayId, on); 760 } 761 mDisplayStateWait.release(); 762 } 763 764 @Override setAllDisplayState(boolean on)765 public void setAllDisplayState(boolean on) { 766 synchronized (mLock) { 767 for (int i = 0; i < mDisplayOn.size(); i++) { 768 int displayId = mDisplayOn.keyAt(i); 769 setDisplayState(displayId, on); 770 } 771 } 772 } 773 waitForDisplayState(int displayId, boolean expectedState)774 boolean waitForDisplayState(int displayId, boolean expectedState) throws Exception { 775 boolean enabled = false; 776 synchronized (mLock) { 777 enabled = mDisplayOn.get(displayId); 778 } 779 if (expectedState == enabled) { 780 return true; 781 } 782 mDisplayStateWait.tryAcquire(MockedCarTestBase.SHORT_WAIT_TIMEOUT_MS, 783 TimeUnit.MILLISECONDS); 784 return expectedState == enabled; 785 } 786 waitForAllDisplayState(boolean expectedState)787 void waitForAllDisplayState(boolean expectedState) throws Exception { 788 SparseBooleanArray displayOn; 789 synchronized (mLock) { 790 displayOn = mDisplayOn.clone(); 791 } 792 for (int i = 0; i < displayOn.size(); i++) { 793 int displayId = displayOn.keyAt(i); 794 waitForDisplayState(displayId, expectedState); 795 } 796 } 797 798 @Override startDisplayStateMonitoring()799 public void startDisplayStateMonitoring() { 800 // To reduce test duration, decrease the polling interval and the 801 // time to wait for a shutdown 802 mCarPowerManagementService.setShutdownTimersForTest(STATE_POLLING_INTERVAL_MS, 803 TEST_SHUTDOWN_TIMEOUT_MS); 804 } 805 806 @Override stopDisplayStateMonitoring()807 public void stopDisplayStateMonitoring() {} 808 809 @Override refreshDefaultDisplayBrightness()810 public void refreshDefaultDisplayBrightness() {} 811 812 @Override refreshDisplayBrightness(int displayId)813 public void refreshDisplayBrightness(int displayId) {} 814 815 @Override isAnyDisplayEnabled()816 public boolean isAnyDisplayEnabled() { 817 synchronized (mLock) { 818 for (int i = 0; i < mDisplayOn.size(); i++) { 819 int displayId = mDisplayOn.keyAt(i); 820 if (isDisplayEnabled(displayId)) { 821 return true; 822 } 823 } 824 } 825 return false; 826 } 827 828 @Override isDisplayEnabled(int displayId)829 public boolean isDisplayEnabled(int displayId) { 830 synchronized (mLock) { 831 return mDisplayOn.get(displayId); 832 } 833 } 834 } 835 836 private class PowerStatePropertyHandler implements VehicleHalPropertyHandler { 837 838 private int mPowerState = VehicleApPowerStateReq.ON; 839 private int mPowerParam = 0; 840 private int mStatus = VehicleHalStatusCode.STATUS_OK; 841 842 private final Semaphore mSubscriptionWaitSemaphore = new Semaphore(0); 843 private final Semaphore mSetWaitSemaphore = new Semaphore(0); 844 private final LinkedList<int[]> mSetStates = new LinkedList<>(); 845 getSetWaitSemaphore()846 public Semaphore getSetWaitSemaphore() { 847 return mSetWaitSemaphore; 848 } 849 setStatus(int status)850 public void setStatus(int status) { 851 mStatus = status; 852 } 853 854 @Override onPropertySet(VehiclePropValue value)855 public void onPropertySet(VehiclePropValue value) { 856 if (mStatus != VehicleHalStatusCode.STATUS_OK) { 857 throw new ServiceSpecificException(mStatus); 858 } 859 int[] v = value.value.int32Values; 860 synchronized (this) { 861 mSetStates.add(new int[] { 862 v[VehicleApPowerStateReqIndex.STATE], 863 v[VehicleApPowerStateReqIndex.ADDITIONAL] 864 }); 865 } 866 mSetWaitSemaphore.release(); 867 } 868 869 @Override onPropertyGet(VehiclePropValue value)870 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) { 871 if (mStatus != VehicleHalStatusCode.STATUS_OK) { 872 throw new ServiceSpecificException(mStatus); 873 } 874 return AidlVehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE_REQ) 875 .setTimestamp(SystemClock.elapsedRealtimeNanos()) 876 .addIntValues(mPowerState, mPowerParam) 877 .build(); 878 } 879 880 @Override onPropertySubscribe(int property, float sampleRate)881 public void onPropertySubscribe(int property, float sampleRate) { 882 mSubscriptionWaitSemaphore.release(); 883 } 884 885 @Override onPropertyUnsubscribe(int property)886 public void onPropertyUnsubscribe(int property) { 887 //ignore 888 } 889 waitForSubscription(long timeoutMs)890 private void waitForSubscription(long timeoutMs) throws Exception { 891 if (!mSubscriptionWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 892 fail("waitForSubscription timeout"); 893 } 894 } 895 waitForStateSetAndGetAll(long timeoutMs, int expectedState)896 private LinkedList<int[]> waitForStateSetAndGetAll(long timeoutMs, int expectedState) 897 throws Exception { 898 while (true) { 899 if (!mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 900 fail("waitForStateSetAndGetAll timeout"); 901 } 902 LinkedList<int[]> result = new LinkedList<>(); 903 synchronized (this) { 904 boolean found = false; 905 906 while (!mSetStates.isEmpty()) { 907 int[] state = mSetStates.pop(); 908 result.add(state); 909 if (state[0] == expectedState) { 910 found = true; 911 break; 912 } 913 } 914 if (found) { 915 // update semaphore to actual number of events in the list 916 mSetWaitSemaphore.drainPermits(); 917 mSetWaitSemaphore.release(mSetStates.size()); 918 return result; 919 } 920 } 921 } 922 } 923 sendStateAndCheckResponse(int state, int param, int expectedState)924 private void sendStateAndCheckResponse(int state, int param, int expectedState) 925 throws Exception { 926 sendPowerState(state, param); 927 waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS, expectedState); 928 } 929 930 /** 931 * Checks that a power state transition does NOT occur. If any state does occur during 932 * the timeout period (other than a POSTPONE), then the test fails. 933 */ sendStateAndExpectNoResponse(int state, int param)934 private void sendStateAndExpectNoResponse(int state, int param) throws Exception { 935 sendPowerState(state, param); 936 // Wait to see if a state transition occurs 937 long startTime = SystemClock.elapsedRealtime(); 938 while (true) { 939 long timeWaitingMs = SystemClock.elapsedRealtime() - startTime; 940 if (timeWaitingMs > STATE_TRANSITION_MAX_WAIT_MS) { 941 // No meaningful state transition: this is a success! 942 return; 943 } 944 if (!mSetWaitSemaphore.tryAcquire(STATE_TRANSITION_MAX_WAIT_MS, 945 TimeUnit.MILLISECONDS)) { 946 // No state transition, this is a success! 947 return; 948 } 949 synchronized (this) { 950 while (!mSetStates.isEmpty()) { 951 int[] newState = mSetStates.pop(); 952 if (newState[0] != VehicleApPowerStateReport.SHUTDOWN_POSTPONE) { 953 fail("Unexpected state change occurred, state=" 954 + Arrays.toString(newState)); 955 } 956 } 957 mSetWaitSemaphore.drainPermits(); 958 } 959 } 960 } 961 sendPowerState(int state, int param)962 private void sendPowerState(int state, int param) { 963 getAidlMockedVehicleHal().injectEvent( 964 AidlVehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE_REQ) 965 .setTimestamp(SystemClock.elapsedRealtimeNanos()) 966 .addIntValues(state, param) 967 .build()); 968 } 969 } 970 971 private static final class PowerPolicyListener extends ICarPowerPolicyListener.Stub { 972 private final CountDownLatch mLatch = new CountDownLatch(1); 973 private final String mWaitingPolicyId; 974 PowerPolicyListener(String policyId)975 private PowerPolicyListener(String policyId) { 976 mWaitingPolicyId = policyId; 977 } 978 979 @Override onPolicyChanged(CarPowerPolicy appliedPolicy, CarPowerPolicy accumulatedPolicy)980 public void onPolicyChanged(CarPowerPolicy appliedPolicy, 981 CarPowerPolicy accumulatedPolicy) { 982 if (Objects.equals(appliedPolicy.getPolicyId(), mWaitingPolicyId)) { 983 mLatch.countDown(); 984 } 985 } 986 waitForPowerPolicy()987 public void waitForPowerPolicy() throws Exception { 988 JavaMockitoHelper.await(mLatch, POLICY_APPLICATION_TIMEOUT_MS); 989 } 990 } 991 992 private static final class SystemStateInterfaceForSuspend implements SystemStateInterface { 993 994 private final Object mLock = new Object(); 995 996 @GuardedBy("mLock") 997 private int mExpectedSuspendStatus = SUSPEND_RESULT_SUCCESS; 998 999 @Override shutdown()1000 public void shutdown() {} 1001 1002 @Override enterDeepSleep()1003 public int enterDeepSleep() { 1004 synchronized (mLock) { 1005 return mExpectedSuspendStatus; 1006 } 1007 } 1008 1009 @Override enterHibernation()1010 public int enterHibernation() { 1011 synchronized (mLock) { 1012 return mExpectedSuspendStatus; 1013 } 1014 } 1015 1016 @Override scheduleActionForBootCompleted(Runnable action, Duration delay, Duration delayRange)1017 public void scheduleActionForBootCompleted(Runnable action, Duration delay, 1018 Duration delayRange) {} 1019 setExpectedSuspendStatus(int expectedStatus)1020 public void setExpectedSuspendStatus(int expectedStatus) { 1021 synchronized (mLock) { 1022 mExpectedSuspendStatus = expectedStatus; 1023 } 1024 } 1025 } 1026 } 1027