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