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