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