• 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 
17 package com.android.car.power;
18 
19 import static android.car.hardware.power.CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE;
20 import static android.car.hardware.power.CarPowerManager.STATE_SHUTDOWN_PREPARE;
21 import static android.net.ConnectivityManager.TETHERING_WIFI;
22 
23 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
24 
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.app.ActivityManager;
28 import android.car.Car;
29 import android.car.ICarResultReceiver;
30 import android.car.builtin.os.BuildHelper;
31 import android.car.builtin.os.ServiceManagerHelper;
32 import android.car.builtin.util.EventLogHelper;
33 import android.car.builtin.util.Slogf;
34 import android.car.hardware.power.CarPowerManager;
35 import android.car.hardware.power.CarPowerPolicy;
36 import android.car.hardware.power.CarPowerPolicyFilter;
37 import android.car.hardware.power.ICarPower;
38 import android.car.hardware.power.ICarPowerPolicyListener;
39 import android.car.hardware.power.ICarPowerStateListener;
40 import android.content.ComponentName;
41 import android.content.Context;
42 import android.content.Intent;
43 import android.content.res.Resources;
44 import android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification;
45 import android.frameworks.automotive.powerpolicy.internal.PolicyState;
46 import android.hardware.automotive.vehicle.VehicleApPowerStateReport;
47 import android.hardware.automotive.vehicle.VehicleApPowerStateReq;
48 import android.hardware.automotive.vehicle.VehicleApPowerStateShutdownParam;
49 import android.net.TetheringManager;
50 import android.net.TetheringManager.TetheringRequest;
51 import android.net.wifi.WifiManager;
52 import android.os.Handler;
53 import android.os.HandlerThread;
54 import android.os.IBinder;
55 import android.os.IInterface;
56 import android.os.Looper;
57 import android.os.Message;
58 import android.os.PowerManager;
59 import android.os.RemoteCallbackList;
60 import android.os.RemoteException;
61 import android.os.SystemClock;
62 import android.os.SystemProperties;
63 import android.os.UserHandle;
64 import android.os.UserManager;
65 import android.util.ArraySet;
66 import android.util.AtomicFile;
67 import android.util.SparseArray;
68 
69 import com.android.car.CarLocalServices;
70 import com.android.car.CarLog;
71 import com.android.car.CarServiceBase;
72 import com.android.car.CarServiceUtils;
73 import com.android.car.CarStatsLogHelper;
74 import com.android.car.R;
75 import com.android.car.hal.PowerHalService;
76 import com.android.car.hal.PowerHalService.PowerState;
77 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
78 import com.android.car.internal.util.DebugUtils;
79 import com.android.car.internal.util.IndentingPrintWriter;
80 import com.android.car.systeminterface.SystemInterface;
81 import com.android.car.user.CarUserNoticeService;
82 import com.android.car.user.CarUserService;
83 import com.android.car.user.UserHandleHelper;
84 import com.android.internal.annotations.GuardedBy;
85 import com.android.internal.annotations.VisibleForTesting;
86 import com.android.internal.util.Preconditions;
87 
88 import java.io.BufferedReader;
89 import java.io.BufferedWriter;
90 import java.io.File;
91 import java.io.FileOutputStream;
92 import java.io.IOException;
93 import java.io.InputStreamReader;
94 import java.io.OutputStreamWriter;
95 import java.lang.ref.WeakReference;
96 import java.nio.charset.StandardCharsets;
97 import java.util.ArrayList;
98 import java.util.LinkedList;
99 import java.util.concurrent.ExecutorService;
100 import java.util.concurrent.Executors;
101 import java.util.concurrent.Semaphore;
102 import java.util.concurrent.TimeUnit;
103 import java.util.concurrent.atomic.AtomicBoolean;
104 import java.util.function.BiFunction;
105 
106 /**
107  * Power Management service class for cars. Controls the power states and interacts with other
108  * parts of the system to ensure its own state.
109  */
110 public class CarPowerManagementService extends ICarPower.Stub implements
111         CarServiceBase, PowerHalService.PowerEventListener {
112     public static final String SILENT_MODE_FORCED_SILENT =
113             SilentModeHandler.SILENT_MODE_FORCED_SILENT;
114     public static final String SILENT_MODE_FORCED_NON_SILENT =
115             SilentModeHandler.SILENT_MODE_FORCED_NON_SILENT;
116     public static final String SILENT_MODE_NON_FORCED = SilentModeHandler.SILENT_MODE_NON_FORCED;
117 
118     public static final long INVALID_TIMEOUT = -1L;
119 
120     public static final int NO_WAKEUP_BY_TIMER = -1;
121 
122     static final String TAG = CarLog.tagFor(CarPowerManagementService.class);
123 
124     private static final String WIFI_STATE_FILENAME = "wifi_state";
125     private static final String TETHERING_STATE_FILENAME = "tethering_state";
126     private static final String COMPONENT_STATE_MODIFIED = "forcibly_disabled";
127     private static final String COMPONENT_STATE_ORIGINAL = "original";
128     // If Suspend to RAM fails, we retry with an exponential back-off:
129     // The wait interval will be 10 msec, 20 msec, 40 msec, ...
130     // Once the wait interval goes beyond 100 msec, it is fixed at 100 msec.
131     private static final long INITIAL_SUSPEND_RETRY_INTERVAL_MS = 10;
132     private static final long MAX_RETRY_INTERVAL_MS = 100;
133     // Minimum and maximum wait duration before the system goes into Suspend to RAM.
134     private static final long MIN_SUSPEND_WAIT_DURATION_MS = 0;
135     private static final long MAX_SUSPEND_WAIT_DURATION_MS = 3 * 60 * 1000;
136 
137     private static final long CAR_POWER_POLICY_DAEMON_FIND_MARGINAL_TIME_MS = 300;
138     private static final long CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS = 500;
139     private static final int CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY = 3;
140     private static final String CAR_POWER_POLICY_DAEMON_INTERFACE =
141             "android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification/"
142                     + "default";
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     // Constants for action on finish
155     private static final int ACTION_ON_FINISH_SHUTDOWN = 0;
156     private static final int ACTION_ON_FINISH_DEEP_SLEEP = 1;
157     private static final int ACTION_ON_FINISH_HIBERNATION = 2;
158 
159     // Default timeout for listener completion during shutdown.
160     private static final int DEFAULT_COMPLETION_WAIT_TIMEOUT = 5_000;
161 
162     private final Object mLock = new Object();
163     private final Object mSimulationWaitObject = new Object();
164 
165     private final Context mContext;
166     private final PowerHalService mHal;
167     private final SystemInterface mSystemInterface;
168     // The listeners that complete simply by returning from onStateChanged()
169     private final PowerManagerCallbackList<ICarPowerStateListener> mPowerManagerListeners =
170             new PowerManagerCallbackList<>(
171                     l -> CarPowerManagementService.this.doUnregisterListener(l));
172     // The listeners that must indicate asynchronous completion by calling finished().
173     private final PowerManagerCallbackList<ICarPowerStateListener>
174             mPowerManagerListenersWithCompletion = new PowerManagerCallbackList<>(
175                     l -> CarPowerManagementService.this.doUnregisterListener(l));
176     // The internal listeners that must indicates asynchronous completion by calling
177     // completeStateChangeHandling(). Note that they are not binder objects.
178     @GuardedBy("mLock")
179     private final ArrayList<ICarPowerStateListener> mInternalPowerListeners = new ArrayList<>();
180 
181     @GuardedBy("mLock")
182     private final ArraySet<IBinder> mListenersWeAreWaitingFor = new ArraySet<>();
183     @GuardedBy("mLock")
184     private final LinkedList<CpmsState> mPendingPowerStates = new LinkedList<>();
185     private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
186             getClass().getSimpleName());
187     private final PowerHandler mHandler = new PowerHandler(mHandlerThread.getLooper(), this);
188 
189     private final UserManager mUserManager;
190     private final CarUserService mUserService;
191 
192     private final WifiManager mWifiManager;
193     private final TetheringManager mTetheringManager;
194     private final AtomicFile mWifiStateFile;
195     private final AtomicFile mTetheringStateFile;
196     private final boolean mWifiAdjustmentForSuspend;
197 
198     // This is a temp work-around to reduce user switching delay after wake-up.
199     private final boolean mSwitchGuestUserBeforeSleep;
200 
201     // CPMS tries to enter Suspend to RAM within the duration specified at
202     // mMaxSuspendWaitDurationMs. The default max duration is MAX_SUSPEND_WAIT_DRATION, and can be
203     // overridden by setting config_maxSuspendWaitDuration in an overrlay resource.
204     // The valid range is MIN_SUSPEND_WAIT_DRATION to MAX_SUSPEND_WAIT_DURATION.
205     private final long mMaxSuspendWaitDurationMs;
206 
207     @GuardedBy("mSimulationWaitObject")
208     private boolean mWakeFromSimulatedSleep;
209     @GuardedBy("mSimulationWaitObject")
210     private boolean mInSimulatedDeepSleepMode;
211     @GuardedBy("mSimulationWaitObject")
212     private int mResumeDelayFromSimulatedSuspendSec = NO_WAKEUP_BY_TIMER;
213 
214     @GuardedBy("mLock")
215     private CpmsState mCurrentState;
216     @GuardedBy("mLock")
217     private long mShutdownStartTime;
218     @GuardedBy("mLock")
219     private long mLastSleepEntryTime;
220 
221     @GuardedBy("mLock")
222     private int mNextWakeupSec;
223     @GuardedBy("mLock")
224     private int mActionOnFinish;
225     @GuardedBy("mLock")
226     private boolean mShutdownOnNextSuspend;
227     @GuardedBy("mLock")
228     private boolean mIsBooting = true;
229     @GuardedBy("mLock")
230     private int mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS;
231     @GuardedBy("mLock")
232     private int mShutdownPollingIntervalMs = SHUTDOWN_POLLING_INTERVAL_MS;
233     @GuardedBy("mLock")
234     private boolean mRebootAfterGarageMode;
235     @GuardedBy("mLock")
236     private boolean mGarageModeShouldExitImmediately;
237 
238     @GuardedBy("mLock")
239     private ICarPowerPolicySystemNotification mCarPowerPolicyDaemon;
240     @GuardedBy("mLock")
241     private boolean mConnectionInProgress;
242     private BinderHandler mBinderHandler;
243     @GuardedBy("mLock")
244     private String mCurrentPowerPolicyId;
245     @GuardedBy("mLock")
246     private String mPendingPowerPolicyId;
247     @GuardedBy("mLock")
248     private String mCurrentPowerPolicyGroupId;
249     @GuardedBy("mLock")
250     private boolean mIsPowerPolicyLocked;
251     @GuardedBy("mLock")
252     private boolean mHasControlOverDaemon;
253     private AtomicBoolean mIsListenerWaitingCancelled = new AtomicBoolean(false);
254     private final Semaphore mListenerCompletionSem = new Semaphore(/* permits= */ 0);
255     @GuardedBy("mLock")
256     @CarPowerManager.CarPowerState
257     private int mStateForCompletion = CarPowerManager.STATE_INVALID;
258 
259     @GuardedBy("mLock")
260     @Nullable
261     private ICarResultReceiver mFactoryResetCallback;
262 
263     private final PowerManagerCallbackList<ICarPowerPolicyListener> mPowerPolicyListeners =
264             new PowerManagerCallbackList<>(
265                     l -> CarPowerManagementService.this.mPowerPolicyListeners.unregister(l));
266 
267     private final PowerComponentHandler mPowerComponentHandler;
268     private final PolicyReader mPolicyReader = new PolicyReader();
269     private final SilentModeHandler mSilentModeHandler;
270 
271     interface ActionOnDeath<T extends IInterface> {
take(T listener)272         void take(T listener);
273     }
274 
275     private final class PowerManagerCallbackList<T extends IInterface> extends
276             RemoteCallbackList<T> {
277         private ActionOnDeath<T> mActionOnDeath;
278 
PowerManagerCallbackList(ActionOnDeath<T> action)279         PowerManagerCallbackList(ActionOnDeath<T> action) {
280             mActionOnDeath = action;
281         }
282 
283         /**
284          * Old version of {@link #onCallbackDied(E, Object)} that
285          * does not provide a cookie.
286          */
287         @Override
onCallbackDied(T listener)288         public void onCallbackDied(T listener) {
289             Slogf.i(TAG, "binderDied %s", listener.asBinder());
290             mActionOnDeath.take(listener);
291         }
292     }
293 
CarPowerManagementService(Context context, PowerHalService powerHal, SystemInterface systemInterface, CarUserService carUserService, ICarPowerPolicySystemNotification powerPolicyDaemon)294     public CarPowerManagementService(Context context, PowerHalService powerHal,
295             SystemInterface systemInterface, CarUserService carUserService,
296             ICarPowerPolicySystemNotification powerPolicyDaemon) {
297         this(context, context.getResources(), powerHal, systemInterface,
298                 context.getSystemService(UserManager.class),
299                 carUserService, powerPolicyDaemon,
300                 new PowerComponentHandler(context, systemInterface),
301                 /* silentModeHwStatePath= */ null, /* silentModeKernelStatePath= */ null,
302                 /* bootReason= */ null);
303     }
304 
305     @VisibleForTesting
CarPowerManagementService(Context context, Resources resources, PowerHalService powerHal, SystemInterface systemInterface, UserManager userManager, CarUserService carUserService, ICarPowerPolicySystemNotification powerPolicyDaemon, PowerComponentHandler powerComponentHandler, @Nullable String silentModeHwStatePath, @Nullable String silentModeKernelStatePath, @Nullable String bootReason)306     public CarPowerManagementService(Context context, Resources resources, PowerHalService powerHal,
307             SystemInterface systemInterface, UserManager userManager, CarUserService carUserService,
308             ICarPowerPolicySystemNotification powerPolicyDaemon,
309             PowerComponentHandler powerComponentHandler, @Nullable String silentModeHwStatePath,
310             @Nullable String silentModeKernelStatePath, @Nullable String bootReason) {
311         mContext = context;
312         mHal = powerHal;
313         mSystemInterface = systemInterface;
314         mUserManager = userManager;
315         mShutdownPrepareTimeMs = resources.getInteger(
316                 R.integer.maxGarageModeRunningDurationInSecs) * 1000;
317         mSwitchGuestUserBeforeSleep = resources.getBoolean(
318                 R.bool.config_switchGuestUserBeforeGoingSleep);
319         if (mShutdownPrepareTimeMs < MIN_MAX_GARAGE_MODE_DURATION_MS) {
320             Slogf.w(TAG,
321                     "maxGarageModeRunningDurationInSecs smaller than minimum required, "
322                     + "resource:%d(ms) while should exceed:%d(ms), Ignore resource.",
323                     mShutdownPrepareTimeMs, MIN_MAX_GARAGE_MODE_DURATION_MS);
324             mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS;
325         }
326         mUserService = carUserService;
327         mCarPowerPolicyDaemon = powerPolicyDaemon;
328         if (powerPolicyDaemon != null) {
329             // For testing purpose
330             mHasControlOverDaemon = true;
331         }
332         mWifiManager = context.getSystemService(WifiManager.class);
333         mTetheringManager = mContext.getSystemService(TetheringManager.class);
334         mWifiStateFile = new AtomicFile(
335                 new File(mSystemInterface.getSystemCarDir(), WIFI_STATE_FILENAME));
336         mTetheringStateFile = new AtomicFile(
337                 new File(mSystemInterface.getSystemCarDir(), TETHERING_STATE_FILENAME));
338         mWifiAdjustmentForSuspend = isWifiAdjustmentForSuspendConfig();
339         mPowerComponentHandler = powerComponentHandler;
340         mSilentModeHandler = new SilentModeHandler(this, silentModeHwStatePath,
341                 silentModeKernelStatePath, bootReason);
342         mMaxSuspendWaitDurationMs = Math.max(MIN_SUSPEND_WAIT_DURATION_MS,
343                 Math.min(getMaxSuspendWaitDurationConfig(), MAX_SUSPEND_WAIT_DURATION_MS));
344     }
345 
346     /**
347      * Overrides timers to keep testing time short.
348      *
349      * <p>Passing in {@code 0} resets the value to the default.
350      */
351     @VisibleForTesting
setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs)352     public void setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs) {
353         synchronized (mLock) {
354             mShutdownPollingIntervalMs =
355                     (pollingIntervalMs == 0) ? SHUTDOWN_POLLING_INTERVAL_MS : pollingIntervalMs;
356             mShutdownPrepareTimeMs =
357                     (shutdownTimeoutMs == 0) ? SHUTDOWN_EXTEND_MAX_MS : shutdownTimeoutMs;
358         }
359     }
360 
361     @VisibleForTesting
getHandlerThread()362     protected HandlerThread getHandlerThread() {
363         return mHandlerThread;
364     }
365 
366     @Override
init()367     public void init() {
368         mPolicyReader.init();
369         mPowerComponentHandler.init();
370         mHal.setListener(this);
371         if (mHal.isPowerStateSupported()) {
372             // Initialize CPMS in WAIT_FOR_VHAL state
373             onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, CarPowerManager.STATE_WAIT_FOR_VHAL);
374         } else {
375             Slogf.w(TAG, "Vehicle hal does not support power state yet.");
376             onApPowerStateChange(CpmsState.ON, CarPowerManager.STATE_ON);
377         }
378         mSystemInterface.init(this, mUserService);
379         mSystemInterface.startDisplayStateMonitoring();
380         connectToPowerPolicyDaemon();
381     }
382 
383     @Override
release()384     public void release() {
385         if (mBinderHandler != null) {
386             mBinderHandler.unlinkToDeath();
387         }
388         synchronized (mLock) {
389             clearWaitingForCompletion(/*clearQueue=*/false);
390             mCurrentState = null;
391             mCarPowerPolicyDaemon = null;
392             mHandler.cancelAll();
393             mListenersWeAreWaitingFor.clear();
394         }
395         mSystemInterface.stopDisplayStateMonitoring();
396         mPowerManagerListeners.kill();
397         mPowerPolicyListeners.kill();
398         mSystemInterface.releaseAllWakeLocks();
399     }
400 
401     @Override
402     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dump(IndentingPrintWriter writer)403     public void dump(IndentingPrintWriter writer) {
404         synchronized (mLock) {
405             writer.println("*PowerManagementService*");
406             writer.printf("mCurrentState: %s\n", mCurrentState);
407             writer.printf("mShutdownStartTime: %d\n", mShutdownStartTime);
408             writer.printf("mLastSleepEntryTime: %d\n", mLastSleepEntryTime);
409             writer.printf("mNextWakeupSec: %d\n", mNextWakeupSec);
410             writer.printf("mShutdownOnNextSuspend: %b\n", mShutdownOnNextSuspend);
411             writer.printf("mActionOnFinish: %s\n", actionOnFinishToString(mActionOnFinish));
412             writer.printf("mShutdownPollingIntervalMs: %d\n", mShutdownPollingIntervalMs);
413             writer.printf("mShutdownPrepareTimeMs: %d\n", mShutdownPrepareTimeMs);
414             writer.printf("mRebootAfterGarageMode: %b\n", mRebootAfterGarageMode);
415             writer.printf("mSwitchGuestUserBeforeSleep: %b\n", mSwitchGuestUserBeforeSleep);
416             writer.printf("mCurrentPowerPolicyId: %s\n", mCurrentPowerPolicyId);
417             writer.printf("mPendingPowerPolicyId: %s\n", mPendingPowerPolicyId);
418             writer.printf("mCurrentPowerPolicyGroupId: %s\n", mCurrentPowerPolicyGroupId);
419             writer.printf("mIsPowerPolicyLocked: %b\n", mIsPowerPolicyLocked);
420             writer.printf("mMaxSuspendWaitDurationMs: %d\n", mMaxSuspendWaitDurationMs);
421             writer.printf("config_maxSuspendWaitDuration: %d\n", getMaxSuspendWaitDurationConfig());
422             writer.printf("mWifiStateFile: %s\n", mWifiStateFile);
423             writer.printf("mTetheringStateFile: %s\n", mTetheringStateFile);
424             writer.printf("mWifiAdjustmentForSuspend: %b\n", mWifiAdjustmentForSuspend);
425             writer.printf("# of power policy change listener: %d\n",
426                     mPowerPolicyListeners.getRegisteredCallbackCount());
427             writer.printf("mFactoryResetCallback: %s\n", mFactoryResetCallback);
428             writer.printf("mIsListenerWaitingCancelled: %b\n", mIsListenerWaitingCancelled.get());
429             writer.printf("kernel support S2R: %b\n",
430                     mSystemInterface.isSystemSupportingDeepSleep());
431             writer.printf("kernel support S2D: %b\n",
432                     mSystemInterface.isSystemSupportingHibernation());
433         }
434         mPolicyReader.dump(writer);
435         mPowerComponentHandler.dump(writer);
436         mSilentModeHandler.dump(writer);
437     }
438 
439     @Override
onApPowerStateChange(PowerState state)440     public void onApPowerStateChange(PowerState state) {
441         EventLogHelper.writeCarPowerManagerStateRequest(state.mState, state.mParam);
442         synchronized (mLock) {
443             mPendingPowerStates.addFirst(new CpmsState(state));
444             mLock.notify();
445         }
446         mHandler.handlePowerStateChange();
447     }
448 
449     @VisibleForTesting
setStateForWakeUp()450     void setStateForWakeUp() {
451         mSilentModeHandler.init();
452         synchronized (mLock) {
453             mIsBooting = false;
454         }
455         handleWaitForVhal(new CpmsState(CpmsState.WAIT_FOR_VHAL,
456                 CarPowerManager.STATE_WAIT_FOR_VHAL, /* canPostpone= */ false));
457         Slogf.d(TAG, "setStateForTesting(): mIsBooting is set to false and power state is switched "
458                 + "to Wait For Vhal");
459     }
460 
461     /**
462      * Initiate state change from CPMS directly.
463      */
onApPowerStateChange(int apState, @CarPowerManager.CarPowerState int carPowerStateListenerState)464     private void onApPowerStateChange(int apState,
465             @CarPowerManager.CarPowerState int carPowerStateListenerState) {
466         CpmsState newState = new CpmsState(apState, carPowerStateListenerState,
467                 /* canPostpone= */ false);
468         BiFunction<CpmsState, CpmsState, Boolean> eventFilter = null;
469 
470         // We are ready to shut down. Suppress this transition if
471         // there is a request to cancel the shutdown (WAIT_FOR_VHAL).
472         // Completely ignore this WAIT_FOR_FINISH
473         if (newState.mState == CpmsState.WAIT_FOR_FINISH) {
474             eventFilter = (stateToAdd, pendingSate) ->
475                     stateToAdd.mState == CpmsState.WAIT_FOR_FINISH
476                     && pendingSate.mState == CpmsState.WAIT_FOR_VHAL;
477         }
478 
479         // Check if there is another pending SHUTDOWN_PREPARE.
480         // This could happen, when another SHUTDOWN_PREPARE request is received from VHAL
481         // while notifying PRE_SHUTDOWN_PREPARE.
482         // If SHUTDOWN_PREPARE request already exist in the queue, and it skips Garage Mode,
483         // then newState is ignored .
484         if (newState.mState == CpmsState.SHUTDOWN_PREPARE) {
485             eventFilter = (stateToAdd, pendingState) ->
486                     pendingState.mState == CpmsState.SHUTDOWN_PREPARE
487                             && !pendingState.mCanPostpone
488                             && pendingState.mCarPowerStateListenerState
489                             == STATE_PRE_SHUTDOWN_PREPARE;
490         }
491 
492         synchronized (mLock) {
493             // If eventFilter exists, lets check if event that satisfies filter is in queue.
494             if (eventFilter != null) {
495                 for (int idx = 0; idx < mPendingPowerStates.size(); idx++) {
496                     CpmsState pendingState = mPendingPowerStates.get(idx);
497                     if (eventFilter.apply(newState, pendingState)) {
498                         return;
499                     }
500                 }
501             }
502             mPendingPowerStates.addFirst(newState);
503             mLock.notify();
504         }
505         mHandler.handlePowerStateChange();
506     }
507 
doHandlePowerStateChange()508     private void doHandlePowerStateChange() {
509         CpmsState newState;
510         CpmsState prevState;
511         synchronized (mLock) {
512             prevState = mCurrentState;
513             newState = mPendingPowerStates.pollFirst();
514             if (newState == null) {
515                 Slogf.w(TAG, "No more power state to process");
516                 return;
517             }
518             Slogf.i(TAG, "doHandlePowerStateChange: newState=%s", newState.name());
519             if (!needPowerStateChangeLocked(newState)) {
520                 // We may need to process the pending power state request.
521                 if (!mPendingPowerStates.isEmpty()) {
522                     Slogf.i(TAG, "There is a pending power state change request. requesting the "
523                             + "processing...");
524                     mHandler.handlePowerStateChange();
525                 }
526                 return;
527             }
528 
529             // now real power change happens. Whatever was queued before should be all cancelled.
530             mPendingPowerStates.clear();
531 
532             // Received updated SHUTDOWN_PREPARE there could be several reasons for that
533             //  1. CPMS is in SHUTDOWN_PREPARE, and received state change to perform transition
534             //     from PRE_SHUTDOWN_PREPARE into SHUTDOWN_PREPARE
535             //  2. New SHUTDOWN_PREPARE request is received, and it is different from existing one.
536             if (newState.mState == CpmsState.SHUTDOWN_PREPARE && newState.mState == prevState.mState
537                     && newState.mCarPowerStateListenerState == STATE_PRE_SHUTDOWN_PREPARE) {
538                 // Nothing to do here, skipping clearing completion queue
539             } else {
540                 clearWaitingForCompletion(/*clearQueue=*/false);
541             }
542 
543             mCurrentState = newState;
544         }
545         mHandler.cancelProcessingComplete();
546 
547         Slogf.i(TAG, "setCurrentState %s", newState);
548         CarStatsLogHelper.logPowerState(newState.mState);
549         EventLogHelper.writeCarPowerManagerStateChange(newState.mState);
550         switch (newState.mState) {
551             case CpmsState.WAIT_FOR_VHAL:
552                 handleWaitForVhal(newState);
553                 break;
554             case CpmsState.ON:
555                 handleOn();
556                 break;
557             case CpmsState.SHUTDOWN_PREPARE:
558                 handleShutdownPrepare(newState, prevState);
559                 break;
560             case CpmsState.SIMULATE_SLEEP:
561             case CpmsState.SIMULATE_HIBERNATION:
562                 simulateShutdownPrepare(newState, prevState);
563                 break;
564             case CpmsState.WAIT_FOR_FINISH:
565                 handleWaitForFinish(newState);
566                 break;
567             case CpmsState.SUSPEND:
568                 // Received FINISH from VHAL
569                 handleFinish();
570                 break;
571             default:
572                 // Illegal state
573                 // TODO(b/202414427): Add handling of illegal state
574                 break;
575         }
576     }
577 
handleWaitForVhal(CpmsState state)578     private void handleWaitForVhal(CpmsState state) {
579         @CarPowerManager.CarPowerState int carPowerStateListenerState =
580                 state.mCarPowerStateListenerState;
581         // TODO(b/177478420): Restore Wifi, Audio, Location, and Bluetooth, if they are artificially
582         // modified for S2R.
583         mSilentModeHandler.querySilentModeHwState();
584 
585         applyDefaultPowerPolicyForState(CarPowerManager.STATE_WAIT_FOR_VHAL,
586                     PolicyReader.POWER_POLICY_ID_INITIAL_ON);
587 
588         if (!mSilentModeHandler.isSilentMode()) {
589             cancelPreemptivePowerPolicy();
590         }
591 
592         sendPowerManagerEvent(carPowerStateListenerState, INVALID_TIMEOUT);
593         // Inspect CarPowerStateListenerState to decide which message to send via VHAL
594         switch (carPowerStateListenerState) {
595             case CarPowerManager.STATE_WAIT_FOR_VHAL:
596                 mHal.sendWaitForVhal();
597                 break;
598             case CarPowerManager.STATE_SHUTDOWN_CANCELLED:
599                 synchronized (mLock) {
600                     mShutdownOnNextSuspend = false; // This cancels the "NextSuspend"
601                 }
602                 mHal.sendShutdownCancel();
603                 break;
604             case CarPowerManager.STATE_SUSPEND_EXIT:
605                 mHal.sendSleepExit();
606                 break;
607             case CarPowerManager.STATE_HIBERNATION_EXIT:
608                 mHal.sendHibernationExit();
609                 break;
610         }
611         if (mWifiAdjustmentForSuspend) {
612             restoreWifiFully();
613         }
614     }
615 
updateCarUserNoticeServiceIfNecessary()616     private void updateCarUserNoticeServiceIfNecessary() {
617         try {
618             int currentUserId = ActivityManager.getCurrentUser();
619             UserHandleHelper userHandleHelper = new UserHandleHelper(mContext, mUserManager);
620             UserHandle currentUser = userHandleHelper.getExistingUserHandle(currentUserId);
621             CarUserNoticeService carUserNoticeService =
622                     CarLocalServices.getService(CarUserNoticeService.class);
623             if (currentUser != null && userHandleHelper.isGuestUser(currentUser)
624                     && carUserNoticeService != null) {
625                 Slogf.i(TAG, "Car user notice service will ignore all messages before user "
626                         + "switch.");
627                 Intent intent = new Intent();
628                 intent.setComponent(ComponentName.unflattenFromString(
629                         mContext.getResources().getString(R.string.continuousBlankActivity)));
630                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
631                 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
632                 carUserNoticeService.ignoreUserNotice(currentUserId);
633             }
634         } catch (Exception e) {
635             Slogf.w(TAG, e, "Cannot ignore user notice for current user");
636         }
637     }
638 
639     @VisibleForTesting
handleOn()640     void handleOn() {
641         if (factoryResetIfNeeded()) return;
642 
643         // If current user is a Guest User, we want to inform CarUserNoticeService not to show
644         // notice for current user, and show user notice only for the target user.
645         if (!mSwitchGuestUserBeforeSleep) {
646             updateCarUserNoticeServiceIfNecessary();
647         }
648 
649         if (!mSilentModeHandler.isSilentMode()) {
650             cancelPreemptivePowerPolicy();
651         }
652         applyDefaultPowerPolicyForState(VehicleApPowerStateReport.ON,
653                 PolicyReader.POWER_POLICY_ID_ALL_ON);
654 
655         sendPowerManagerEvent(CarPowerManager.STATE_ON, INVALID_TIMEOUT);
656 
657         mHal.sendOn();
658 
659         synchronized (mLock) {
660             if (mIsBooting) {
661                 Slogf.d(TAG, "handleOn(): called on boot");
662                 mIsBooting = false;
663                 return;
664             }
665         }
666 
667         try {
668             mUserService.onResume();
669         } catch (Exception e) {
670             Slogf.e(TAG, e, "Could not switch user on resume");
671         }
672     }
673 
factoryResetIfNeeded()674     private boolean factoryResetIfNeeded() {
675         ICarResultReceiver callback;
676         synchronized (mLock) {
677             if (mFactoryResetCallback == null) return false;
678             callback = mFactoryResetCallback;
679         }
680 
681         try {
682             Slogf.i(TAG, "Factory resetting as it was delayed by user");
683             callback.send(/* resultCode= */ 0, /* resultData= */ null);
684             return true;
685         } catch (Exception e) {
686             Slogf.wtf(TAG, e, "Should have factory reset, but failed");
687             return false;
688         }
689     }
690 
applyDefaultPowerPolicyForState(@arPowerManager.CarPowerState int state, @Nullable String fallbackPolicyId)691     private void applyDefaultPowerPolicyForState(@CarPowerManager.CarPowerState int state,
692             @Nullable String fallbackPolicyId) {
693         Slogf.i(TAG, "Applying the default power policy for %s (fallback policy = %s)",
694                 powerStateToString(state), fallbackPolicyId);
695         CarPowerPolicy policy;
696         synchronized (mLock) {
697             policy = mPolicyReader
698                     .getDefaultPowerPolicyForState(mCurrentPowerPolicyGroupId, state);
699         }
700         if (policy == null && fallbackPolicyId == null) {
701             Slogf.w(TAG, "No default power policy for %s is found", powerStateToString(state));
702             return;
703         }
704         String policyId = policy == null ? fallbackPolicyId : policy.getPolicyId();
705         applyPowerPolicy(policyId, /* delayNotification= */ false, /* upToDaemon= */ true,
706                 /* force= */ false);
707     }
708 
709     /**
710      * Sets the callback used to factory reset the device on resume when the user delayed it.
711      */
setFactoryResetCallback(ICarResultReceiver callback)712     public void setFactoryResetCallback(ICarResultReceiver callback) {
713         synchronized (mLock) {
714             mFactoryResetCallback = callback;
715         }
716     }
717 
718     /**
719      * Tells Garage Mode if it should run normally, or just
720      * exit immediately without indicating 'idle'
721      * @return True if no idle jobs should be run
722      * @hide
723      */
garageModeShouldExitImmediately()724     public boolean garageModeShouldExitImmediately() {
725         synchronized (mLock) {
726             return mGarageModeShouldExitImmediately;
727         }
728     }
729 
handleShutdownPrepare(CpmsState currentState, CpmsState prevState)730     private void handleShutdownPrepare(CpmsState currentState, CpmsState prevState) {
731         switch (currentState.mCarPowerStateListenerState) {
732             case CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE:
733                 updateShutdownPrepareStatus(currentState);
734                 if (prevState.mCarPowerStateListenerState == STATE_SHUTDOWN_PREPARE) {
735                     // Received request to update SHUTDOWN target
736                     currentState = new CpmsState(currentState.mState,
737                             prevState.mCarPowerStateListenerState,
738                             prevState.mCanPostpone, currentState.mShutdownType);
739                     synchronized (mLock) {
740                         mCurrentState = currentState;
741                     }
742                     clearWaitingForCompletion(/*clearQueue=*/true);
743                 } else if (prevState.mCarPowerStateListenerState == STATE_PRE_SHUTDOWN_PREPARE) {
744                     // Update of state occurred while in PRE_SHUTDOWN_PREPARE
745                     boolean areListenersEmpty;
746                     synchronized (mLock) {
747                         areListenersEmpty = mListenersWeAreWaitingFor.isEmpty();
748                     }
749                     if (areListenersEmpty) {
750                         handleCoreShutdownPrepare();
751                     } else {
752                         // PRE_SHUTDOWN_PREPARE is still being processed, no actions required
753                         return;
754                     }
755                 } else {
756                     handlePreShutdownPrepare();
757                 }
758                 break;
759             case CarPowerManager.STATE_SHUTDOWN_PREPARE:
760                 handleCoreShutdownPrepare();
761                 break;
762             default:
763                 Slogf.w(TAG, "Not supported listener state(%d)",
764                         currentState.mCarPowerStateListenerState);
765         }
766     }
767 
updateShutdownPrepareStatus(CpmsState newState)768     private void updateShutdownPrepareStatus(CpmsState newState) {
769         // Shutdown on finish if the system doesn't support deep sleep/hibernation
770         // or doesn't allow it.
771         int intervalMs;
772         synchronized (mLock) {
773             if (mShutdownOnNextSuspend
774                     || newState.mShutdownType == PowerState.SHUTDOWN_TYPE_POWER_OFF) {
775                 mActionOnFinish = ACTION_ON_FINISH_SHUTDOWN;
776             } else if (newState.mShutdownType == PowerState.SHUTDOWN_TYPE_DEEP_SLEEP) {
777                 boolean isDeepSleepOnFinish =
778                         isDeepSleepAvailable() || newState.mState == CpmsState.SIMULATE_SLEEP;
779                 mActionOnFinish = isDeepSleepOnFinish ? ACTION_ON_FINISH_DEEP_SLEEP
780                         : ACTION_ON_FINISH_SHUTDOWN;
781             } else if (newState.mShutdownType == PowerState.SHUTDOWN_TYPE_HIBERNATION) {
782                 boolean isHibernationOnFinish = isHibernationAvailable()
783                         || newState.mState == CpmsState.SIMULATE_HIBERNATION;
784                 mActionOnFinish = isHibernationOnFinish ? ACTION_ON_FINISH_HIBERNATION
785                         : ACTION_ON_FINISH_SHUTDOWN;
786             } else {
787                 Slogf.wtf(TAG, "handleShutdownPrepare - incorrect state " + newState);
788             }
789             mGarageModeShouldExitImmediately = !newState.mCanPostpone;
790             intervalMs = mShutdownPollingIntervalMs;
791         }
792     }
793 
handlePreShutdownPrepare()794     private void handlePreShutdownPrepare() {
795         int intervalMs;
796         synchronized (mLock) {
797             intervalMs = mShutdownPollingIntervalMs;
798             Slogf.i(TAG,
799                     mGarageModeShouldExitImmediately ? "starting shutdown prepare with Garage Mode"
800                             : "starting shutdown prepare without Garage Mode");
801         }
802 
803         long timeoutMs = getPreShutdownPrepareTimeoutConfig();
804         int state = CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE;
805         sendPowerManagerEvent(state, timeoutMs);
806         Runnable taskAtCompletion = () -> {
807             // The next power state is still SHUTDOWN_PREPARE, and the listener state is
808             // SHUTDOW_PREPARE.
809             Slogf.i(TAG, "All listeners completed for %s", powerStateToString(state));
810             onApPowerStateChange(CpmsState.SHUTDOWN_PREPARE,
811                     CarPowerManager.STATE_SHUTDOWN_PREPARE);
812         };
813 
814         waitForCompletionWithShutdownPostpone(state, timeoutMs, taskAtCompletion, intervalMs);
815     }
816 
handleCoreShutdownPrepare()817     private void handleCoreShutdownPrepare() {
818         Slogf.i(TAG, "Handling core part of shutdown prepare");
819         doShutdownPrepare();
820     }
821 
822     // Simulates system shutdown to suspend
simulateShutdownPrepare(CpmsState newState, CpmsState oldState)823     private void simulateShutdownPrepare(CpmsState newState, CpmsState oldState) {
824         Slogf.i(TAG, "Simulating shutdown prepare");
825         handleShutdownPrepare(newState, oldState);
826     }
827 
doShutdownPrepare()828     private void doShutdownPrepare() {
829         long timeoutMs;
830         long intervalMs;
831         synchronized (mLock) {
832             timeoutMs = mShutdownPrepareTimeMs;
833             intervalMs = mShutdownPollingIntervalMs;
834             mShutdownStartTime = SystemClock.elapsedRealtime();
835         }
836         if (BuildHelper.isUserDebugBuild() || BuildHelper.isEngBuild()) {
837             int shutdownPrepareTimeOverrideInSecs =
838                     SystemProperties.getInt(PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE, -1);
839             if (shutdownPrepareTimeOverrideInSecs >= 0) {
840                 timeoutMs = shutdownPrepareTimeOverrideInSecs * 1000L;
841             }
842         }
843         makeSureNoUserInteraction();
844         sendPowerManagerEvent(CarPowerManager.STATE_SHUTDOWN_PREPARE, timeoutMs);
845         mHal.sendShutdownPrepare();
846         waitForShutdownPrepareListenersToComplete(timeoutMs, intervalMs);
847     }
848 
handleWaitForFinish(CpmsState state)849     private void handleWaitForFinish(CpmsState state) {
850         int timeoutMs = getShutdownEnterTimeoutConfig();
851         sendPowerManagerEvent(state.mCarPowerStateListenerState, timeoutMs);
852         Runnable taskAtCompletion = () -> {
853             Slogf.i(TAG, "All listeners completed for %s",
854                     powerStateToString(state.mCarPowerStateListenerState));
855             int wakeupSec;
856             synchronized (mLock) {
857                 // If we're shutting down immediately, don't schedule a wakeup time.
858                 wakeupSec = mGarageModeShouldExitImmediately ? 0 : mNextWakeupSec;
859             }
860             switch (state.mCarPowerStateListenerState) {
861                 case CarPowerManager.STATE_SUSPEND_ENTER:
862                     mHal.sendSleepEntry(wakeupSec);
863                     break;
864                 case CarPowerManager.STATE_SHUTDOWN_ENTER:
865                     mHal.sendShutdownStart(wakeupSec);
866                     break;
867                 case CarPowerManager.STATE_HIBERNATION_ENTER:
868                     mHal.sendHibernationEntry(wakeupSec);
869                     break;
870             }
871         };
872 
873         int intervalMs;
874         synchronized (mLock) {
875             intervalMs = mShutdownPollingIntervalMs;
876         }
877 
878         waitForCompletionWithShutdownPostpone(state.mCarPowerStateListenerState, timeoutMs,
879                 taskAtCompletion, intervalMs);
880     }
881 
handleFinish()882     private void handleFinish() {
883         int listenerState;
884         synchronized (mLock) {
885             switch (mActionOnFinish) {
886                 case ACTION_ON_FINISH_SHUTDOWN:
887                     listenerState = CarPowerManager.STATE_POST_SHUTDOWN_ENTER;
888                     break;
889                 case ACTION_ON_FINISH_DEEP_SLEEP:
890                     listenerState = CarPowerManager.STATE_POST_SUSPEND_ENTER;
891                     break;
892                 case ACTION_ON_FINISH_HIBERNATION:
893                     listenerState = CarPowerManager.STATE_POST_HIBERNATION_ENTER;
894                     break;
895                 default:
896                     Slogf.w(TAG, "Invalid action on finish: %d", mActionOnFinish);
897                     return;
898             }
899         }
900         int timeoutMs = getPostShutdownEnterTimeoutConfig();
901         sendPowerManagerEvent(listenerState, timeoutMs);
902         Runnable taskAtCompletion = () -> {
903             Slogf.i(TAG, "All listeners completed for %s", powerStateToString(listenerState));
904             doHandleFinish();
905         };
906         Slogf.i(TAG, "Start waiting for listener completion for %s",
907                 powerStateToString(listenerState));
908         waitForCompletion(taskAtCompletion, /* taskAtInterval= */ null, timeoutMs,
909                 /* intervalMs= */ -1);
910     }
911 
doHandleFinish()912     private void doHandleFinish() {
913         boolean simulatedMode;
914         synchronized (mSimulationWaitObject) {
915             simulatedMode = mInSimulatedDeepSleepMode;
916         }
917         boolean mustShutDown;
918         boolean forceReboot;
919         synchronized (mLock) {
920             mustShutDown = (mActionOnFinish == ACTION_ON_FINISH_SHUTDOWN) && !simulatedMode;
921             forceReboot = mRebootAfterGarageMode;
922             mRebootAfterGarageMode = false;
923         }
924         if (forceReboot) {
925             PowerManager powerManager = mContext.getSystemService(PowerManager.class);
926             if (powerManager == null) {
927                 Slogf.wtf(TAG, "No PowerManager. Cannot reboot.");
928             } else {
929                 Slogf.i(TAG, "GarageMode has completed. Forcing reboot.");
930                 powerManager.reboot("GarageModeReboot");
931                 throw new AssertionError("Should not return from PowerManager.reboot()");
932             }
933         }
934         // To make Kernel implementation simpler when going into sleep.
935         if (mWifiAdjustmentForSuspend) {
936             disableWifiFully();
937         }
938 
939         if (mustShutDown) {
940             // shutdown HU
941             mSystemInterface.shutdown();
942         } else {
943             doHandleDeepSleep(simulatedMode);
944         }
945         synchronized (mLock) {
946             mShutdownOnNextSuspend = false;
947         }
948     }
949 
disableWifiFully()950     private void disableWifiFully() {
951         disableWifi();
952         disableTethering();
953     }
954 
restoreWifiFully()955     private void restoreWifiFully() {
956         restoreTethering();
957         restoreWifi();
958     }
959 
restoreWifi()960     private void restoreWifi() {
961         boolean needToRestore = readWifiModifiedState(mWifiStateFile);
962         if (!needToRestore) return;
963         if (!mWifiManager.isWifiEnabled()) {
964             Slogf.i(TAG, "Wifi has been enabled to restore the last setting");
965             mWifiManager.setWifiEnabled(true);
966         }
967         // Update the persistent data as wifi is not modified by car framework.
968         saveWifiModifiedState(mWifiStateFile, /* forciblyDisabled= */ false);
969     }
970 
disableWifi()971     private void disableWifi() {
972         boolean wifiEnabled = mWifiManager.isWifiEnabled();
973         boolean wifiModifiedState = readWifiModifiedState(mWifiStateFile);
974         if (wifiEnabled != wifiModifiedState) {
975             Slogf.i(TAG, "Saving the current Wifi state");
976             saveWifiModifiedState(mWifiStateFile, wifiEnabled);
977         }
978 
979         // In some devices, enabling a tether temporarily turns off Wifi. To make sure that Wifi is
980         // disabled, we call this method in all cases.
981         mWifiManager.setWifiEnabled(false);
982         Slogf.i(TAG, "Wifi has been disabled and the last setting was saved");
983     }
984 
restoreTethering()985     private void restoreTethering() {
986         boolean needToRestore = readWifiModifiedState(mTetheringStateFile);
987         if (!needToRestore) return;
988         if (!mWifiManager.isWifiApEnabled()) {
989             Slogf.i(TAG, "Tethering has been enabled to restore the last setting");
990             startTethering();
991         }
992         // Update the persistent data as wifi is not modified by car framework.
993         saveWifiModifiedState(mTetheringStateFile, /*forciblyDisabled= */ false);
994     }
995 
disableTethering()996     private void disableTethering() {
997         boolean tetheringEnabled = mWifiManager.isWifiApEnabled();
998         boolean tetheringModifiedState = readWifiModifiedState(mTetheringStateFile);
999         if (tetheringEnabled != tetheringModifiedState) {
1000             Slogf.i(TAG, "Saving the current tethering state: tetheringEnabled=%b",
1001                     tetheringEnabled);
1002             saveWifiModifiedState(mTetheringStateFile, tetheringEnabled);
1003         }
1004         if (!tetheringEnabled) return;
1005 
1006         mTetheringManager.stopTethering(TETHERING_WIFI);
1007         Slogf.i(TAG, "Tethering has been disabled and the last setting was saved");
1008     }
1009 
saveWifiModifiedState(AtomicFile file, boolean forciblyDisabled)1010     private void saveWifiModifiedState(AtomicFile file, boolean forciblyDisabled) {
1011         FileOutputStream fos;
1012         try {
1013             fos = file.startWrite();
1014         } catch (IOException e) {
1015             Slogf.e(TAG, e, "Cannot create %s", file);
1016             return;
1017         }
1018 
1019         try (BufferedWriter writer = new BufferedWriter(
1020                 new OutputStreamWriter(fos, StandardCharsets.UTF_8))) {
1021             writer.write(forciblyDisabled ? COMPONENT_STATE_MODIFIED : COMPONENT_STATE_ORIGINAL);
1022             writer.newLine();
1023             writer.flush();
1024             file.finishWrite(fos);
1025         } catch (IOException e) {
1026             file.failWrite(fos);
1027             Slogf.e(TAG, e, "Writing %s failed", file);
1028         }
1029     }
1030 
readWifiModifiedState(AtomicFile file)1031     private boolean readWifiModifiedState(AtomicFile file) {
1032         boolean needToRestore = false;
1033         boolean invalidState = false;
1034 
1035         try (BufferedReader reader = new BufferedReader(
1036                 new InputStreamReader(file.openRead(), StandardCharsets.UTF_8))) {
1037             String line = reader.readLine();
1038             if (line == null) {
1039                 needToRestore = false;
1040                 invalidState = true;
1041             } else {
1042                 line = line.trim();
1043                 needToRestore = COMPONENT_STATE_MODIFIED.equals(line);
1044                 invalidState = !(needToRestore || COMPONENT_STATE_ORIGINAL.equals(line));
1045             }
1046         } catch (IOException e) {
1047             // If a file named wifi_state doesn't exist, we will not modify Wifi at system start.
1048             Slogf.w(TAG, "Failed to read %s: %s", file, e);
1049             return false;
1050         }
1051         if (invalidState) {
1052             file.delete();
1053         }
1054 
1055         return needToRestore;
1056     }
1057 
startTethering()1058     private void startTethering() {
1059         TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
1060                 .setShouldShowEntitlementUi(false).build();
1061         mTetheringManager.startTethering(request, mContext.getMainExecutor(),
1062                 new TetheringManager.StartTetheringCallback() {
1063                     @Override
1064                     public void onTetheringFailed(int error) {
1065                         Slogf.w(TAG, "Starting tethering failed: %d", error);
1066                     }
1067                 });
1068     }
1069 
waitForShutdownPrepareListenersToComplete(long timeoutMs, long intervalMs)1070     private void waitForShutdownPrepareListenersToComplete(long timeoutMs, long intervalMs) {
1071         int state = CarPowerManager.STATE_SHUTDOWN_PREPARE;
1072         Runnable taskAtCompletion = () -> {
1073             finishShutdownPrepare();
1074             Slogf.i(TAG, "All listeners completed for %s", powerStateToString(state));
1075         };
1076 
1077         waitForCompletionWithShutdownPostpone(state, timeoutMs, taskAtCompletion, intervalMs);
1078 
1079         // allowUserSwitch value doesn't matter for onSuspend = true
1080         mUserService.onSuspend();
1081     }
1082 
waitForCompletion(Runnable taskAtCompletion, Runnable taskAtInterval, long timeoutMs, long intervalMs)1083     private void waitForCompletion(Runnable taskAtCompletion, Runnable taskAtInterval,
1084             long timeoutMs, long intervalMs) {
1085         boolean isComplete = false;
1086         synchronized (mLock) {
1087             isComplete = mListenersWeAreWaitingFor.isEmpty();
1088         }
1089         if (isComplete) {
1090             taskAtCompletion.run();
1091         } else {
1092             // Reset a flag to signal that waiting for completion is cancelled.
1093             mIsListenerWaitingCancelled.set(false);
1094             waitForCompletionAsync(taskAtCompletion, taskAtInterval, timeoutMs, intervalMs);
1095         }
1096     }
1097 
1098     // Waits for listeners to complete.
1099     // If {@code intervalMs} is non-positive value, it is ignored and the method waits up to
1100     // {@code timeoutMs}.
waitForCompletionAsync(Runnable taskAtCompletion, Runnable taskAtInterval, long timeoutMs, long intervalMs)1101     private void waitForCompletionAsync(Runnable taskAtCompletion, Runnable taskAtInterval,
1102             long timeoutMs, long intervalMs) {
1103         ExecutorService executor = Executors.newSingleThreadExecutor();
1104         executor.submit(() -> {
1105             long startTimeMs = SystemClock.elapsedRealtime();
1106             while (true) {
1107                 try {
1108                     long waitTimeMs = timeoutMs - (SystemClock.elapsedRealtime() - startTimeMs);
1109                     boolean isLastWait = true;
1110                     if (intervalMs > 0 && waitTimeMs > intervalMs) {
1111                         isLastWait = false;
1112                         waitTimeMs = intervalMs;
1113                     }
1114                     boolean isNotified = mListenerCompletionSem.tryAcquire(waitTimeMs,
1115                             TimeUnit.MILLISECONDS);
1116                     mListenerCompletionSem.drainPermits();
1117                     if (!isNotified) {
1118                         if (isLastWait) {
1119                             Slogf.w(TAG, "Waiting for listener completion is timeout(%d)",
1120                                     waitTimeMs);
1121                             taskAtCompletion.run();
1122                             return;
1123                         } else if (taskAtInterval != null) {
1124                             taskAtInterval.run();
1125                         }
1126                     }
1127                     boolean isComplete = false;
1128                     synchronized (mLock) {
1129                         if (mIsListenerWaitingCancelled.get()) {
1130                             Slogf.i(TAG, "Waiting for listener completion is cancelled");
1131                             mIsListenerWaitingCancelled.set(false);
1132                             return;
1133                         }
1134                         isComplete = mListenersWeAreWaitingFor.isEmpty();
1135                     }
1136                     if (isComplete) {
1137                         Slogf.i(TAG, "All listeners completed");
1138                         taskAtCompletion.run();
1139                         mIsListenerWaitingCancelled.set(false);
1140                         return;
1141                     }
1142                 } catch (InterruptedException e) {
1143                     Slogf.w(TAG, e, "Thread interrupted while waiting for listener completion");
1144                     Thread.currentThread().interrupt();
1145                 }
1146             }
1147         });
1148         executor.shutdown();
1149     }
1150 
clearWaitingForCompletion(boolean clearQueue)1151     private void clearWaitingForCompletion(boolean clearQueue) {
1152         if (clearQueue) {
1153             synchronized (mLock) {
1154                 mListenersWeAreWaitingFor.clear();
1155             }
1156         } else {
1157             mIsListenerWaitingCancelled.set(true);
1158         }
1159 
1160         mListenerCompletionSem.release();
1161     }
1162 
sendPowerManagerEvent(@arPowerManager.CarPowerState int newState, long timeoutMs)1163     private void sendPowerManagerEvent(@CarPowerManager.CarPowerState int newState,
1164             long timeoutMs) {
1165         // Broadcasts to the listeners that do not signal completion.
1166         notifyListeners(mPowerManagerListeners, newState, INVALID_TIMEOUT);
1167 
1168         boolean allowCompletion = false;
1169         boolean isShutdownPrepare = newState == CarPowerManager.STATE_SHUTDOWN_PREPARE;
1170         long internalListenerExpirationTimeMs = INVALID_TIMEOUT;
1171         long binderListenerExpirationTimeMs = INVALID_TIMEOUT;
1172 
1173         // Fully populates mListenersWeAreWaitingFor before calling any onStateChanged()
1174         // for the listeners that signal completion.
1175         // Otherwise, if the first listener calls finish() synchronously, we will
1176         // see the list go empty and we will think that we are done.
1177         PowerManagerCallbackList<ICarPowerStateListener> completingInternalListeners =
1178                 new PowerManagerCallbackList(l -> { });
1179         PowerManagerCallbackList<ICarPowerStateListener> completingBinderListeners =
1180                 new PowerManagerCallbackList(l -> { });
1181         synchronized (mLock) {
1182             if (isCompletionAllowed(newState)) {
1183                 if (timeoutMs < 0) {
1184                     Slogf.wtf(TAG, "Completion timeout(%d) for state(%d) should be "
1185                             + "non-negative", timeoutMs, newState);
1186                     return;
1187                 }
1188                 mStateForCompletion = newState;
1189                 allowCompletion = true;
1190                 internalListenerExpirationTimeMs = SystemClock.elapsedRealtime() + timeoutMs;
1191                 binderListenerExpirationTimeMs =
1192                         isShutdownPrepare ? INVALID_TIMEOUT : internalListenerExpirationTimeMs;
1193             } else {
1194                 mStateForCompletion = CarPowerManager.STATE_INVALID;
1195             }
1196 
1197             mListenersWeAreWaitingFor.clear();
1198             for (int i = 0; i < mInternalPowerListeners.size(); i++) {
1199                 ICarPowerStateListener listener = mInternalPowerListeners.get(i);
1200                 completingInternalListeners.register(listener);
1201                 if (allowCompletion) {
1202                     mListenersWeAreWaitingFor.add(listener.asBinder());
1203                 }
1204             }
1205             int idx = mPowerManagerListenersWithCompletion.beginBroadcast();
1206             while (idx-- > 0) {
1207                 ICarPowerStateListener listener =
1208                         mPowerManagerListenersWithCompletion.getBroadcastItem(idx);
1209                 completingBinderListeners.register(listener);
1210                 // For binder listeners, listener completion is not allowed for SHUTDOWN_PREPARE.
1211                 if (allowCompletion && !isShutdownPrepare) {
1212                     mListenersWeAreWaitingFor.add(listener.asBinder());
1213                 }
1214             }
1215             mPowerManagerListenersWithCompletion.finishBroadcast();
1216         }
1217         // Resets the semaphore's available permits to 0.
1218         mListenerCompletionSem.drainPermits();
1219         // Broadcasts to the listeners that DO signal completion.
1220         notifyListeners(completingInternalListeners, newState, internalListenerExpirationTimeMs);
1221         notifyListeners(completingBinderListeners, newState, binderListenerExpirationTimeMs);
1222     }
1223 
notifyListeners(PowerManagerCallbackList<ICarPowerStateListener> listenerList, @CarPowerManager.CarPowerState int newState, long expirationTimeMs)1224     private void notifyListeners(PowerManagerCallbackList<ICarPowerStateListener> listenerList,
1225             @CarPowerManager.CarPowerState int newState, long expirationTimeMs) {
1226         int idx = listenerList.beginBroadcast();
1227         while (idx-- > 0) {
1228             ICarPowerStateListener listener = listenerList.getBroadcastItem(idx);
1229             try {
1230                 listener.onStateChanged(newState, expirationTimeMs);
1231             } catch (RemoteException e) {
1232                 // It's likely the connection snapped. Let binder death handle the situation.
1233                 Slogf.e(TAG, e, "onStateChanged() call failed");
1234             }
1235         }
1236         listenerList.finishBroadcast();
1237     }
1238 
doHandleDeepSleep(boolean simulatedMode)1239     private void doHandleDeepSleep(boolean simulatedMode) {
1240         int status = applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_SUSPEND_PREP);
1241         if (status != PolicyOperationStatus.OK) {
1242             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
1243         }
1244         // Keeps holding partial wakelock to prevent entering sleep before enterDeepSleep call.
1245         // enterDeepSleep should force sleep entry even if wake lock is kept.
1246         mSystemInterface.switchToPartialWakeLock();
1247         mHandler.cancelProcessingComplete();
1248         synchronized (mLock) {
1249             mLastSleepEntryTime = SystemClock.elapsedRealtime();
1250         }
1251         @CarPowerManager.CarPowerState int nextListenerState;
1252         if (simulatedMode) {
1253             simulateSleepByWaiting();
1254             nextListenerState = CarPowerManager.STATE_SHUTDOWN_CANCELLED;
1255         } else {
1256             boolean sleepSucceeded = suspendWithRetries();
1257             if (!sleepSucceeded) {
1258                 // Suspend failed and we shut down instead.
1259                 // We either won't get here at all or we will power off very soon.
1260                 return;
1261             }
1262             synchronized (mLock) {
1263                 // We suspended and have now resumed
1264                 nextListenerState = (mActionOnFinish == ACTION_ON_FINISH_DEEP_SLEEP)
1265                         ? CarPowerManager.STATE_SUSPEND_EXIT
1266                         : CarPowerManager.STATE_HIBERNATION_EXIT;
1267             }
1268         }
1269         synchronized (mLock) {
1270             // Any wakeup time from before is no longer valid.
1271             mNextWakeupSec = 0;
1272         }
1273         Slogf.i(TAG, "Resuming after suspending");
1274         mSystemInterface.refreshDisplayBrightness();
1275         onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, nextListenerState);
1276     }
1277 
1278     @GuardedBy("mLock")
needPowerStateChangeLocked(@onNull CpmsState newState)1279     private boolean needPowerStateChangeLocked(@NonNull CpmsState newState) {
1280         if (mCurrentState == null) {
1281             return true;
1282         } else if (mCurrentState.equals(newState)) {
1283             Slogf.d(TAG, "Requested state is already in effect: %s", newState.name());
1284             return false;
1285         }
1286 
1287         // The following switch/case enforces the allowed state transitions.
1288         boolean transitionAllowed = false;
1289         switch (mCurrentState.mState) {
1290             case CpmsState.WAIT_FOR_VHAL:
1291                 transitionAllowed = (newState.mState == CpmsState.ON)
1292                     || (newState.mState == CpmsState.SHUTDOWN_PREPARE);
1293                 break;
1294             case CpmsState.SUSPEND:
1295                 transitionAllowed = newState.mState == CpmsState.WAIT_FOR_VHAL;
1296                 break;
1297             case CpmsState.ON:
1298                 transitionAllowed = (newState.mState == CpmsState.SHUTDOWN_PREPARE)
1299                     || (newState.mState == CpmsState.SIMULATE_SLEEP)
1300                     || (newState.mState == CpmsState.SIMULATE_HIBERNATION);
1301                 break;
1302             case CpmsState.SHUTDOWN_PREPARE:
1303                 // If VHAL sends SHUTDOWN_IMMEDIATELY or SLEEP_IMMEDIATELY while in
1304                 // SHUTDOWN_PREPARE state, do it.
1305                 transitionAllowed =
1306                         ((newState.mState == CpmsState.SHUTDOWN_PREPARE) && !newState.mCanPostpone)
1307                                 || (newState.mState == CpmsState.WAIT_FOR_FINISH)
1308                                 || (newState.mState == CpmsState.WAIT_FOR_VHAL);
1309                 break;
1310             case CpmsState.SIMULATE_SLEEP:
1311             case CpmsState.SIMULATE_HIBERNATION:
1312                 transitionAllowed = true;
1313                 break;
1314             case CpmsState.WAIT_FOR_FINISH:
1315                 transitionAllowed = (newState.mState == CpmsState.SUSPEND
1316                         || newState.mState == CpmsState.WAIT_FOR_VHAL);
1317                 break;
1318             default:
1319                 Slogf.e(TAG, "Unexpected current state: currentState=%s, newState=%s",
1320                         mCurrentState.name(), newState.name());
1321                 transitionAllowed = true;
1322         }
1323         if (!transitionAllowed) {
1324             Slogf.e(TAG, "Requested power transition is not allowed: %s --> %s",
1325                     mCurrentState.name(), newState.name());
1326         }
1327         return transitionAllowed;
1328     }
1329 
doHandleProcessingComplete()1330     private void doHandleProcessingComplete() {
1331         int listenerState = CarPowerManager.STATE_SHUTDOWN_ENTER;
1332         synchronized (mLock) {
1333             clearWaitingForCompletion(/*clearQueue=*/false);
1334             boolean shutdownOnFinish = (mActionOnFinish == ACTION_ON_FINISH_SHUTDOWN);
1335             if (!shutdownOnFinish && mLastSleepEntryTime > mShutdownStartTime) {
1336                 // entered sleep after processing start. So this could be duplicate request.
1337                 Slogf.w(TAG, "Duplicate sleep entry request, ignore");
1338                 return;
1339             }
1340             if (shutdownOnFinish) {
1341                 listenerState = CarPowerManager.STATE_SHUTDOWN_ENTER;
1342             } else if (mActionOnFinish == ACTION_ON_FINISH_DEEP_SLEEP) {
1343                 listenerState = CarPowerManager.STATE_SUSPEND_ENTER;
1344             } else if (mActionOnFinish == ACTION_ON_FINISH_HIBERNATION) {
1345                 listenerState = CarPowerManager.STATE_HIBERNATION_ENTER;
1346             }
1347         }
1348 
1349         onApPowerStateChange(CpmsState.WAIT_FOR_FINISH, listenerState);
1350     }
1351 
1352     @Override
onDisplayBrightnessChange(int brightness)1353     public void onDisplayBrightnessChange(int brightness) {
1354         mHandler.handleDisplayBrightnessChange(brightness);
1355     }
1356 
doHandleDisplayBrightnessChange(int brightness)1357     private void doHandleDisplayBrightnessChange(int brightness) {
1358         mSystemInterface.setDisplayBrightness(brightness);
1359     }
1360 
doHandleMainDisplayStateChange(boolean on)1361     private void doHandleMainDisplayStateChange(boolean on) {
1362         Slogf.w(TAG, "Unimplemented: doHandleMainDisplayStateChange() - on = %b", on);
1363     }
1364 
doHandlePowerPolicyNotification(String policyId)1365     private void doHandlePowerPolicyNotification(String policyId) {
1366         // Sending notification of power policy change triggered through CarPowerManager API.
1367         notifyPowerPolicyChange(policyId, /* upToDaemon= */ true, /* force= */ false);
1368     }
1369 
1370     /**
1371      * Handles when a main display changes.
1372      */
handleMainDisplayChanged(boolean on)1373     public void handleMainDisplayChanged(boolean on) {
1374         mHandler.handleMainDisplayStateChange(on);
1375     }
1376 
1377     /**
1378      * Sends display brightness to VHAL.
1379      * @param brightness value 0-100%
1380      */
sendDisplayBrightness(int brightness)1381     public void sendDisplayBrightness(int brightness) {
1382         mHal.sendDisplayBrightness(brightness);
1383     }
1384 
1385     /**
1386      * Gets the PowerHandler that we use to change power states
1387      */
getHandler()1388     public Handler getHandler() {
1389         return mHandler;
1390 
1391     }
1392 
1393     /**
1394      * Registers power state change listeners running in CarService, which is not a binder
1395      * interfaces.
1396      */
registerInternalListener(ICarPowerStateListener listener)1397     public void registerInternalListener(ICarPowerStateListener listener) {
1398         CarServiceUtils.assertCallingFromSystemProcessOrSelf();
1399         synchronized (mLock) {
1400             mInternalPowerListeners.add(listener);
1401         }
1402     }
1403 
1404     /**
1405      * Unregisters power state change listeners running in CarService, which is not a binder
1406      * interface.
1407      */
unregisterInternalListener(ICarPowerStateListener listener)1408     public void unregisterInternalListener(ICarPowerStateListener listener) {
1409         CarServiceUtils.assertCallingFromSystemProcessOrSelf();
1410         boolean found = false;
1411         synchronized (mLock) {
1412             found = mInternalPowerListeners.remove(listener);
1413         }
1414         if (found) {
1415             removeListenerFromWaitingList(listener.asBinder());
1416         }
1417     }
1418 
1419     /**
1420      * Tells {@link CarPowerManagementService} that the listener running in CarService completes
1421      * handling power state change.
1422      */
completeHandlingPowerStateChange(int state, ICarPowerStateListener listener)1423     public void completeHandlingPowerStateChange(int state, ICarPowerStateListener listener) {
1424         CarServiceUtils.assertCallingFromSystemProcessOrSelf();
1425         handleListenerCompletion(state, listener,
1426                 new ArraySet(new Integer[] {CarPowerManager.STATE_INVALID}));
1427     }
1428 
1429     // Binder interface for general use.
1430     // The listener is not required (or allowed) to call finished().
1431     @Override
registerListener(ICarPowerStateListener listener)1432     public void registerListener(ICarPowerStateListener listener) {
1433         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1434         mPowerManagerListeners.register(listener);
1435     }
1436 
1437     // Binder interface for Car services only.
1438     // After the listener completes its processing, it must call finished().
1439     @Override
registerListenerWithCompletion(ICarPowerStateListener listener)1440     public void registerListenerWithCompletion(ICarPowerStateListener listener) {
1441         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS);
1442 
1443         mPowerManagerListenersWithCompletion.register(listener);
1444         // TODO: Need to send current state to newly registered listener? If so, need to handle
1445         //       completion for SHUTDOWN_PREPARE state
1446     }
1447 
1448     @Override
unregisterListener(ICarPowerStateListener listener)1449     public void unregisterListener(ICarPowerStateListener listener) {
1450         CarServiceUtils.assertAnyPermission(mContext, Car.PERMISSION_CAR_POWER,
1451                 Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS);
1452         doUnregisterListener(listener);
1453     }
1454 
1455     @Override
requestShutdownOnNextSuspend()1456     public void requestShutdownOnNextSuspend() {
1457         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1458         synchronized (mLock) {
1459             mShutdownOnNextSuspend = true;
1460         }
1461     }
1462 
1463     @Override
finished(int state, ICarPowerStateListener listener)1464     public void finished(int state, ICarPowerStateListener listener) {
1465         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS);
1466         handleListenerCompletion(state, listener, new ArraySet(new Integer[]
1467                 {CarPowerManager.STATE_INVALID, CarPowerManager.STATE_SHUTDOWN_PREPARE}));
1468     }
1469 
1470     @Override
scheduleNextWakeupTime(int seconds)1471     public void scheduleNextWakeupTime(int seconds) {
1472         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1473         if (seconds < 0) {
1474             Slogf.w(TAG, "Next wake up time is negative. Ignoring!");
1475             return;
1476         }
1477         boolean timedWakeupAllowed = mHal.isTimedWakeupAllowed();
1478         synchronized (mLock) {
1479             if (!timedWakeupAllowed) {
1480                 Slogf.w(TAG, "Setting timed wakeups are disabled in HAL. Skipping");
1481                 mNextWakeupSec = 0;
1482                 return;
1483             }
1484             if (mNextWakeupSec == 0 || mNextWakeupSec > seconds) {
1485                 // The new value is sooner than the old value. Take the new value.
1486                 mNextWakeupSec = seconds;
1487             } else {
1488                 Slogf.d(TAG, "Tried to schedule next wake up, but already had shorter "
1489                         + "scheduled time");
1490             }
1491         }
1492     }
1493 
1494     @Override
getPowerState()1495     public @CarPowerManager.CarPowerState int getPowerState() {
1496         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1497         synchronized (mLock) {
1498             return (mCurrentState == null) ? CarPowerManager.STATE_INVALID
1499                     : mCurrentState.mCarPowerStateListenerState;
1500         }
1501     }
1502 
1503     /**
1504      * @see android.car.hardware.power.CarPowerManager#getCurrentPowerPolicy
1505      */
1506     @Override
getCurrentPowerPolicy()1507     public CarPowerPolicy getCurrentPowerPolicy() {
1508         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
1509         return mPowerComponentHandler.getAccumulatedPolicy();
1510     }
1511 
1512     /**
1513      * @see android.car.hardware.power.CarPowerManager#applyPowerPolicy
1514      */
1515     @Override
applyPowerPolicy(String policyId)1516     public void applyPowerPolicy(String policyId) {
1517         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_POWER_POLICY);
1518         Preconditions.checkArgument(policyId != null, "policyId cannot be null");
1519         Preconditions.checkArgument(!policyId.startsWith(PolicyReader.SYSTEM_POWER_POLICY_PREFIX),
1520                 "System power policy cannot be applied by apps");
1521         int status = applyPowerPolicy(policyId, /* delayNotification= */ true,
1522                 /* upToDaemon= */ true, /* force= */ false);
1523         if (status != PolicyOperationStatus.OK) {
1524             throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status));
1525         }
1526         Slogf.d(TAG, "Queueing power policy notification (id: %s) in the handler", policyId);
1527         mHandler.handlePowerPolicyNotification(policyId);
1528     }
1529 
1530     /**
1531      * @see android.car.hardware.power.CarPowerManager#setPowerPolicyGroup
1532      */
1533     @Override
setPowerPolicyGroup(String policyGroupId)1534     public void setPowerPolicyGroup(String policyGroupId) {
1535         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_POWER_POLICY);
1536         Preconditions.checkArgument(policyGroupId != null, "policyGroupId cannot be null");
1537         int status = setCurrentPowerPolicyGroup(policyGroupId);
1538         if (status != PolicyOperationStatus.OK) {
1539             throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status));
1540         }
1541     }
1542 
1543     /**
1544      * @see android.car.hardware.power.CarPowerManager#addPowerPolicyListener
1545      */
1546     @Override
addPowerPolicyListener(CarPowerPolicyFilter filter, ICarPowerPolicyListener listener)1547     public void addPowerPolicyListener(CarPowerPolicyFilter filter,
1548             ICarPowerPolicyListener listener) {
1549         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
1550         mPowerPolicyListeners.register(listener, filter);
1551     }
1552 
1553     /**
1554      * @see android.car.hardware.power.CarPowerManager#removePowerPolicyListener
1555      */
1556     @Override
removePowerPolicyListener(ICarPowerPolicyListener listener)1557     public void removePowerPolicyListener(ICarPowerPolicyListener listener) {
1558         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
1559         mPowerPolicyListeners.unregister(listener);
1560     }
1561 
notifySilentModeChange(boolean silent)1562     void notifySilentModeChange(boolean silent) {
1563         Slogf.i(TAG, "Silent mode is set to %b", silent);
1564         if (silent) {
1565             applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION);
1566         } else {
1567             cancelPreemptivePowerPolicy();
1568         }
1569     }
1570 
handleListenerCompletion(int state, ICarPowerStateListener listener, ArraySet<Integer> notAllowedStates)1571     private void handleListenerCompletion(int state, ICarPowerStateListener listener,
1572             ArraySet<Integer> notAllowedStates) {
1573         synchronized (mLock) {
1574             if (notAllowedStates.contains(mStateForCompletion)) {
1575                 Slogf.w(TAG, "The current state(%d) doesn't allow listener completion",
1576                         mStateForCompletion);
1577                 return;
1578             }
1579             if (state != mStateForCompletion) {
1580                 Slogf.w(TAG, "Given state(%d) doesn't match the current state(%d) for completion",
1581                         state, mStateForCompletion);
1582                 return;
1583             }
1584         }
1585         removeListenerFromWaitingList(listener.asBinder());
1586     }
1587 
1588 
doUnregisterListener(ICarPowerStateListener listener)1589     private void doUnregisterListener(ICarPowerStateListener listener) {
1590         mPowerManagerListeners.unregister(listener);
1591         boolean found = mPowerManagerListenersWithCompletion.unregister(listener);
1592         if (found) {
1593             // Remove this from the completion list (if it's there)
1594             removeListenerFromWaitingList(listener.asBinder());
1595         }
1596     }
1597 
removeListenerFromWaitingList(IBinder binderListener)1598     private void removeListenerFromWaitingList(IBinder binderListener) {
1599         synchronized (mLock) {
1600             mListenersWeAreWaitingFor.remove(binderListener);
1601         }
1602         // Signals a thread to check if all listeners complete.
1603         mListenerCompletionSem.release();
1604     }
1605 
finishShutdownPrepare()1606     private void finishShutdownPrepare() {
1607         boolean shouldHandleProcessingComplete = false;
1608         synchronized (mLock) {
1609             if (mCurrentState != null
1610                     && (mCurrentState.mState == CpmsState.SHUTDOWN_PREPARE
1611                             || mCurrentState.mState == CpmsState.SIMULATE_SLEEP
1612                             || mCurrentState.mState == CpmsState.SIMULATE_HIBERNATION)) {
1613                 // All apps are ready to shutdown/suspend.
1614                 if (mActionOnFinish != ACTION_ON_FINISH_SHUTDOWN) {
1615                     if (mLastSleepEntryTime > mShutdownStartTime
1616                             && mLastSleepEntryTime < SystemClock.elapsedRealtime()) {
1617                         Slogf.d(TAG, "finishShutdownPrepare: Already slept!");
1618                         return;
1619                     }
1620                 }
1621                 shouldHandleProcessingComplete = true;
1622             }
1623         }
1624 
1625         if (shouldHandleProcessingComplete) {
1626             Slogf.i(TAG, "Apps are finished, call handleProcessingComplete()");
1627             mHandler.handleProcessingComplete();
1628         }
1629     }
1630 
initializePowerPolicy()1631     private void initializePowerPolicy() {
1632         Slogf.i(TAG, "CPMS is taking control from carpowerpolicyd");
1633         ICarPowerPolicySystemNotification daemon;
1634         synchronized (mLock) {
1635             daemon = mCarPowerPolicyDaemon;
1636         }
1637         PolicyState state;
1638         if (daemon != null) {
1639             try {
1640                 state = daemon.notifyCarServiceReady();
1641             } catch (RemoteException e) {
1642                 Slogf.e(TAG, e, "Failed to tell car power policy daemon that CarService is ready");
1643                 return;
1644             }
1645         } else {
1646             Slogf.w(TAG, "Failed to notify car service is ready. car power policy daemon is not "
1647                     + "available");
1648             return;
1649         }
1650 
1651         String currentPowerPolicyId;
1652         String currentPolicyGroupId;
1653         synchronized (mLock) {
1654             mHasControlOverDaemon = true;
1655             currentPowerPolicyId = mCurrentPowerPolicyId;
1656             currentPolicyGroupId = mCurrentPowerPolicyGroupId;
1657         }
1658         // If the current power policy or the policy group has been modified by CPMS, we ignore
1659         // the power policy or the policy group passed from car power policy daemon, and notifies
1660         // the current power policy to the daemon.
1661         if (currentPowerPolicyId == null || currentPowerPolicyId.isEmpty()) {
1662             Slogf.i(TAG, "Attempting to apply the power policy(%s) from the daemon",
1663                     state.policyId);
1664             int status = applyPowerPolicy(state.policyId, /* delayNotification= */ false,
1665                     /* upToDaemon= */ false, /* force= */ false);
1666             if (status != PolicyOperationStatus.OK) {
1667                 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
1668             }
1669         } else {
1670             Slogf.i(TAG, "CPMS applied power policy(%s) before connecting to the daemon. Notifying "
1671                     + "to the daemon...", currentPowerPolicyId);
1672             notifyPowerPolicyChangeToDaemon(currentPowerPolicyId, /* force= */ true);
1673         }
1674         if (currentPolicyGroupId == null || currentPolicyGroupId.isEmpty()) {
1675             int status = setCurrentPowerPolicyGroup(state.policyGroupId);
1676             if (status != PolicyOperationStatus.OK) {
1677                 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
1678             }
1679         }
1680         mSilentModeHandler.init();
1681     }
1682 
1683     @PolicyOperationStatus.ErrorCode
setCurrentPowerPolicyGroup(String policyGroupId)1684     private int setCurrentPowerPolicyGroup(String policyGroupId) {
1685         if (!mPolicyReader.isPowerPolicyGroupAvailable(policyGroupId)) {
1686             int error = PolicyOperationStatus.ERROR_SET_POWER_POLICY_GROUP;
1687             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error,
1688                     policyGroupId + " is not registered"));
1689             return error;
1690         }
1691         synchronized (mLock) {
1692             mCurrentPowerPolicyGroupId = policyGroupId;
1693         }
1694         return PolicyOperationStatus.OK;
1695     }
1696 
1697     @PolicyOperationStatus.ErrorCode
applyPowerPolicy(@ullable String policyId, boolean delayNotification, boolean upToDaemon, boolean force)1698     private int applyPowerPolicy(@Nullable String policyId, boolean delayNotification,
1699             boolean upToDaemon, boolean force) {
1700         CarPowerPolicy policy = mPolicyReader.getPowerPolicy(policyId);
1701         if (policy == null) {
1702             int error = PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID;
1703             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId));
1704             return error;
1705         }
1706         synchronized (mLock) {
1707             if (mIsPowerPolicyLocked) {
1708                 Slogf.i(TAG, "Power policy is locked. The request policy(%s) will be applied when "
1709                         + "power policy becomes unlocked", policyId);
1710                 mPendingPowerPolicyId = policyId;
1711                 return PolicyOperationStatus.OK;
1712             }
1713             mCurrentPowerPolicyId = policyId;
1714         }
1715         mPowerComponentHandler.applyPowerPolicy(policy);
1716         if (!delayNotification) {
1717             notifyPowerPolicyChange(policyId, upToDaemon, force);
1718         }
1719         Slogf.i(TAG, "The current power policy is %s", policyId);
1720         return PolicyOperationStatus.OK;
1721     }
1722 
1723     @PolicyOperationStatus.ErrorCode
applyPreemptivePowerPolicy(String policyId)1724     private int applyPreemptivePowerPolicy(String policyId) {
1725         CarPowerPolicy policy = mPolicyReader.getPreemptivePowerPolicy(policyId);
1726         if (policy == null) {
1727             int error = PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID;
1728             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId));
1729             return error;
1730         }
1731         synchronized (mLock) {
1732             mIsPowerPolicyLocked = true;
1733             if (!mPolicyReader.isPreemptivePowerPolicy(mCurrentPowerPolicyId)) {
1734                 mPendingPowerPolicyId = mCurrentPowerPolicyId;
1735             }
1736             mCurrentPowerPolicyId = policyId;
1737         }
1738         mPowerComponentHandler.applyPowerPolicy(policy);
1739         notifyPowerPolicyChange(policyId, /* upToDaemon= */ true, /* force= */ true);
1740         Slogf.i(TAG, "The current power policy is %s", policyId);
1741         return PolicyOperationStatus.OK;
1742     }
1743 
cancelPreemptivePowerPolicy()1744     private void cancelPreemptivePowerPolicy() {
1745         String policyId;
1746         synchronized (mLock) {
1747             if (!mIsPowerPolicyLocked) {
1748                 Slogf.w(TAG, "Failed to cancel system power policy: the current policy is not the "
1749                         + "system power policy");
1750                 return;
1751             }
1752             mIsPowerPolicyLocked = false;
1753             policyId = mPendingPowerPolicyId;
1754             mPendingPowerPolicyId = null;
1755         }
1756         if (policyId != null) { // Pending policy exist
1757             int status = applyPowerPolicy(policyId, /* delayNotification= */ false,
1758                     /* upToDaemon= */ true, /* force= */ true);
1759             if (status != PolicyOperationStatus.OK) {
1760                 Slogf.w(TAG, "Failed to cancel system power policy: %s",
1761                         PolicyOperationStatus.errorCodeToString(status));
1762             }
1763         } else {
1764             Slogf.w(TAG, "cancelPreemptivePowerPolicy(), no pending power policy");
1765         }
1766     }
1767 
notifyPowerPolicyChangeToDaemon(String policyId, boolean force)1768     private void notifyPowerPolicyChangeToDaemon(String policyId, boolean force) {
1769         ICarPowerPolicySystemNotification daemon;
1770         boolean hadPendingPolicyNotification;
1771         synchronized (mLock) {
1772             daemon = mCarPowerPolicyDaemon;
1773             if (daemon == null) {
1774                 Slogf.e(TAG, "Failed to notify car power policy daemon: the daemon is not ready");
1775                 return;
1776             }
1777             if (!mHasControlOverDaemon) {
1778                 Slogf.w(TAG, "Notifying policy change is deferred: CPMS has not yet taken control");
1779                 return;
1780             }
1781         }
1782         try {
1783             daemon.notifyPowerPolicyChange(policyId, force);
1784         } catch (RemoteException | IllegalStateException e) {
1785             Slogf.e(TAG, e, "Failed to notify car power policy daemon of a new power policy(%s)",
1786                     policyId);
1787         }
1788     }
1789 
notifyPowerPolicyChange(String policyId, boolean upToDaemon, boolean force)1790     private void notifyPowerPolicyChange(String policyId, boolean upToDaemon, boolean force) {
1791         EventLogHelper.writePowerPolicyChange(policyId);
1792         // Notify system clients
1793         if (upToDaemon) {
1794             notifyPowerPolicyChangeToDaemon(policyId, force);
1795         }
1796 
1797         // Notify Java clients
1798         CarPowerPolicy accumulatedPolicy = mPowerComponentHandler.getAccumulatedPolicy();
1799         CarPowerPolicy appliedPolicy = mPolicyReader.isPreemptivePowerPolicy(policyId)
1800                 ? mPolicyReader.getPreemptivePowerPolicy(policyId)
1801                 : mPolicyReader.getPowerPolicy(policyId);
1802         if (appliedPolicy == null) {
1803             Slogf.wtf(TAG, "The new power policy(%s) should exist", policyId);
1804         }
1805         int idx = mPowerPolicyListeners.beginBroadcast();
1806         while (idx-- > 0) {
1807             ICarPowerPolicyListener listener = mPowerPolicyListeners.getBroadcastItem(idx);
1808             CarPowerPolicyFilter filter =
1809                     (CarPowerPolicyFilter) mPowerPolicyListeners.getBroadcastCookie(idx);
1810             if (!mPowerComponentHandler.isComponentChanged(filter)) {
1811                 continue;
1812             }
1813             try {
1814                 listener.onPolicyChanged(appliedPolicy, accumulatedPolicy);
1815             } catch (RemoteException e) {
1816                 // It's likely the connection snapped. Let binder death handle the situation.
1817                 Slogf.e(TAG, e, "onPolicyChanged() call failed: policyId = %s", policyId);
1818             }
1819         }
1820         mPowerPolicyListeners.finishBroadcast();
1821     }
1822 
makeSureNoUserInteraction()1823     private void makeSureNoUserInteraction() {
1824         mSilentModeHandler.updateKernelSilentMode(true);
1825         int status = applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION);
1826         if (status != PolicyOperationStatus.OK) {
1827             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
1828         }
1829     }
1830 
connectToPowerPolicyDaemon()1831     private void connectToPowerPolicyDaemon() {
1832         synchronized (mLock) {
1833             if (mCarPowerPolicyDaemon != null || mConnectionInProgress) {
1834                 return;
1835             }
1836             mConnectionInProgress = true;
1837         }
1838         connectToDaemonHelper(CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY);
1839     }
1840 
connectToDaemonHelper(int retryCount)1841     private void connectToDaemonHelper(int retryCount) {
1842         if (retryCount <= 0) {
1843             synchronized (mLock) {
1844                 mConnectionInProgress = false;
1845             }
1846             Slogf.e(TAG, "Cannot reconnect to car power policyd daemon after retrying %d times",
1847                     CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY);
1848             return;
1849         }
1850         if (makeBinderConnection()) {
1851             Slogf.i(TAG, "Connected to car power policy daemon");
1852             initializePowerPolicy();
1853             return;
1854         }
1855         final int numRetry = retryCount - 1;
1856         mHandler.postDelayed(() -> connectToDaemonHelper(numRetry),
1857                 CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS);
1858     }
1859 
makeBinderConnection()1860     private boolean makeBinderConnection() {
1861         long currentTimeMs = SystemClock.uptimeMillis();
1862         IBinder binder = ServiceManagerHelper.getService(CAR_POWER_POLICY_DAEMON_INTERFACE);
1863         if (binder == null) {
1864             Slogf.w(TAG, "Finding car power policy daemon failed. Power policy management is not "
1865                     + "supported");
1866             return false;
1867         }
1868         long elapsedTimeMs = SystemClock.uptimeMillis() - currentTimeMs;
1869         if (elapsedTimeMs > CAR_POWER_POLICY_DAEMON_FIND_MARGINAL_TIME_MS) {
1870             Slogf.wtf(TAG, "Finding car power policy daemon took too long(%dms)", elapsedTimeMs);
1871         }
1872 
1873         ICarPowerPolicySystemNotification daemon =
1874                 ICarPowerPolicySystemNotification.Stub.asInterface(binder);
1875         if (daemon == null) {
1876             Slogf.w(TAG, "Getting car power policy daemon interface failed. Power policy management"
1877                     + " is not supported");
1878             return false;
1879         }
1880         synchronized (mLock) {
1881             mCarPowerPolicyDaemon = daemon;
1882             mConnectionInProgress = false;
1883         }
1884         mBinderHandler = new BinderHandler(daemon);
1885         mBinderHandler.linkToDeath();
1886         return true;
1887     }
1888 
1889     private final class BinderHandler implements IBinder.DeathRecipient {
1890         private ICarPowerPolicySystemNotification mDaemon;
1891 
BinderHandler(ICarPowerPolicySystemNotification daemon)1892         private BinderHandler(ICarPowerPolicySystemNotification daemon) {
1893             mDaemon = daemon;
1894         }
1895 
1896         @Override
binderDied()1897         public void binderDied() {
1898             Slogf.w(TAG, "Car power policy daemon died: reconnecting");
1899             unlinkToDeath();
1900             mDaemon = null;
1901             synchronized (mLock) {
1902                 mCarPowerPolicyDaemon = null;
1903                 mHasControlOverDaemon = false;
1904             }
1905             mHandler.postDelayed(
1906                     () -> connectToDaemonHelper(CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY),
1907                     CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS);
1908         }
1909 
linkToDeath()1910         private void linkToDeath() {
1911             if (mDaemon == null) {
1912                 return;
1913             }
1914             IBinder binder = mDaemon.asBinder();
1915             if (binder == null) {
1916                 Slogf.w(TAG, "Linking to binder death recipient skipped");
1917                 return;
1918             }
1919             try {
1920                 binder.linkToDeath(this, 0);
1921             } catch (RemoteException e) {
1922                 mDaemon = null;
1923                 Slogf.w(TAG, e, "Linking to binder death recipient failed: %s");
1924             }
1925         }
1926 
unlinkToDeath()1927         private void unlinkToDeath() {
1928             if (mDaemon == null) {
1929                 return;
1930             }
1931             IBinder binder = mDaemon.asBinder();
1932             if (binder == null) {
1933                 Slogf.w(TAG, "Unlinking from binder death recipient skipped");
1934                 return;
1935             }
1936             binder.unlinkToDeath(this, 0);
1937         }
1938     }
1939 
1940     private static final class PowerHandler extends Handler {
1941         private static final String TAG = PowerHandler.class.getSimpleName();
1942         private static final int MSG_POWER_STATE_CHANGE = 0;
1943         private static final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1;
1944         private static final int MSG_MAIN_DISPLAY_STATE_CHANGE = 2;
1945         private static final int MSG_PROCESSING_COMPLETE = 3;
1946         private static final int MSG_POWER_POLICY_NOTIFICATION = 4;
1947 
1948         // Do not handle this immediately but with some delay as there can be a race between
1949         // display off due to rear view camera and delivery to here.
1950         private static final long MAIN_DISPLAY_EVENT_DELAY_MS = 500;
1951 
1952         private final WeakReference<CarPowerManagementService> mService;
1953 
PowerHandler(Looper looper, CarPowerManagementService service)1954         private PowerHandler(Looper looper, CarPowerManagementService service) {
1955             super(looper);
1956             mService = new WeakReference<CarPowerManagementService>(service);
1957         }
1958 
handlePowerStateChange()1959         private void handlePowerStateChange() {
1960             Message msg = obtainMessage(MSG_POWER_STATE_CHANGE);
1961             sendMessage(msg);
1962         }
1963 
handleDisplayBrightnessChange(int brightness)1964         private void handleDisplayBrightnessChange(int brightness) {
1965             Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, brightness, 0);
1966             sendMessage(msg);
1967         }
1968 
handleMainDisplayStateChange(boolean on)1969         private void handleMainDisplayStateChange(boolean on) {
1970             removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
1971             Message msg = obtainMessage(MSG_MAIN_DISPLAY_STATE_CHANGE, Boolean.valueOf(on));
1972             sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS);
1973         }
1974 
handleProcessingComplete()1975         private void handleProcessingComplete() {
1976             removeMessages(MSG_PROCESSING_COMPLETE);
1977             Message msg = obtainMessage(MSG_PROCESSING_COMPLETE);
1978             sendMessage(msg);
1979         }
1980 
cancelProcessingComplete()1981         private void cancelProcessingComplete() {
1982             removeMessages(MSG_PROCESSING_COMPLETE);
1983         }
1984 
handlePowerPolicyNotification(String policyId)1985         private void handlePowerPolicyNotification(String policyId) {
1986             Message msg = obtainMessage(MSG_POWER_POLICY_NOTIFICATION, policyId);
1987             sendMessage(msg);
1988         }
1989 
cancelAll()1990         private void cancelAll() {
1991             removeMessages(MSG_POWER_STATE_CHANGE);
1992             removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE);
1993             removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
1994             removeMessages(MSG_PROCESSING_COMPLETE);
1995             removeMessages(MSG_POWER_POLICY_NOTIFICATION);
1996         }
1997 
1998         @Override
handleMessage(Message msg)1999         public void handleMessage(Message msg) {
2000             CarPowerManagementService service = mService.get();
2001             if (service == null) {
2002                 Slogf.i(TAG, "handleMessage null service");
2003                 return;
2004             }
2005             switch (msg.what) {
2006                 case MSG_POWER_STATE_CHANGE:
2007                     service.doHandlePowerStateChange();
2008                     break;
2009                 case MSG_DISPLAY_BRIGHTNESS_CHANGE:
2010                     service.doHandleDisplayBrightnessChange(msg.arg1);
2011                     break;
2012                 case MSG_MAIN_DISPLAY_STATE_CHANGE:
2013                     service.doHandleMainDisplayStateChange((Boolean) msg.obj);
2014                     break;
2015                 case MSG_PROCESSING_COMPLETE:
2016                     service.doHandleProcessingComplete();
2017                     break;
2018                 case MSG_POWER_POLICY_NOTIFICATION:
2019                     service.doHandlePowerPolicyNotification((String) msg.obj);
2020                     break;
2021             }
2022         }
2023     }
2024 
2025     // Send the command to enter Suspend to RAM.
2026     // If the command is not successful, try again with an exponential back-off.
2027     // If it fails repeatedly, send the command to shut down.
2028     // If we decide to go to a different power state, abort this retry mechanism.
2029     // Returns true if we successfully suspended.
suspendWithRetries()2030     private boolean suspendWithRetries() {
2031         boolean isDeepSleep;
2032         synchronized (mLock) {
2033             isDeepSleep = (mActionOnFinish == ACTION_ON_FINISH_DEEP_SLEEP);
2034         }
2035 
2036         String suspendTarget = isDeepSleep ? "Suspend-to-RAM" : "Suspend-to-Disk";
2037         long retryIntervalMs = INITIAL_SUSPEND_RETRY_INTERVAL_MS;
2038         long totalWaitDurationMs = 0;
2039         while (true) {
2040             Slogf.i(TAG, "Entering %s", suspendTarget);
2041             boolean suspendSucceeded = isDeepSleep ? mSystemInterface.enterDeepSleep()
2042                     : mSystemInterface.enterHibernation();
2043 
2044             if (suspendSucceeded) {
2045                 return true;
2046             }
2047             if (totalWaitDurationMs >= mMaxSuspendWaitDurationMs) {
2048                 break;
2049             }
2050             // We failed to suspend. Block the thread briefly and try again.
2051             synchronized (mLock) {
2052                 if (!mPendingPowerStates.isEmpty()) {
2053                     // Check for a new power state now, before going around the loop again.
2054                     CpmsState state = mPendingPowerStates.peekFirst();
2055                     if (state != null && needPowerStateChangeLocked(state)) {
2056                         Slogf.i(TAG, "Terminating the attempt to suspend target = %s,"
2057                                         + " currentState = %s, pendingState = %s", suspendTarget,
2058                                 mCurrentState.stateToString(), state.stateToString());
2059                         return false;
2060                     }
2061                 }
2062 
2063                 Slogf.w(TAG, "Failed to Suspend; will retry after %dms", retryIntervalMs);
2064                 try {
2065                     mLock.wait(retryIntervalMs);
2066                 } catch (InterruptedException ignored) {
2067                     Thread.currentThread().interrupt();
2068                 }
2069                 totalWaitDurationMs += retryIntervalMs;
2070                 retryIntervalMs = Math.min(retryIntervalMs * 2, MAX_RETRY_INTERVAL_MS);
2071             }
2072         }
2073         // Too many failures trying to suspend. Shut down.
2074         Slogf.w(TAG, "Could not %s after %dms long trial. Shutting down.", suspendTarget,
2075                 totalWaitDurationMs);
2076         mSystemInterface.shutdown();
2077         return false;
2078     }
2079 
2080     private static final class CpmsState {
2081         // NOTE: When modifying states below, make sure to update CarPowerStateChanged.State in
2082         //   frameworks/proto_logging/stats/atoms.proto also.
2083         public static final int WAIT_FOR_VHAL = 0;
2084         public static final int ON = 1;
2085         public static final int SHUTDOWN_PREPARE = 2;
2086         public static final int WAIT_FOR_FINISH = 3;
2087         public static final int SUSPEND = 4;
2088         public static final int SIMULATE_SLEEP = 5;
2089         public static final int SIMULATE_HIBERNATION = 6;
2090 
2091         /* Config values from AP_POWER_STATE_REQ */
2092         public final boolean mCanPostpone;
2093 
2094         @PowerState.ShutdownType
2095         public final int mShutdownType;
2096 
2097         /* Message sent to CarPowerStateListener in response to this state */
2098         @CarPowerManager.CarPowerState
2099         public final int mCarPowerStateListenerState;
2100         /* One of the above state variables */
2101         public final int mState;
2102 
2103         /**
2104           * This constructor takes a PowerHalService.PowerState object and creates the corresponding
2105           * CPMS state from it.
2106           */
CpmsState(PowerState halPowerState)2107         CpmsState(PowerState halPowerState) {
2108             switch (halPowerState.mState) {
2109                 case VehicleApPowerStateReq.ON:
2110                     this.mCanPostpone = false;
2111                     this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED;
2112                     this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(ON);
2113                     this.mState = ON;
2114                     break;
2115                 case VehicleApPowerStateReq.SHUTDOWN_PREPARE:
2116                     this.mCanPostpone = halPowerState.canPostponeShutdown();
2117                     this.mShutdownType = halPowerState.getShutdownType();
2118                     this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(
2119                             SHUTDOWN_PREPARE);
2120                     this.mState = SHUTDOWN_PREPARE;
2121                     break;
2122                 case VehicleApPowerStateReq.CANCEL_SHUTDOWN:
2123                     this.mCanPostpone = false;
2124                     this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED;
2125                     this.mCarPowerStateListenerState = CarPowerManager.STATE_SHUTDOWN_CANCELLED;
2126                     this.mState = WAIT_FOR_VHAL;
2127                     break;
2128                 case VehicleApPowerStateReq.FINISHED:
2129                     this.mCanPostpone = false;
2130                     this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED;
2131                     this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(SUSPEND);
2132                     this.mState = SUSPEND;
2133                     break;
2134                 default:
2135                     // Illegal state from PowerState.  Throw an exception?
2136                     // TODO(b/202414427): Add handling of illegal state
2137                     this.mCanPostpone = false;
2138                     this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED;
2139                     this.mCarPowerStateListenerState = 0;
2140                     this.mState = 0;
2141                     break;
2142             }
2143         }
2144 
CpmsState(int state, int carPowerStateListenerState, boolean canPostpone)2145         CpmsState(int state, int carPowerStateListenerState, boolean canPostpone) {
2146             this.mCanPostpone = canPostpone;
2147             this.mCarPowerStateListenerState = carPowerStateListenerState;
2148             this.mState = state;
2149             this.mShutdownType = state == SIMULATE_SLEEP ? PowerState.SHUTDOWN_TYPE_DEEP_SLEEP :
2150                     (state == SIMULATE_HIBERNATION ? PowerState.SHUTDOWN_TYPE_HIBERNATION
2151                             : PowerState.SHUTDOWN_TYPE_POWER_OFF);
2152         }
2153 
CpmsState(int state, int carPowerStateListenerState, boolean canPostpone, int shutdownType)2154         CpmsState(int state, int carPowerStateListenerState, boolean canPostpone,
2155                 int shutdownType) {
2156             this.mCanPostpone = canPostpone;
2157             this.mCarPowerStateListenerState = carPowerStateListenerState;
2158             this.mState = state;
2159             this.mShutdownType = shutdownType;
2160         }
2161 
name()2162         public String name() {
2163             return new StringBuilder()
2164                     .append(stateToString())
2165                     .append('(')
2166                     .append(mState)
2167                     .append(')')
2168                     .toString();
2169         }
2170 
stateToString()2171         private String stateToString() {
2172             String baseName;
2173             switch(mState) {
2174                 case WAIT_FOR_VHAL:         baseName = "WAIT_FOR_VHAL";        break;
2175                 case ON:                    baseName = "ON";                   break;
2176                 case SHUTDOWN_PREPARE:      baseName = "SHUTDOWN_PREPARE";     break;
2177                 case WAIT_FOR_FINISH:       baseName = "WAIT_FOR_FINISH";      break;
2178                 case SUSPEND:               baseName = "SUSPEND";              break;
2179                 case SIMULATE_SLEEP:        baseName = "SIMULATE_SLEEP";       break;
2180                 case SIMULATE_HIBERNATION:  baseName = "SIMULATE_HIBERNATION"; break;
2181                 default:                    baseName = "<unknown>";            break;
2182             }
2183             return baseName;
2184         }
2185 
cpmsStateToPowerStateListenerState(int state)2186         private static int cpmsStateToPowerStateListenerState(int state) {
2187             int powerStateListenerState = 0;
2188 
2189             // Set the CarPowerStateListenerState based on current state
2190             switch (state) {
2191                 case ON:
2192                     powerStateListenerState = CarPowerManager.STATE_ON;
2193                     break;
2194                 case SHUTDOWN_PREPARE:
2195                     powerStateListenerState = CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE;
2196                     break;
2197                 case SUSPEND:
2198                     powerStateListenerState = CarPowerManager.STATE_SUSPEND_ENTER;
2199                     break;
2200                 case WAIT_FOR_VHAL:
2201                 case WAIT_FOR_FINISH:
2202                 default:
2203                     // Illegal state for this constructor. Throw an exception?
2204                     break;
2205             }
2206             return powerStateListenerState;
2207         }
2208 
2209         @Override
equals(Object o)2210         public boolean equals(Object o) {
2211             if (this == o) {
2212                 return true;
2213             }
2214             if (!(o instanceof CpmsState)) {
2215                 return false;
2216             }
2217             CpmsState that = (CpmsState) o;
2218             return this.mState == that.mState
2219                     && this.mShutdownType == that.mShutdownType
2220                     && this.mCanPostpone == that.mCanPostpone
2221                     && this.mCarPowerStateListenerState == that.mCarPowerStateListenerState;
2222         }
2223 
2224         // PowerPolicyHostTest uses the dump output of {@code CarPowerManagementService}. If the
2225         // {@code CpmsState.toString} is modifed, PowerPolicyHostTest should be updated accordingly.
2226         // TODO(b/184862429): Remove the above comment once dump in proto buffer is done.
2227         @Override
toString()2228         public String toString() {
2229             return "CpmsState canPostpone=" + mCanPostpone
2230                     + ", carPowerStateListenerState=" + mCarPowerStateListenerState
2231                     + ", mShutdownType=" + mShutdownType
2232                     + ", CpmsState=" + name();
2233         }
2234     }
2235 
2236     /**
2237      * Resume after a manually-invoked suspend.
2238      * Invoked using "adb shell dumpsys cmd car_service resume".
2239      */
forceSimulatedResume()2240     public void forceSimulatedResume() {
2241         synchronized (mLock) {
2242             // Cancel Garage Mode in case it's running
2243             mPendingPowerStates.addFirst(new CpmsState(CpmsState.WAIT_FOR_VHAL,
2244                     CarPowerManager.STATE_SHUTDOWN_CANCELLED, /* canPostpone= */ false));
2245             mLock.notify();
2246         }
2247         mHandler.handlePowerStateChange();
2248 
2249         synchronized (mSimulationWaitObject) {
2250             mWakeFromSimulatedSleep = true;
2251             mSimulationWaitObject.notify();
2252         }
2253     }
2254 
2255     /**
2256      * Manually enters simulated suspend (deep sleep or hibernation) mode, trigging Garage mode.
2257      *
2258      * <p>If {@code shouldReboot} is 'true', reboots the system when Garage Mode completes.
2259      *
2260      * Can be invoked using
2261      * {@code "adb shell cmd car_service suspend --simulate"} or
2262      * {@code "adb shell cmd car_service hibernate --simulate"} or
2263      * {@code "adb shell cmd car_service garage-mode reboot"}.
2264      *
2265      * This is similar to {@code 'onApPowerStateChange()'} except that it needs to create a
2266      * {@code CpmsState} that is not directly derived from a {@code VehicleApPowerStateReq}.
2267      */
simulateSuspendAndMaybeReboot(@owerState.ShutdownType int shutdownType, boolean shouldReboot, boolean skipGarageMode, int wakeupAfter)2268     public void simulateSuspendAndMaybeReboot(@PowerState.ShutdownType int shutdownType,
2269             boolean shouldReboot, boolean skipGarageMode, int wakeupAfter) {
2270         boolean isDeepSleep = shutdownType == PowerState.SHUTDOWN_TYPE_DEEP_SLEEP;
2271         synchronized (mSimulationWaitObject) {
2272             mInSimulatedDeepSleepMode = true;
2273             mWakeFromSimulatedSleep = false;
2274             mResumeDelayFromSimulatedSuspendSec = wakeupAfter;
2275         }
2276         synchronized (mLock) {
2277             mRebootAfterGarageMode = shouldReboot;
2278             mPendingPowerStates.addFirst(new CpmsState(isDeepSleep ? CpmsState.SIMULATE_SLEEP
2279                             : CpmsState.SIMULATE_HIBERNATION,
2280                     CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE, !skipGarageMode));
2281         }
2282         mHandler.handlePowerStateChange();
2283     }
2284 
2285     /**
2286      * Manually defines a power policy.
2287      *
2288      * <p>If the given ID already exists or specified power components are invalid, it fails.
2289      *
2290      * @return {@code true}, if successful. Otherwise, {@code false}.
2291      */
definePowerPolicyFromCommand(String[] args, IndentingPrintWriter writer)2292     public boolean definePowerPolicyFromCommand(String[] args, IndentingPrintWriter writer) {
2293         if (args.length < 2) {
2294             writer.println("Too few arguments");
2295             return false;
2296         }
2297         String powerPolicyId = args[1];
2298         int index = 2;
2299         String[] enabledComponents = new String[0];
2300         String[] disabledComponents = new String[0];
2301         while (index < args.length) {
2302             switch (args[index]) {
2303                 case "--enable":
2304                     if (index == args.length - 1) {
2305                         writer.println("No components for --enable");
2306                         return false;
2307                     }
2308                     enabledComponents = args[index + 1].split(",");
2309                     break;
2310                 case "--disable":
2311                     if (index == args.length - 1) {
2312                         writer.println("No components for --disabled");
2313                         return false;
2314                     }
2315                     disabledComponents = args[index + 1].split(",");
2316                     break;
2317                 default:
2318                     writer.printf("Unrecognized argument: %s\n", args[index]);
2319                     return false;
2320             }
2321             index += 2;
2322         }
2323         int status = definePowerPolicy(powerPolicyId, enabledComponents, disabledComponents);
2324         if (status != PolicyOperationStatus.OK) {
2325             writer.println(PolicyOperationStatus.errorCodeToString(status));
2326             return false;
2327         }
2328         writer.printf("Power policy(%s) is successfully defined.\n", powerPolicyId);
2329         return true;
2330     }
2331 
2332     /**
2333      * Defines a power policy with the given id and components.
2334      *
2335      * <p> A policy defined with this method is valid until the system is rebooted/restarted.
2336      */
2337     @VisibleForTesting
2338     @PolicyOperationStatus.ErrorCode
definePowerPolicy(String powerPolicyId, String[] enabledComponents, String[] disabledComponents)2339     public int definePowerPolicy(String powerPolicyId, String[] enabledComponents,
2340             String[] disabledComponents) {
2341         int status = mPolicyReader.definePowerPolicy(powerPolicyId,
2342                 enabledComponents, disabledComponents);
2343         if (status != PolicyOperationStatus.OK) {
2344             int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY;
2345             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error));
2346             return error;
2347         }
2348         ICarPowerPolicySystemNotification daemon;
2349         synchronized (mLock) {
2350             daemon = mCarPowerPolicyDaemon;
2351         }
2352         try {
2353             daemon.notifyPowerPolicyDefinition(powerPolicyId, enabledComponents,
2354                     disabledComponents);
2355         } catch (RemoteException e) {
2356             int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY;
2357             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error));
2358             return error;
2359         }
2360         return PolicyOperationStatus.OK;
2361     }
2362 
2363     /**
2364      * Manually applies a power policy.
2365      *
2366      * <p>If the given ID is not defined, it fails.
2367      *
2368      * @return {@code true}, if successful. Otherwise, {@code false}.
2369      */
applyPowerPolicyFromCommand(String[] args, IndentingPrintWriter writer)2370     public boolean applyPowerPolicyFromCommand(String[] args, IndentingPrintWriter writer) {
2371         if (args.length != 2) {
2372             writer.println("Power policy ID should be given");
2373             return false;
2374         }
2375         String powerPolicyId = args[1];
2376         if (powerPolicyId == null) {
2377             writer.println("Policy ID cannot be null");
2378             return false;
2379         }
2380         boolean isPreemptive = mPolicyReader.isPreemptivePowerPolicy(powerPolicyId);
2381         int status = isPreemptive ? applyPreemptivePowerPolicy(powerPolicyId)
2382                 : applyPowerPolicy(powerPolicyId, /* delayNotification= */ false,
2383                         /* upToDaemon= */ true, /* force= */ false);
2384         if (status != PolicyOperationStatus.OK) {
2385             writer.println(PolicyOperationStatus.errorCodeToString(status));
2386             return false;
2387         }
2388         writer.printf("Power policy(%s) is successfully applied.\n", powerPolicyId);
2389         return true;
2390     }
2391 
2392     /**
2393      * Manually defines a power policy group.
2394      *
2395      * <p>If the given ID already exists, a wrong power state is given, or specified power policy ID
2396      * doesn't exist, it fails.
2397      *
2398      * @return {@code true}, if successful. Otherwise, {@code false}.
2399      */
definePowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer)2400     public boolean definePowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer) {
2401         if (args.length < 3 || args.length > 4) {
2402             writer.println("Invalid syntax");
2403             return false;
2404         }
2405         String policyGroupId = args[1];
2406         int index = 2;
2407         SparseArray<String> defaultPolicyPerState = new SparseArray<>();
2408         while (index < args.length) {
2409             String[] tokens = args[index].split(":");
2410             if (tokens.length != 2) {
2411                 writer.println("Invalid syntax");
2412                 return false;
2413             }
2414             int state = PolicyReader.toPowerState(tokens[0]);
2415             if (state == PolicyReader.INVALID_POWER_STATE) {
2416                 writer.printf("Invalid power state: %s\n", tokens[0]);
2417                 return false;
2418             }
2419             defaultPolicyPerState.put(state, tokens[1]);
2420             index++;
2421         }
2422         int status = mPolicyReader.definePowerPolicyGroup(policyGroupId,
2423                 defaultPolicyPerState);
2424         if (status != PolicyOperationStatus.OK) {
2425             writer.println(PolicyOperationStatus.errorCodeToString(status));
2426             return false;
2427         }
2428         writer.printf("Power policy group(%s) is successfully defined.\n", policyGroupId);
2429         return true;
2430     }
2431 
2432     /**
2433      * Manually sets a power policy group.
2434      *
2435      * <p>If the given ID is not defined, it fails.
2436      *
2437      * @return {@code true}, if successful. Otherwise, {@code false}.
2438      */
setPowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer)2439     public boolean setPowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer) {
2440         if (args.length != 2) {
2441             writer.println("Power policy group ID should be given");
2442             return false;
2443         }
2444         String policyGroupId = args[1];
2445         int status = setCurrentPowerPolicyGroup(policyGroupId);
2446         if (status != PolicyOperationStatus.OK) {
2447             writer.println(PolicyOperationStatus.errorCodeToString(status));
2448             return false;
2449         }
2450         writer.printf("Setting power policy group(%s) is successful.\n", policyGroupId);
2451         return true;
2452     }
2453 
2454     /**
2455      * Suspends the device.
2456      *
2457      * <p>According to the argument, the device is suspended to RAM or disk.
2458      */
suspendFromCommand(boolean isHibernation, boolean skipGarageMode)2459     public void suspendFromCommand(boolean isHibernation, boolean skipGarageMode) {
2460         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
2461         int param = 0;
2462         if (isHibernation) {
2463             if (!isHibernationAvailable()) {
2464                 throw new IllegalStateException("The device doesn't support hibernation");
2465             }
2466             param = skipGarageMode ? VehicleApPowerStateShutdownParam.HIBERNATE_IMMEDIATELY
2467                     : VehicleApPowerStateShutdownParam.CAN_HIBERNATE;
2468         } else {
2469             if (!isDeepSleepAvailable()) {
2470                 throw new IllegalStateException("The device doesn't support deep sleep");
2471             }
2472             param = skipGarageMode ? VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY
2473                     : VehicleApPowerStateShutdownParam.CAN_SLEEP;
2474         }
2475         PowerState state = new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, param);
2476         synchronized (mLock) {
2477             mRebootAfterGarageMode = false;
2478             mPendingPowerStates.addFirst(new CpmsState(state));
2479             mLock.notify();
2480         }
2481         mHandler.handlePowerStateChange();
2482     }
2483 
2484     /**
2485      * Powers off the device.
2486      */
powerOffFromCommand(boolean skipGarageMode, boolean reboot)2487     public void powerOffFromCommand(boolean skipGarageMode, boolean reboot) {
2488         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
2489         Slogf.i(TAG, "%s %s Garage Mode", reboot ? "Rebooting" : "Powering off",
2490                 skipGarageMode ? "with" : "without");
2491         int param = skipGarageMode ? VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY
2492                 : VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY;
2493         PowerState state = new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, param);
2494         synchronized (mLock) {
2495             mRebootAfterGarageMode = reboot;
2496             mPendingPowerStates.addFirst(new CpmsState(state));
2497             mLock.notify();
2498         }
2499         mHandler.handlePowerStateChange();
2500     }
2501 
2502     /**
2503      * Changes Silent Mode to the given mode.
2504      */
setSilentMode(String silentMode)2505     public void setSilentMode(String silentMode) {
2506         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
2507         mSilentModeHandler.setSilentMode(silentMode);
2508     }
2509 
2510     /**
2511      * Dumps the current Silent Mode.
2512      */
dumpSilentMode(IndentingPrintWriter writer)2513     public void dumpSilentMode(IndentingPrintWriter writer) {
2514         mSilentModeHandler.dump(writer);
2515     }
2516 
2517     /**
2518      * Returns whether a listener completion is allowed for the given state.
2519      *
2520      * <p>This method is used internally and is different from
2521      * {@link CarPowerManager.isCompletionAllowed} in that listener completion is allowed for
2522      * SHUTDOWN_PREPARE.
2523      */
isCompletionAllowed(@arPowerManager.CarPowerState int state)2524     public static boolean isCompletionAllowed(@CarPowerManager.CarPowerState int state) {
2525         return CarPowerManager.isCompletionAllowed(state);
2526     }
2527 
2528     /**
2529      * Returns a corresponding string of the given power state.
2530      */
powerStateToString(int state)2531     public static String powerStateToString(int state) {
2532         return DebugUtils.valueToString(CarPowerManager.class, "STATE_", state);
2533     }
2534 
2535     /**
2536      * Returns whether suspend (deep sleep or hibernation) is available on the device.
2537      */
isSuspendAvailable(boolean isHibernation)2538     public boolean isSuspendAvailable(boolean isHibernation) {
2539         return isHibernation ? isHibernationAvailable() : isDeepSleepAvailable();
2540     }
2541 
isDeepSleepAvailable()2542     private boolean isDeepSleepAvailable() {
2543         return mHal.isDeepSleepAllowed() && mSystemInterface.isSystemSupportingDeepSleep();
2544     }
2545 
isHibernationAvailable()2546     private boolean isHibernationAvailable() {
2547         return mHal.isHibernationAllowed() && mSystemInterface.isSystemSupportingHibernation();
2548     }
2549 
2550     // In a real Deep Sleep, the hardware removes power from the CPU (but retains power
2551     // on the RAM). This puts the processor to sleep. Upon some external signal, power
2552     // is re-applied to the CPU, and processing resumes right where it left off.
2553     // We simulate this behavior by calling wait().
2554     // We continue from wait() when forceSimulatedResume() is called.
simulateSleepByWaiting()2555     private void simulateSleepByWaiting() {
2556         Slogf.i(TAG, "Starting to simulate Deep Sleep by waiting");
2557         synchronized (mSimulationWaitObject) {
2558             if (mResumeDelayFromSimulatedSuspendSec >= 0) {
2559                 Slogf.i(TAG, "Scheduling a wakeup after %d seconds",
2560                         mResumeDelayFromSimulatedSuspendSec);
2561                 Handler handler = new Handler(Looper.getMainLooper());
2562                 handler.postDelayed(() -> forceSimulatedResume(),
2563                         mResumeDelayFromSimulatedSuspendSec * 1000);
2564             }
2565             while (!mWakeFromSimulatedSleep) {
2566                 try {
2567                     mSimulationWaitObject.wait();
2568                 } catch (InterruptedException ignored) {
2569                     Thread.currentThread().interrupt(); // Restore interrupted status
2570                 }
2571             }
2572             mInSimulatedDeepSleepMode = false;
2573         }
2574         Slogf.i(TAG, "Exit Deep Sleep simulation");
2575     }
2576 
getMaxSuspendWaitDurationConfig()2577     private int getMaxSuspendWaitDurationConfig() {
2578         return mContext.getResources().getInteger(R.integer.config_maxSuspendWaitDuration);
2579     }
2580 
isWifiAdjustmentForSuspendConfig()2581     private boolean isWifiAdjustmentForSuspendConfig() {
2582         return mContext.getResources().getBoolean(R.bool.config_wifiAdjustmentForSuspend);
2583     }
2584 
getPreShutdownPrepareTimeoutConfig()2585     private int getPreShutdownPrepareTimeoutConfig() {
2586         return getCompletionWaitTimeoutConfig(R.integer.config_preShutdownPrepareTimeout);
2587     }
2588 
getShutdownEnterTimeoutConfig()2589     private int getShutdownEnterTimeoutConfig() {
2590         return getCompletionWaitTimeoutConfig(R.integer.config_shutdownEnterTimeout);
2591     }
2592 
getPostShutdownEnterTimeoutConfig()2593     private int getPostShutdownEnterTimeoutConfig() {
2594         return getCompletionWaitTimeoutConfig(R.integer.config_postShutdownEnterTimeout);
2595     }
2596 
getCompletionWaitTimeoutConfig(int resourceId)2597     private int getCompletionWaitTimeoutConfig(int resourceId) {
2598         int timeout = mContext.getResources().getInteger(resourceId);
2599         return timeout >= 0 ? timeout : DEFAULT_COMPLETION_WAIT_TIMEOUT;
2600     }
2601 
actionOnFinishToString(int actionOnFinish)2602     private static String actionOnFinishToString(int actionOnFinish) {
2603         switch (actionOnFinish) {
2604             case ACTION_ON_FINISH_SHUTDOWN:
2605                 return "Shutdown";
2606             case ACTION_ON_FINISH_DEEP_SLEEP:
2607                 return "Deep sleep";
2608             case ACTION_ON_FINISH_HIBERNATION:
2609                 return "Hibernation";
2610             default:
2611                 return "Unknown";
2612         }
2613     }
2614 
waitForCompletionWithShutdownPostpone( @arPowerManager.CarPowerState int carPowerStateListenerState, long timeoutMs, Runnable taskAtCompletion, long intervalMs)2615     private void waitForCompletionWithShutdownPostpone(
2616             @CarPowerManager.CarPowerState int carPowerStateListenerState, long timeoutMs,
2617             Runnable taskAtCompletion, long intervalMs) {
2618         Runnable taskAtInterval = () -> {
2619             mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS);
2620         };
2621 
2622         Slogf.i(TAG, "Start waiting for listener completion for %s",
2623                 powerStateToString(carPowerStateListenerState));
2624 
2625         waitForCompletion(taskAtCompletion, taskAtInterval, timeoutMs, intervalMs);
2626     }
2627 }
2628