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; 17 18 import android.annotation.NonNull; 19 import android.annotation.UserIdInt; 20 import android.app.ActivityManager; 21 import android.car.Car; 22 import android.car.hardware.power.CarPowerManager.CarPowerStateListener; 23 import android.car.hardware.power.ICarPower; 24 import android.car.hardware.power.ICarPowerStateListener; 25 import android.car.userlib.HalCallback; 26 import android.car.userlib.InitialUserSetter; 27 import android.car.userlib.InitialUserSetter.InitialUserInfoType; 28 import android.car.userlib.UserHalHelper; 29 import android.car.userlib.UserHelper; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.pm.UserInfo; 34 import android.content.res.Resources; 35 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType; 36 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction; 37 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq; 38 import android.os.Build; 39 import android.os.Handler; 40 import android.os.HandlerThread; 41 import android.os.IBinder; 42 import android.os.Looper; 43 import android.os.Message; 44 import android.os.PowerManager; 45 import android.os.RemoteCallbackList; 46 import android.os.RemoteException; 47 import android.os.ServiceManager; 48 import android.os.SystemClock; 49 import android.os.SystemProperties; 50 import android.os.UserHandle; 51 import android.os.UserManager; 52 import android.sysprop.CarProperties; 53 import android.util.Log; 54 55 import com.android.car.am.ContinuousBlankActivity; 56 import com.android.car.hal.PowerHalService; 57 import com.android.car.hal.PowerHalService.PowerState; 58 import com.android.car.systeminterface.SystemInterface; 59 import com.android.car.user.CarUserNoticeService; 60 import com.android.car.user.CarUserService; 61 import com.android.internal.annotations.GuardedBy; 62 import com.android.internal.annotations.VisibleForTesting; 63 import com.android.internal.app.IVoiceInteractionManagerService; 64 65 import java.io.PrintWriter; 66 import java.lang.ref.WeakReference; 67 import java.util.HashSet; 68 import java.util.LinkedList; 69 import java.util.Set; 70 import java.util.Timer; 71 import java.util.TimerTask; 72 73 /** 74 * Power Management service class for cars. Controls the power states and interacts with other 75 * parts of the system to ensure its own state. 76 */ 77 public class CarPowerManagementService extends ICarPower.Stub implements 78 CarServiceBase, PowerHalService.PowerEventListener { 79 80 // TODO: replace all usage 81 private static final String TAG = CarLog.TAG_POWER; 82 83 private final Object mLock = new Object(); 84 private final Object mSimulationWaitObject = new Object(); 85 86 private final Context mContext; 87 private final PowerHalService mHal; 88 private final SystemInterface mSystemInterface; 89 // The listeners that complete simply by returning from onStateChanged() 90 private final PowerManagerCallbackList mPowerManagerListeners = new PowerManagerCallbackList(); 91 // The listeners that must indicate asynchronous completion by calling finished(). 92 private final PowerManagerCallbackList mPowerManagerListenersWithCompletion = 93 new PowerManagerCallbackList(); 94 95 @GuardedBy("mSimulationWaitObject") 96 private boolean mWakeFromSimulatedSleep; 97 @GuardedBy("mSimulationWaitObject") 98 private boolean mInSimulatedDeepSleepMode; 99 100 @GuardedBy("mLock") 101 private final Set<IBinder> mListenersWeAreWaitingFor = new HashSet<>(); 102 @GuardedBy("mLock") 103 private CpmsState mCurrentState; 104 @GuardedBy("mLock") 105 private Timer mTimer; 106 @GuardedBy("mLock") 107 private long mProcessingStartTime; 108 @GuardedBy("mLock") 109 private long mLastSleepEntryTime; 110 @GuardedBy("mLock") 111 private final LinkedList<CpmsState> mPendingPowerStates = new LinkedList<>(); 112 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread( 113 getClass().getSimpleName()); 114 private final PowerHandler mHandler = new PowerHandler(mHandlerThread.getLooper(), this); 115 116 @GuardedBy("mLock") 117 private boolean mTimerActive; 118 @GuardedBy("mLock") 119 private int mNextWakeupSec; 120 @GuardedBy("mLock") 121 private boolean mShutdownOnFinish; 122 @GuardedBy("mLock") 123 private boolean mShutdownOnNextSuspend; 124 @GuardedBy("mLock") 125 private boolean mIsBooting = true; 126 @GuardedBy("mLock") 127 private boolean mIsResuming; 128 @GuardedBy("mLock") 129 private int mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS; 130 @GuardedBy("mLock") 131 private int mShutdownPollingIntervalMs = SHUTDOWN_POLLING_INTERVAL_MS; 132 @GuardedBy("mLock") 133 private boolean mRebootAfterGarageMode; 134 @GuardedBy("mLock") 135 private boolean mGarageModeShouldExitImmediately; 136 private final boolean mDisableUserSwitchDuringResume; 137 138 private final UserManager mUserManager; 139 private final CarUserService mUserService; 140 private final InitialUserSetter mInitialUserSetter; 141 142 private final IVoiceInteractionManagerService mVoiceInteractionManagerService; 143 144 // TODO: Make this OEM configurable. 145 private static final int SHUTDOWN_POLLING_INTERVAL_MS = 2000; 146 private static final int SHUTDOWN_EXTEND_MAX_MS = 5000; 147 148 // maxGarageModeRunningDurationInSecs should be equal or greater than this. 15 min for now. 149 private static final int MIN_MAX_GARAGE_MODE_DURATION_MS = 15 * 60 * 1000; 150 151 // in secs 152 private static final String PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE = 153 "android.car.garagemodeduration"; 154 155 // This is a temp work-around to reduce user switching delay after wake-up. 156 private final boolean mSwitchGuestUserBeforeSleep; 157 158 private class PowerManagerCallbackList extends RemoteCallbackList<ICarPowerStateListener> { 159 /** 160 * Old version of {@link #onCallbackDied(E, Object)} that 161 * does not provide a cookie. 162 */ 163 @Override onCallbackDied(ICarPowerStateListener listener)164 public void onCallbackDied(ICarPowerStateListener listener) { 165 Log.i(CarLog.TAG_POWER, "binderDied " + listener.asBinder()); 166 CarPowerManagementService.this.doUnregisterListener(listener); 167 } 168 } 169 CarPowerManagementService(Context context, PowerHalService powerHal, SystemInterface systemInterface, CarUserService carUserService)170 public CarPowerManagementService(Context context, PowerHalService powerHal, 171 SystemInterface systemInterface, CarUserService carUserService) { 172 this(context, context.getResources(), powerHal, systemInterface, UserManager.get(context), 173 carUserService, new InitialUserSetter(context, 174 (u) -> carUserService.setInitialUser(u), 175 context.getString(R.string.default_guest_name)), 176 IVoiceInteractionManagerService.Stub.asInterface( 177 ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE))); 178 } 179 180 @VisibleForTesting CarPowerManagementService(Context context, Resources resources, PowerHalService powerHal, SystemInterface systemInterface, UserManager userManager, CarUserService carUserService, InitialUserSetter initialUserSetter, IVoiceInteractionManagerService voiceInteractionService)181 public CarPowerManagementService(Context context, Resources resources, PowerHalService powerHal, 182 SystemInterface systemInterface, UserManager userManager, CarUserService carUserService, 183 InitialUserSetter initialUserSetter, 184 IVoiceInteractionManagerService voiceInteractionService) { 185 mContext = context; 186 mHal = powerHal; 187 mSystemInterface = systemInterface; 188 mUserManager = userManager; 189 mDisableUserSwitchDuringResume = resources 190 .getBoolean(R.bool.config_disableUserSwitchDuringResume); 191 mShutdownPrepareTimeMs = resources.getInteger( 192 R.integer.maxGarageModeRunningDurationInSecs) * 1000; 193 mSwitchGuestUserBeforeSleep = resources.getBoolean( 194 R.bool.config_switchGuestUserBeforeGoingSleep); 195 if (mShutdownPrepareTimeMs < MIN_MAX_GARAGE_MODE_DURATION_MS) { 196 Log.w(CarLog.TAG_POWER, 197 "maxGarageModeRunningDurationInSecs smaller than minimum required, resource:" 198 + mShutdownPrepareTimeMs + "(ms) while should exceed:" 199 + MIN_MAX_GARAGE_MODE_DURATION_MS + "(ms), Ignore resource."); 200 mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS; 201 } 202 mUserService = carUserService; 203 mInitialUserSetter = initialUserSetter; 204 mVoiceInteractionManagerService = voiceInteractionService; 205 } 206 207 @VisibleForTesting setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs)208 public void setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs) { 209 // Override timers to keep testing time short 210 // Passing in '0' resets the value to the default 211 synchronized (mLock) { 212 mShutdownPollingIntervalMs = 213 (pollingIntervalMs == 0) ? SHUTDOWN_POLLING_INTERVAL_MS : pollingIntervalMs; 214 mShutdownPrepareTimeMs = 215 (shutdownTimeoutMs == 0) ? SHUTDOWN_EXTEND_MAX_MS : shutdownTimeoutMs; 216 } 217 } 218 219 @VisibleForTesting getHandlerThread()220 protected HandlerThread getHandlerThread() { 221 return mHandlerThread; 222 } 223 224 @Override init()225 public void init() { 226 mHal.setListener(this); 227 if (mHal.isPowerStateSupported()) { 228 // Initialize CPMS in WAIT_FOR_VHAL state 229 onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, CarPowerStateListener.WAIT_FOR_VHAL); 230 } else { 231 Log.w(CarLog.TAG_POWER, "Vehicle hal does not support power state yet."); 232 onApPowerStateChange(CpmsState.ON, CarPowerStateListener.ON); 233 } 234 mSystemInterface.startDisplayStateMonitoring(this); 235 } 236 237 @Override release()238 public void release() { 239 synchronized (mLock) { 240 releaseTimerLocked(); 241 mCurrentState = null; 242 mHandler.cancelAll(); 243 mListenersWeAreWaitingFor.clear(); 244 } 245 mSystemInterface.stopDisplayStateMonitoring(); 246 mPowerManagerListeners.kill(); 247 mSystemInterface.releaseAllWakeLocks(); 248 } 249 250 @Override dump(PrintWriter writer)251 public void dump(PrintWriter writer) { 252 synchronized (mLock) { 253 writer.println("*PowerManagementService*"); 254 // TODO: split it in multiple lines 255 // TODO: lock only what's needed 256 writer.print("mCurrentState:" + mCurrentState); 257 writer.print(",mProcessingStartTime:" + mProcessingStartTime); 258 writer.print(",mLastSleepEntryTime:" + mLastSleepEntryTime); 259 writer.print(",mNextWakeupSec:" + mNextWakeupSec); 260 writer.print(",mShutdownOnNextSuspend:" + mShutdownOnNextSuspend); 261 writer.print(",mShutdownOnFinish:" + mShutdownOnFinish); 262 writer.print(",mShutdownPollingIntervalMs:" + mShutdownPollingIntervalMs); 263 writer.print(",mShutdownPrepareTimeMs:" + mShutdownPrepareTimeMs); 264 writer.print(",mDisableUserSwitchDuringResume:" + mDisableUserSwitchDuringResume); 265 writer.println(",mRebootAfterGarageMode:" + mRebootAfterGarageMode); 266 writer.println("mSwitchGuestUserBeforeSleep:" + mSwitchGuestUserBeforeSleep); 267 } 268 mInitialUserSetter.dump(writer); 269 } 270 271 @Override onApPowerStateChange(PowerState state)272 public void onApPowerStateChange(PowerState state) { 273 synchronized (mLock) { 274 mPendingPowerStates.addFirst(new CpmsState(state)); 275 } 276 mHandler.handlePowerStateChange(); 277 } 278 279 @VisibleForTesting setStateForTesting(boolean isBooting, boolean isResuming)280 void setStateForTesting(boolean isBooting, boolean isResuming) { 281 synchronized (mLock) { 282 Log.d(CarLog.TAG_POWER, "setStateForTesting():" 283 + " booting(" + mIsBooting + ">" + isBooting + ")" 284 + " resuming(" + mIsResuming + ">" + isResuming + ")"); 285 mIsBooting = isBooting; 286 mIsResuming = isResuming; 287 } 288 } 289 290 /** 291 * Initiate state change from CPMS directly. 292 */ onApPowerStateChange(int apState, int carPowerStateListenerState)293 private void onApPowerStateChange(int apState, int carPowerStateListenerState) { 294 CpmsState newState = new CpmsState(apState, carPowerStateListenerState); 295 synchronized (mLock) { 296 mPendingPowerStates.addFirst(newState); 297 } 298 mHandler.handlePowerStateChange(); 299 } 300 doHandlePowerStateChange()301 private void doHandlePowerStateChange() { 302 CpmsState state; 303 synchronized (mLock) { 304 state = mPendingPowerStates.peekFirst(); 305 mPendingPowerStates.clear(); 306 if (state == null) { 307 Log.e(CarLog.TAG_POWER, "Null power state was requested"); 308 return; 309 } 310 Log.i(CarLog.TAG_POWER, "doHandlePowerStateChange: newState=" + state.name()); 311 if (!needPowerStateChangeLocked(state)) { 312 return; 313 } 314 // now real power change happens. Whatever was queued before should be all cancelled. 315 releaseTimerLocked(); 316 } 317 mHandler.cancelProcessingComplete(); 318 Log.i(CarLog.TAG_POWER, "setCurrentState " + state.toString()); 319 CarStatsLogHelper.logPowerState(state.mState); 320 mCurrentState = state; 321 switch (state.mState) { 322 case CpmsState.WAIT_FOR_VHAL: 323 handleWaitForVhal(state); 324 break; 325 case CpmsState.ON: 326 handleOn(); 327 break; 328 case CpmsState.SHUTDOWN_PREPARE: 329 handleShutdownPrepare(state); 330 break; 331 case CpmsState.SIMULATE_SLEEP: 332 simulateShutdownPrepare(); 333 break; 334 case CpmsState.WAIT_FOR_FINISH: 335 handleWaitForFinish(state); 336 break; 337 case CpmsState.SUSPEND: 338 // Received FINISH from VHAL 339 handleFinish(); 340 break; 341 default: 342 // Illegal state 343 // TODO: Throw exception? 344 break; 345 } 346 } 347 handleWaitForVhal(CpmsState state)348 private void handleWaitForVhal(CpmsState state) { 349 int carPowerStateListenerState = state.mCarPowerStateListenerState; 350 sendPowerManagerEvent(carPowerStateListenerState); 351 // Inspect CarPowerStateListenerState to decide which message to send via VHAL 352 switch (carPowerStateListenerState) { 353 case CarPowerStateListener.WAIT_FOR_VHAL: 354 mHal.sendWaitForVhal(); 355 break; 356 case CarPowerStateListener.SHUTDOWN_CANCELLED: 357 mShutdownOnNextSuspend = false; // This cancels the "NextSuspend" 358 mHal.sendShutdownCancel(); 359 break; 360 case CarPowerStateListener.SUSPEND_EXIT: 361 mHal.sendSleepExit(); 362 break; 363 } 364 } 365 updateCarUserNoticeServiceIfNecessary()366 private void updateCarUserNoticeServiceIfNecessary() { 367 try { 368 int currentUserId = ActivityManager.getCurrentUser(); 369 UserInfo currentUserInfo = mUserManager.getUserInfo(currentUserId); 370 CarUserNoticeService carUserNoticeService = 371 CarLocalServices.getService(CarUserNoticeService.class); 372 if (currentUserInfo != null && currentUserInfo.isGuest() 373 && carUserNoticeService != null) { 374 Log.i(CarLog.TAG_POWER, 375 "Car user notice service will ignore all messages before user switch."); 376 Intent intent = new Intent(); 377 intent.setComponent(new ComponentName(mContext.getPackageName(), 378 ContinuousBlankActivity.class.getName())); 379 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 380 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 381 carUserNoticeService.ignoreUserNotice(currentUserId); 382 } 383 } catch (Exception e) { 384 Log.w(CarLog.TAG_POWER, "Cannot ignore user notice for current user", e); 385 } 386 } 387 handleOn()388 private void handleOn() { 389 // If current user is a Guest User, we want to inform CarUserNoticeService not to show 390 // notice for current user, and show user notice only for the target user. 391 if (!mSwitchGuestUserBeforeSleep) { 392 updateCarUserNoticeServiceIfNecessary(); 393 } 394 395 // Some OEMs have their own user-switching logic, which may not be coordinated with this 396 // code. To avoid contention, we don't switch users when we coming alive. The OEM's code 397 // should do the switch. 398 boolean allowUserSwitch = true; 399 synchronized (mLock) { 400 if (mIsBooting) { 401 // The system is booting, so don't switch users 402 allowUserSwitch = false; 403 mIsBooting = false; 404 mIsResuming = false; 405 Log.i(CarLog.TAG_POWER, "User switch disallowed while booting"); 406 } else { 407 // The system is resuming after a suspension. Optionally disable user switching. 408 allowUserSwitch = !mDisableUserSwitchDuringResume; 409 mIsBooting = false; 410 mIsResuming = false; 411 if (!allowUserSwitch) { 412 Log.i(CarLog.TAG_POWER, "User switch disallowed while resuming"); 413 } 414 } 415 } 416 417 mSystemInterface.setDisplayState(true); 418 sendPowerManagerEvent(CarPowerStateListener.ON); 419 420 mHal.sendOn(); 421 422 try { 423 switchUserOnResumeIfNecessary(allowUserSwitch); 424 } catch (Exception e) { 425 Log.e(CarLog.TAG_POWER, "Could not switch user on resume", e); 426 } 427 428 setVoiceInteractionDisabled(false); 429 } 430 431 @VisibleForTesting // Ideally it should not be exposed, but it speeds up the unit tests switchUserOnResumeIfNecessary(boolean allowSwitching)432 void switchUserOnResumeIfNecessary(boolean allowSwitching) { 433 Log.d(TAG, "switchUserOnResumeIfNecessary(): allowSwitching=" + allowSwitching 434 + ", mSwitchGuestUserBeforeSleep=" + mSwitchGuestUserBeforeSleep); 435 if (!allowSwitching) { 436 if (mSwitchGuestUserBeforeSleep) { // already handled 437 return; 438 } 439 switchToNewGuestIfNecessary(); 440 return; 441 } 442 443 if (CarProperties.user_hal_enabled().orElse(false) && mUserService.isUserHalSupported()) { 444 switchUserOnResumeIfNecessaryUsingHal(); 445 return; 446 } 447 448 executeDefaultInitialUserBehavior(!mSwitchGuestUserBeforeSleep); 449 } 450 executeDefaultInitialUserBehavior(boolean replaceGuest)451 private void executeDefaultInitialUserBehavior(boolean replaceGuest) { 452 mInitialUserSetter.set(newInitialUserInfoBuilder(InitialUserSetter.TYPE_DEFAULT_BEHAVIOR) 453 .setReplaceGuest(replaceGuest) 454 .build()); 455 } 456 457 /** 458 * Replaces the current user if it's a guest. 459 */ switchToNewGuestIfNecessary()460 private void switchToNewGuestIfNecessary() { 461 int currentUserId = ActivityManager.getCurrentUser(); 462 UserInfo currentUser = mUserManager.getUserInfo(currentUserId); 463 464 UserInfo newUser = mInitialUserSetter.replaceGuestIfNeeded(currentUser); 465 if (newUser == currentUser) return; // Not a guest 466 467 boolean replaceGuest = !mSwitchGuestUserBeforeSleep; 468 if (newUser == null) { 469 Log.w(TAG, "Failed to replace guest; falling back to default behavior"); 470 executeDefaultInitialUserBehavior(replaceGuest); 471 return; 472 } 473 switchUser(newUser.id, replaceGuest); 474 } 475 switchUser(@serIdInt int userId, boolean replaceGuest)476 private void switchUser(@UserIdInt int userId, boolean replaceGuest) { 477 mInitialUserSetter.set(newInitialUserInfoBuilder(InitialUserSetter.TYPE_SWITCH) 478 .setSwitchUserId(userId).setReplaceGuest(replaceGuest).build()); 479 } 480 newInitialUserInfoBuilder(@nitialUserInfoType int type)481 private InitialUserSetter.Builder newInitialUserInfoBuilder(@InitialUserInfoType int type) { 482 return new InitialUserSetter.Builder(type) 483 .setSupportsOverrideUserIdProperty(!mUserService.isUserHalSupported()); 484 } 485 486 /** 487 * Tells Garage Mode if it should run normally, or just 488 * exit immediately without indicating 'idle' 489 * @return True if no idle jobs should be run 490 * @hide 491 */ garageModeShouldExitImmediately()492 public boolean garageModeShouldExitImmediately() { 493 synchronized (mLock) { 494 return mGarageModeShouldExitImmediately; 495 } 496 } 497 498 /** 499 * Switches the initial user by calling the User HAL to define the behavior. 500 */ switchUserOnResumeIfNecessaryUsingHal()501 private void switchUserOnResumeIfNecessaryUsingHal() { 502 Log.i(TAG, "Using User HAL to define initial user behavior"); 503 mUserService.getInitialUserInfo(InitialUserInfoRequestType.RESUME, (status, response) -> { 504 switch (status) { 505 case HalCallback.STATUS_HAL_RESPONSE_TIMEOUT: 506 case HalCallback.STATUS_HAL_SET_TIMEOUT: 507 switchUserOnResumeUserHalFallback("timeout"); 508 return; 509 case HalCallback.STATUS_CONCURRENT_OPERATION: 510 switchUserOnResumeUserHalFallback("concurrent call"); 511 return; 512 case HalCallback.STATUS_WRONG_HAL_RESPONSE: 513 switchUserOnResumeUserHalFallback("wrong response"); 514 return; 515 case HalCallback.STATUS_HAL_NOT_SUPPORTED: 516 switchUserOnResumeUserHalFallback("Hal not supported"); 517 return; 518 case HalCallback.STATUS_OK: 519 if (response == null) { 520 switchUserOnResumeUserHalFallback("no response"); 521 return; 522 } 523 boolean replaceGuest = !mSwitchGuestUserBeforeSleep; 524 switch (response.action) { 525 case InitialUserInfoResponseAction.DEFAULT: 526 Log.i(TAG, "HAL requested default initial user behavior"); 527 executeDefaultInitialUserBehavior(replaceGuest); 528 return; 529 case InitialUserInfoResponseAction.SWITCH: 530 int userId = response.userToSwitchOrCreate.userId; 531 Log.i(TAG, "HAL requested switch to user " + userId); 532 // If guest was replaced on shutdown, it doesn't need to be replaced 533 // again 534 switchUser(userId, replaceGuest); 535 return; 536 case InitialUserInfoResponseAction.CREATE: 537 int halFlags = response.userToSwitchOrCreate.flags; 538 String name = response.userNameToCreate; 539 Log.i(TAG, "HAL requested new user (name=" 540 + UserHelper.safeName(name) + ", flags=" 541 + UserHalHelper.userFlagsToString(halFlags) + ")"); 542 mInitialUserSetter 543 .set(newInitialUserInfoBuilder(InitialUserSetter.TYPE_CREATE) 544 .setNewUserName(name) 545 .setNewUserFlags(halFlags) 546 .build()); 547 return; 548 default: 549 switchUserOnResumeUserHalFallback( 550 "invalid response action: " + response.action); 551 return; 552 } 553 default: 554 switchUserOnResumeUserHalFallback("invalid status: " + status); 555 } 556 }); 557 } 558 559 /** 560 * Switches the initial user directly when the User HAL call failed. 561 */ switchUserOnResumeUserHalFallback(String reason)562 private void switchUserOnResumeUserHalFallback(String reason) { 563 Log.w(TAG, "Failed to set initial user based on User Hal (" + reason 564 + "); falling back to default behavior"); 565 executeDefaultInitialUserBehavior(!mSwitchGuestUserBeforeSleep); 566 } 567 handleShutdownPrepare(CpmsState newState)568 private void handleShutdownPrepare(CpmsState newState) { 569 setVoiceInteractionDisabled(true); 570 mSystemInterface.setDisplayState(false); 571 // Shutdown on finish if the system doesn't support deep sleep or doesn't allow it. 572 synchronized (mLock) { 573 mShutdownOnFinish = mShutdownOnNextSuspend 574 || !mHal.isDeepSleepAllowed() 575 || !mSystemInterface.isSystemSupportingDeepSleep() 576 || !newState.mCanSleep; 577 mGarageModeShouldExitImmediately = !newState.mCanPostpone; 578 } 579 Log.i(CarLog.TAG_POWER, 580 (newState.mCanPostpone 581 ? "starting shutdown prepare with Garage Mode" 582 : "starting shutdown prepare without Garage Mode")); 583 sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE); 584 mHal.sendShutdownPrepare(); 585 doHandlePreprocessing(); 586 } 587 588 // Simulate system shutdown to Deep Sleep simulateShutdownPrepare()589 private void simulateShutdownPrepare() { 590 mSystemInterface.setDisplayState(false); 591 Log.i(CarLog.TAG_POWER, "starting shutdown prepare"); 592 sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE); 593 mHal.sendShutdownPrepare(); 594 doHandlePreprocessing(); 595 } 596 handleWaitForFinish(CpmsState state)597 private void handleWaitForFinish(CpmsState state) { 598 sendPowerManagerEvent(state.mCarPowerStateListenerState); 599 int wakeupSec; 600 synchronized (mLock) { 601 // If we're shutting down immediately, don't schedule 602 // a wakeup time. 603 wakeupSec = mGarageModeShouldExitImmediately ? 0 : mNextWakeupSec; 604 } 605 switch (state.mCarPowerStateListenerState) { 606 case CarPowerStateListener.SUSPEND_ENTER: 607 mHal.sendSleepEntry(wakeupSec); 608 break; 609 case CarPowerStateListener.SHUTDOWN_ENTER: 610 mHal.sendShutdownStart(wakeupSec); 611 break; 612 } 613 } 614 handleFinish()615 private void handleFinish() { 616 boolean simulatedMode; 617 synchronized (mSimulationWaitObject) { 618 simulatedMode = mInSimulatedDeepSleepMode; 619 } 620 boolean mustShutDown; 621 boolean forceReboot; 622 synchronized (mLock) { 623 mustShutDown = mShutdownOnFinish && !simulatedMode; 624 forceReboot = mRebootAfterGarageMode; 625 mRebootAfterGarageMode = false; 626 } 627 if (forceReboot) { 628 PowerManager powerManager = mContext.getSystemService(PowerManager.class); 629 if (powerManager == null) { 630 Log.wtf(CarLog.TAG_POWER, "No PowerManager. Cannot reboot."); 631 } else { 632 Log.i(CarLog.TAG_POWER, "GarageMode has completed. Forcing reboot."); 633 powerManager.reboot("GarageModeReboot"); 634 throw new AssertionError("Should not return from PowerManager.reboot()"); 635 } 636 } 637 setVoiceInteractionDisabled(true); 638 639 if (mustShutDown) { 640 // shutdown HU 641 mSystemInterface.shutdown(); 642 } else { 643 doHandleDeepSleep(simulatedMode); 644 } 645 mShutdownOnNextSuspend = false; 646 } 647 setVoiceInteractionDisabled(boolean disabled)648 private void setVoiceInteractionDisabled(boolean disabled) { 649 try { 650 mVoiceInteractionManagerService.setDisabled(disabled); 651 } catch (RemoteException e) { 652 Log.w(TAG, "setVoiceIntefactionDisabled(" + disabled + ") failed", e); 653 } 654 } 655 656 @GuardedBy("mLock") releaseTimerLocked()657 private void releaseTimerLocked() { 658 if (mTimer != null) { 659 mTimer.cancel(); 660 } 661 mTimer = null; 662 mTimerActive = false; 663 } 664 doHandlePreprocessing()665 private void doHandlePreprocessing() { 666 int intervalMs; 667 int pollingCount; 668 synchronized (mLock) { 669 intervalMs = mShutdownPollingIntervalMs; 670 pollingCount = (mShutdownPrepareTimeMs / mShutdownPollingIntervalMs) + 1; 671 } 672 if (Build.IS_USERDEBUG || Build.IS_ENG) { 673 int shutdownPrepareTimeOverrideInSecs = 674 SystemProperties.getInt(PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE, -1); 675 if (shutdownPrepareTimeOverrideInSecs >= 0) { 676 pollingCount = 677 (shutdownPrepareTimeOverrideInSecs * 1000 / intervalMs) 678 + 1; 679 Log.i(CarLog.TAG_POWER, 680 "Garage mode duration overridden secs:" 681 + shutdownPrepareTimeOverrideInSecs); 682 } 683 } 684 Log.i(CarLog.TAG_POWER, "processing before shutdown expected for: " 685 + mShutdownPrepareTimeMs + " ms, adding polling:" + pollingCount); 686 synchronized (mLock) { 687 mProcessingStartTime = SystemClock.elapsedRealtime(); 688 releaseTimerLocked(); 689 mTimer = new Timer(); 690 mTimerActive = true; 691 mTimer.scheduleAtFixedRate( 692 new ShutdownProcessingTimerTask(pollingCount), 693 0 /*delay*/, 694 intervalMs); 695 } 696 if (mSwitchGuestUserBeforeSleep) { 697 switchToNewGuestIfNecessary(); 698 } 699 } 700 sendPowerManagerEvent(int newState)701 private void sendPowerManagerEvent(int newState) { 702 // Broadcast to the listeners that do not signal completion 703 notifyListeners(mPowerManagerListeners, newState); 704 705 // SHUTDOWN_PREPARE is the only state where we need 706 // to maintain callbacks from listener components. 707 boolean allowCompletion = (newState == CarPowerStateListener.SHUTDOWN_PREPARE); 708 709 // Fully populate mListenersWeAreWaitingFor before calling any onStateChanged() 710 // for the listeners that signal completion. 711 // Otherwise, if the first listener calls finish() synchronously, we will 712 // see the list go empty and we will think that we are done. 713 boolean haveSomeCompleters = false; 714 PowerManagerCallbackList completingListeners = new PowerManagerCallbackList(); 715 synchronized (mLock) { 716 mListenersWeAreWaitingFor.clear(); 717 int idx = mPowerManagerListenersWithCompletion.beginBroadcast(); 718 while (idx-- > 0) { 719 ICarPowerStateListener listener = 720 mPowerManagerListenersWithCompletion.getBroadcastItem(idx); 721 completingListeners.register(listener); 722 if (allowCompletion) { 723 mListenersWeAreWaitingFor.add(listener.asBinder()); 724 haveSomeCompleters = true; 725 } 726 } 727 mPowerManagerListenersWithCompletion.finishBroadcast(); 728 } 729 // Broadcast to the listeners that DO signal completion 730 notifyListeners(completingListeners, newState); 731 732 if (allowCompletion && !haveSomeCompleters) { 733 // No jobs need to signal completion. So we are now complete. 734 signalComplete(); 735 } 736 } 737 notifyListeners(PowerManagerCallbackList listenerList, int newState)738 private void notifyListeners(PowerManagerCallbackList listenerList, int newState) { 739 int idx = listenerList.beginBroadcast(); 740 while (idx-- > 0) { 741 ICarPowerStateListener listener = listenerList.getBroadcastItem(idx); 742 try { 743 listener.onStateChanged(newState); 744 } catch (RemoteException e) { 745 // It's likely the connection snapped. Let binder death handle the situation. 746 Log.e(CarLog.TAG_POWER, "onStateChanged() call failed", e); 747 } 748 } 749 listenerList.finishBroadcast(); 750 } 751 doHandleDeepSleep(boolean simulatedMode)752 private void doHandleDeepSleep(boolean simulatedMode) { 753 // keep holding partial wakelock to prevent entering sleep before enterDeepSleep call 754 // enterDeepSleep should force sleep entry even if wake lock is kept. 755 mSystemInterface.switchToPartialWakeLock(); 756 mHandler.cancelProcessingComplete(); 757 synchronized (mLock) { 758 mLastSleepEntryTime = SystemClock.elapsedRealtime(); 759 } 760 int nextListenerState; 761 if (simulatedMode) { 762 simulateSleepByWaiting(); 763 nextListenerState = CarPowerStateListener.SHUTDOWN_CANCELLED; 764 } else { 765 boolean sleepSucceeded = suspendWithRetries(); 766 if (!sleepSucceeded) { 767 // Suspend failed and we shut down instead. 768 // We either won't get here at all or we will power off very soon. 769 return; 770 } 771 // We suspended and have now resumed 772 nextListenerState = CarPowerStateListener.SUSPEND_EXIT; 773 } 774 synchronized (mLock) { 775 mIsResuming = true; 776 // Any wakeup time from before is no longer valid. 777 mNextWakeupSec = 0; 778 } 779 Log.i(CarLog.TAG_POWER, "Resuming after suspending"); 780 mSystemInterface.refreshDisplayBrightness(); 781 onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, nextListenerState); 782 } 783 needPowerStateChangeLocked(@onNull CpmsState newState)784 private boolean needPowerStateChangeLocked(@NonNull CpmsState newState) { 785 if (mCurrentState == null) { 786 return true; 787 } else if (mCurrentState.equals(newState)) { 788 Log.d(CarLog.TAG_POWER, "Requested state is already in effect: " 789 + newState.name()); 790 return false; 791 } 792 793 // The following switch/case enforces the allowed state transitions. 794 boolean transitionAllowed = false; 795 switch (mCurrentState.mState) { 796 case CpmsState.WAIT_FOR_VHAL: 797 transitionAllowed = (newState.mState == CpmsState.ON) 798 || (newState.mState == CpmsState.SHUTDOWN_PREPARE); 799 break; 800 case CpmsState.SUSPEND: 801 transitionAllowed = newState.mState == CpmsState.WAIT_FOR_VHAL; 802 break; 803 case CpmsState.ON: 804 transitionAllowed = (newState.mState == CpmsState.SHUTDOWN_PREPARE) 805 || (newState.mState == CpmsState.SIMULATE_SLEEP); 806 break; 807 case CpmsState.SHUTDOWN_PREPARE: 808 // If VHAL sends SHUTDOWN_IMMEDIATELY or SLEEP_IMMEDIATELY while in 809 // SHUTDOWN_PREPARE state, do it. 810 transitionAllowed = 811 ((newState.mState == CpmsState.SHUTDOWN_PREPARE) && !newState.mCanPostpone) 812 || (newState.mState == CpmsState.WAIT_FOR_FINISH) 813 || (newState.mState == CpmsState.WAIT_FOR_VHAL); 814 break; 815 case CpmsState.SIMULATE_SLEEP: 816 transitionAllowed = true; 817 break; 818 case CpmsState.WAIT_FOR_FINISH: 819 transitionAllowed = (newState.mState == CpmsState.SUSPEND 820 || newState.mState == CpmsState.WAIT_FOR_VHAL); 821 break; 822 default: 823 Log.e(CarLog.TAG_POWER, "Unexpected current state: currentState=" 824 + mCurrentState.name() + ", newState=" + newState.name()); 825 transitionAllowed = true; 826 } 827 if (!transitionAllowed) { 828 Log.e(CarLog.TAG_POWER, "Requested power transition is not allowed: " 829 + mCurrentState.name() + " --> " + newState.name()); 830 } 831 return transitionAllowed; 832 } 833 doHandleProcessingComplete()834 private void doHandleProcessingComplete() { 835 int listenerState; 836 synchronized (mLock) { 837 releaseTimerLocked(); 838 if (!mShutdownOnFinish && mLastSleepEntryTime > mProcessingStartTime) { 839 // entered sleep after processing start. So this could be duplicate request. 840 Log.w(CarLog.TAG_POWER, "Duplicate sleep entry request, ignore"); 841 return; 842 } 843 listenerState = mShutdownOnFinish 844 ? CarPowerStateListener.SHUTDOWN_ENTER : CarPowerStateListener.SUSPEND_ENTER; 845 } 846 847 onApPowerStateChange(CpmsState.WAIT_FOR_FINISH, listenerState); 848 } 849 850 @Override onDisplayBrightnessChange(int brightness)851 public void onDisplayBrightnessChange(int brightness) { 852 mHandler.handleDisplayBrightnessChange(brightness); 853 } 854 doHandleDisplayBrightnessChange(int brightness)855 private void doHandleDisplayBrightnessChange(int brightness) { 856 mSystemInterface.setDisplayBrightness(brightness); 857 } 858 doHandleMainDisplayStateChange(boolean on)859 private void doHandleMainDisplayStateChange(boolean on) { 860 Log.w(CarLog.TAG_POWER, "Unimplemented: doHandleMainDisplayStateChange() - on = " + on); 861 } 862 handleMainDisplayChanged(boolean on)863 public void handleMainDisplayChanged(boolean on) { 864 mHandler.handleMainDisplayStateChange(on); 865 } 866 867 /** 868 * Send display brightness to VHAL. 869 * @param brightness value 0-100% 870 */ sendDisplayBrightness(int brightness)871 public void sendDisplayBrightness(int brightness) { 872 mHal.sendDisplayBrightness(brightness); 873 } 874 875 /** 876 * Get the PowerHandler that we use to change power states 877 */ getHandler()878 public Handler getHandler() { 879 return mHandler; 880 881 } 882 883 // Binder interface for general use. 884 // The listener is not required (or allowed) to call finished(). 885 @Override registerListener(ICarPowerStateListener listener)886 public void registerListener(ICarPowerStateListener listener) { 887 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 888 mPowerManagerListeners.register(listener); 889 } 890 891 // Binder interface for Car services only. 892 // After the listener completes its processing, it must call finished(). 893 @Override registerListenerWithCompletion(ICarPowerStateListener listener)894 public void registerListenerWithCompletion(ICarPowerStateListener listener) { 895 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 896 ICarImpl.assertCallingFromSystemProcessOrSelf(); 897 898 mPowerManagerListenersWithCompletion.register(listener); 899 // TODO: Need to send current state to newly registered listener? If so, need to handle 900 // completion for SHUTDOWN_PREPARE state 901 } 902 903 @Override unregisterListener(ICarPowerStateListener listener)904 public void unregisterListener(ICarPowerStateListener listener) { 905 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 906 doUnregisterListener(listener); 907 } 908 doUnregisterListener(ICarPowerStateListener listener)909 private void doUnregisterListener(ICarPowerStateListener listener) { 910 mPowerManagerListeners.unregister(listener); 911 boolean found = mPowerManagerListenersWithCompletion.unregister(listener); 912 if (found) { 913 // Remove this from the completion list (if it's there) 914 finishedImpl(listener.asBinder()); 915 } 916 } 917 918 @Override requestShutdownOnNextSuspend()919 public void requestShutdownOnNextSuspend() { 920 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 921 synchronized (mLock) { 922 mShutdownOnNextSuspend = true; 923 } 924 } 925 926 @Override finished(ICarPowerStateListener listener)927 public void finished(ICarPowerStateListener listener) { 928 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 929 ICarImpl.assertCallingFromSystemProcessOrSelf(); 930 finishedImpl(listener.asBinder()); 931 } 932 933 @Override scheduleNextWakeupTime(int seconds)934 public void scheduleNextWakeupTime(int seconds) { 935 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 936 if (seconds < 0) { 937 Log.w(CarLog.TAG_POWER, "Next wake up time is negative. Ignoring!"); 938 return; 939 } 940 boolean timedWakeupAllowed = mHal.isTimedWakeupAllowed(); 941 synchronized (mLock) { 942 if (!timedWakeupAllowed) { 943 Log.w(CarLog.TAG_POWER, "Setting timed wakeups are disabled in HAL. Skipping"); 944 mNextWakeupSec = 0; 945 return; 946 } 947 if (mNextWakeupSec == 0 || mNextWakeupSec > seconds) { 948 // The new value is sooner than the old value. Take the new value. 949 mNextWakeupSec = seconds; 950 } else { 951 Log.d(CarLog.TAG_POWER, "Tried to schedule next wake up, but already had shorter " 952 + "scheduled time"); 953 } 954 } 955 } 956 957 @Override getPowerState()958 public int getPowerState() { 959 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER); 960 synchronized (mLock) { 961 return (mCurrentState == null) ? CarPowerStateListener.INVALID 962 : mCurrentState.mCarPowerStateListenerState; 963 } 964 } 965 finishedImpl(IBinder binder)966 private void finishedImpl(IBinder binder) { 967 boolean allAreComplete; 968 synchronized (mLock) { 969 mListenersWeAreWaitingFor.remove(binder); 970 allAreComplete = mListenersWeAreWaitingFor.isEmpty(); 971 } 972 if (allAreComplete) { 973 signalComplete(); 974 } 975 } 976 signalComplete()977 private void signalComplete() { 978 if (mCurrentState.mState == CpmsState.SHUTDOWN_PREPARE 979 || mCurrentState.mState == CpmsState.SIMULATE_SLEEP) { 980 PowerHandler powerHandler; 981 // All apps are ready to shutdown/suspend. 982 synchronized (mLock) { 983 if (!mShutdownOnFinish) { 984 if (mLastSleepEntryTime > mProcessingStartTime 985 && mLastSleepEntryTime < SystemClock.elapsedRealtime()) { 986 Log.i(CarLog.TAG_POWER, "signalComplete: Already slept!"); 987 return; 988 } 989 } 990 powerHandler = mHandler; 991 } 992 Log.i(CarLog.TAG_POWER, "Apps are finished, call handleProcessingComplete()"); 993 powerHandler.handleProcessingComplete(); 994 } 995 } 996 997 private static final class PowerHandler extends Handler { 998 private static final String TAG = PowerHandler.class.getSimpleName(); 999 1000 private final int MSG_POWER_STATE_CHANGE = 0; 1001 private final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1; 1002 private final int MSG_MAIN_DISPLAY_STATE_CHANGE = 2; 1003 private final int MSG_PROCESSING_COMPLETE = 3; 1004 1005 // Do not handle this immediately but with some delay as there can be a race between 1006 // display off due to rear view camera and delivery to here. 1007 private final long MAIN_DISPLAY_EVENT_DELAY_MS = 500; 1008 1009 private final WeakReference<CarPowerManagementService> mService; 1010 PowerHandler(Looper looper, CarPowerManagementService service)1011 private PowerHandler(Looper looper, CarPowerManagementService service) { 1012 super(looper); 1013 mService = new WeakReference<CarPowerManagementService>(service); 1014 } 1015 handlePowerStateChange()1016 private void handlePowerStateChange() { 1017 Message msg = obtainMessage(MSG_POWER_STATE_CHANGE); 1018 sendMessage(msg); 1019 } 1020 handleDisplayBrightnessChange(int brightness)1021 private void handleDisplayBrightnessChange(int brightness) { 1022 Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, brightness, 0); 1023 sendMessage(msg); 1024 } 1025 handleMainDisplayStateChange(boolean on)1026 private void handleMainDisplayStateChange(boolean on) { 1027 removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE); 1028 Message msg = obtainMessage(MSG_MAIN_DISPLAY_STATE_CHANGE, Boolean.valueOf(on)); 1029 sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS); 1030 } 1031 handleProcessingComplete()1032 private void handleProcessingComplete() { 1033 removeMessages(MSG_PROCESSING_COMPLETE); 1034 Message msg = obtainMessage(MSG_PROCESSING_COMPLETE); 1035 sendMessage(msg); 1036 } 1037 cancelProcessingComplete()1038 private void cancelProcessingComplete() { 1039 removeMessages(MSG_PROCESSING_COMPLETE); 1040 } 1041 cancelAll()1042 private void cancelAll() { 1043 removeMessages(MSG_POWER_STATE_CHANGE); 1044 removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE); 1045 removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE); 1046 removeMessages(MSG_PROCESSING_COMPLETE); 1047 } 1048 1049 @Override handleMessage(Message msg)1050 public void handleMessage(Message msg) { 1051 CarPowerManagementService service = mService.get(); 1052 if (service == null) { 1053 Log.i(TAG, "handleMessage null service"); 1054 return; 1055 } 1056 switch (msg.what) { 1057 case MSG_POWER_STATE_CHANGE: 1058 service.doHandlePowerStateChange(); 1059 break; 1060 case MSG_DISPLAY_BRIGHTNESS_CHANGE: 1061 service.doHandleDisplayBrightnessChange(msg.arg1); 1062 break; 1063 case MSG_MAIN_DISPLAY_STATE_CHANGE: 1064 service.doHandleMainDisplayStateChange((Boolean) msg.obj); 1065 break; 1066 case MSG_PROCESSING_COMPLETE: 1067 service.doHandleProcessingComplete(); 1068 break; 1069 } 1070 } 1071 } 1072 1073 private class ShutdownProcessingTimerTask extends TimerTask { 1074 private final int mExpirationCount; 1075 private int mCurrentCount; 1076 ShutdownProcessingTimerTask(int expirationCount)1077 private ShutdownProcessingTimerTask(int expirationCount) { 1078 mExpirationCount = expirationCount; 1079 mCurrentCount = 0; 1080 } 1081 1082 @Override run()1083 public void run() { 1084 synchronized (mLock) { 1085 if (!mTimerActive) { 1086 // Ignore timer expiration since we got cancelled 1087 return; 1088 } 1089 mCurrentCount++; 1090 if (mCurrentCount > mExpirationCount) { 1091 PowerHandler handler; 1092 releaseTimerLocked(); 1093 handler = mHandler; 1094 handler.handleProcessingComplete(); 1095 } else { 1096 mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS); 1097 } 1098 } 1099 } 1100 } 1101 1102 // Send the command to enter Suspend to RAM. 1103 // If the command is not successful, try again. 1104 // If it fails repeatedly, send the command to shut down. 1105 // Returns true if we successfully suspended. suspendWithRetries()1106 private boolean suspendWithRetries() { 1107 final int maxTries = 3; 1108 final long retryIntervalMs = 10; 1109 int tryCount = 0; 1110 1111 while (true) { 1112 Log.i(CarLog.TAG_POWER, "Entering Suspend to RAM"); 1113 boolean suspendSucceeded = mSystemInterface.enterDeepSleep(); 1114 if (suspendSucceeded) { 1115 return true; 1116 } 1117 tryCount++; 1118 if (tryCount >= maxTries) { 1119 break; 1120 } 1121 // We failed to suspend. Block the thread briefly and try again. 1122 Log.w(CarLog.TAG_POWER, "Failed to Suspend; will retry later."); 1123 try { 1124 Thread.sleep(retryIntervalMs); 1125 } catch (InterruptedException ignored) { } 1126 } 1127 // Too many failures trying to suspend. Shut down. 1128 Log.w(CarLog.TAG_POWER, "Could not Suspend to RAM. Shutting down."); 1129 mSystemInterface.shutdown(); 1130 return false; 1131 } 1132 1133 private static class CpmsState { 1134 // NOTE: When modifying states below, make sure to update CarPowerStateChanged.State in 1135 // frameworks/base/cmds/statsd/src/atoms.proto also. 1136 public static final int WAIT_FOR_VHAL = 0; 1137 public static final int ON = 1; 1138 public static final int SHUTDOWN_PREPARE = 2; 1139 public static final int WAIT_FOR_FINISH = 3; 1140 public static final int SUSPEND = 4; 1141 public static final int SIMULATE_SLEEP = 5; 1142 1143 /* Config values from AP_POWER_STATE_REQ */ 1144 public final boolean mCanPostpone; 1145 public final boolean mCanSleep; 1146 /* Message sent to CarPowerStateListener in response to this state */ 1147 public final int mCarPowerStateListenerState; 1148 /* One of the above state variables */ 1149 public final int mState; 1150 1151 /** 1152 * This constructor takes a PowerHalService.PowerState object and creates the corresponding 1153 * CPMS state from it. 1154 */ CpmsState(PowerState halPowerState)1155 CpmsState(PowerState halPowerState) { 1156 switch (halPowerState.mState) { 1157 case VehicleApPowerStateReq.ON: 1158 this.mCanPostpone = false; 1159 this.mCanSleep = false; 1160 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(ON); 1161 this.mState = ON; 1162 break; 1163 case VehicleApPowerStateReq.SHUTDOWN_PREPARE: 1164 this.mCanPostpone = halPowerState.canPostponeShutdown(); 1165 this.mCanSleep = halPowerState.canEnterDeepSleep(); 1166 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState( 1167 SHUTDOWN_PREPARE); 1168 this.mState = SHUTDOWN_PREPARE; 1169 break; 1170 case VehicleApPowerStateReq.CANCEL_SHUTDOWN: 1171 this.mCanPostpone = false; 1172 this.mCanSleep = false; 1173 this.mCarPowerStateListenerState = CarPowerStateListener.SHUTDOWN_CANCELLED; 1174 this.mState = WAIT_FOR_VHAL; 1175 break; 1176 case VehicleApPowerStateReq.FINISHED: 1177 this.mCanPostpone = false; 1178 this.mCanSleep = false; 1179 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(SUSPEND); 1180 this.mState = SUSPEND; 1181 break; 1182 default: 1183 // Illegal state from PowerState. Throw an exception? 1184 this.mCanPostpone = false; 1185 this.mCanSleep = false; 1186 this.mCarPowerStateListenerState = 0; 1187 this.mState = 0; 1188 break; 1189 } 1190 } 1191 CpmsState(int state)1192 CpmsState(int state) { 1193 this(state, cpmsStateToPowerStateListenerState(state)); 1194 } 1195 CpmsState(int state, int carPowerStateListenerState)1196 CpmsState(int state, int carPowerStateListenerState) { 1197 this.mCanPostpone = (state == SIMULATE_SLEEP); 1198 this.mCanSleep = (state == SIMULATE_SLEEP); 1199 this.mCarPowerStateListenerState = carPowerStateListenerState; 1200 this.mState = state; 1201 } 1202 name()1203 public String name() { 1204 String baseName; 1205 switch(mState) { 1206 case WAIT_FOR_VHAL: baseName = "WAIT_FOR_VHAL"; break; 1207 case ON: baseName = "ON"; break; 1208 case SHUTDOWN_PREPARE: baseName = "SHUTDOWN_PREPARE"; break; 1209 case WAIT_FOR_FINISH: baseName = "WAIT_FOR_FINISH"; break; 1210 case SUSPEND: baseName = "SUSPEND"; break; 1211 case SIMULATE_SLEEP: baseName = "SIMULATE_SLEEP"; break; 1212 default: baseName = "<unknown>"; break; 1213 } 1214 return baseName + "(" + mState + ")"; 1215 } 1216 cpmsStateToPowerStateListenerState(int state)1217 private static int cpmsStateToPowerStateListenerState(int state) { 1218 int powerStateListenerState = 0; 1219 1220 // Set the CarPowerStateListenerState based on current state 1221 switch (state) { 1222 case ON: 1223 powerStateListenerState = CarPowerStateListener.ON; 1224 break; 1225 case SHUTDOWN_PREPARE: 1226 powerStateListenerState = CarPowerStateListener.SHUTDOWN_PREPARE; 1227 break; 1228 case SUSPEND: 1229 powerStateListenerState = CarPowerStateListener.SUSPEND_ENTER; 1230 break; 1231 case WAIT_FOR_VHAL: 1232 case WAIT_FOR_FINISH: 1233 default: 1234 // Illegal state for this constructor. Throw an exception? 1235 break; 1236 } 1237 return powerStateListenerState; 1238 } 1239 1240 @Override equals(Object o)1241 public boolean equals(Object o) { 1242 if (this == o) { 1243 return true; 1244 } 1245 if (!(o instanceof CpmsState)) { 1246 return false; 1247 } 1248 CpmsState that = (CpmsState) o; 1249 return this.mState == that.mState 1250 && this.mCanSleep == that.mCanSleep 1251 && this.mCanPostpone == that.mCanPostpone 1252 && this.mCarPowerStateListenerState == that.mCarPowerStateListenerState; 1253 } 1254 1255 @Override toString()1256 public String toString() { 1257 return "CpmsState canSleep:" + mCanSleep + ", canPostpone=" + mCanPostpone 1258 + ", carPowerStateListenerState=" + mCarPowerStateListenerState 1259 + ", CpmsState=" + this.name(); 1260 } 1261 } 1262 1263 /** 1264 * Resume after a manually-invoked suspend. 1265 * Invoked using "adb shell dumpsys activity service com.android.car resume". 1266 */ forceSimulatedResume()1267 public void forceSimulatedResume() { 1268 PowerHandler handler; 1269 synchronized (mLock) { 1270 // Cancel Garage Mode in case it's running 1271 mPendingPowerStates.addFirst(new CpmsState(CpmsState.WAIT_FOR_VHAL, 1272 CarPowerStateListener.SHUTDOWN_CANCELLED)); 1273 handler = mHandler; 1274 } 1275 handler.handlePowerStateChange(); 1276 1277 synchronized (mSimulationWaitObject) { 1278 mWakeFromSimulatedSleep = true; 1279 mSimulationWaitObject.notify(); 1280 } 1281 } 1282 1283 /** 1284 * Manually enter simulated suspend (Deep Sleep) mode, trigging Garage mode. 1285 * If the parameter is 'true', reboot the system when Garage Mode completes. 1286 * 1287 * Invoked using "adb shell dumpsys activity service com.android.car suspend" or 1288 * "adb shell dumpsys activity service com.android.car garage-mode reboot". 1289 * This is similar to 'onApPowerStateChange()' except that it needs to create a CpmsState 1290 * that is not directly derived from a VehicleApPowerStateReq. 1291 */ 1292 @VisibleForTesting forceSuspendAndMaybeReboot(boolean shouldReboot)1293 void forceSuspendAndMaybeReboot(boolean shouldReboot) { 1294 synchronized (mSimulationWaitObject) { 1295 mInSimulatedDeepSleepMode = true; 1296 mWakeFromSimulatedSleep = false; 1297 mGarageModeShouldExitImmediately = false; 1298 } 1299 PowerHandler handler; 1300 synchronized (mLock) { 1301 mRebootAfterGarageMode = shouldReboot; 1302 mPendingPowerStates.addFirst(new CpmsState(CpmsState.SIMULATE_SLEEP, 1303 CarPowerStateListener.SHUTDOWN_PREPARE)); 1304 handler = mHandler; 1305 } 1306 handler.handlePowerStateChange(); 1307 } 1308 1309 // In a real Deep Sleep, the hardware removes power from the CPU (but retains power 1310 // on the RAM). This puts the processor to sleep. Upon some external signal, power 1311 // is re-applied to the CPU, and processing resumes right where it left off. 1312 // We simulate this behavior by calling wait(). 1313 // We continue from wait() when forceSimulatedResume() is called. simulateSleepByWaiting()1314 private void simulateSleepByWaiting() { 1315 Log.i(CarLog.TAG_POWER, "Starting to simulate Deep Sleep by waiting"); 1316 synchronized (mSimulationWaitObject) { 1317 while (!mWakeFromSimulatedSleep) { 1318 try { 1319 mSimulationWaitObject.wait(); 1320 } catch (InterruptedException ignored) { 1321 Thread.currentThread().interrupt(); // Restore interrupted status 1322 } 1323 } 1324 mInSimulatedDeepSleepMode = false; 1325 } 1326 Log.i(CarLog.TAG_POWER, "Exit Deep Sleep simulation"); 1327 } 1328 } 1329