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.car.hardware.power.PowerComponentUtil.FIRST_POWER_COMPONENT;
22 import static android.car.hardware.power.PowerComponentUtil.LAST_POWER_COMPONENT;
23 import static android.net.ConnectivityManager.TETHERING_WIFI;
24 
25 import static com.android.car.hal.PowerHalService.BOOTUP_REASON_SYSTEM_ENTER_GARAGE_MODE;
26 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
27 
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.app.ActivityManager;
31 import android.automotive.powerpolicy.internal.ICarPowerPolicyDelegate;
32 import android.automotive.powerpolicy.internal.ICarPowerPolicyDelegateCallback;
33 import android.automotive.powerpolicy.internal.PowerPolicyFailureReason;
34 import android.automotive.powerpolicy.internal.PowerPolicyInitData;
35 import android.car.Car;
36 import android.car.CarOccupantZoneManager;
37 import android.car.ICarResultReceiver;
38 import android.car.builtin.app.ActivityManagerHelper;
39 import android.car.builtin.content.pm.PackageManagerHelper;
40 import android.car.builtin.os.BuildHelper;
41 import android.car.builtin.os.HandlerHelper;
42 import android.car.builtin.os.ServiceManagerHelper;
43 import android.car.builtin.os.UserManagerHelper;
44 import android.car.builtin.util.EventLogHelper;
45 import android.car.builtin.util.Slogf;
46 import android.car.feature.FeatureFlags;
47 import android.car.feature.FeatureFlagsImpl;
48 import android.car.hardware.power.CarPowerManager;
49 import android.car.hardware.power.CarPowerPolicy;
50 import android.car.hardware.power.CarPowerPolicyFilter;
51 import android.car.hardware.power.ICarPower;
52 import android.car.hardware.power.ICarPowerPolicyListener;
53 import android.car.hardware.power.ICarPowerStateListener;
54 import android.car.hardware.power.PowerComponentUtil;
55 import android.car.remoteaccess.CarRemoteAccessManager;
56 import android.content.ComponentName;
57 import android.content.Context;
58 import android.content.Intent;
59 import android.content.res.Resources;
60 import android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification;
61 import android.frameworks.automotive.powerpolicy.internal.PolicyState;
62 import android.hardware.automotive.vehicle.VehicleApPowerStateReport;
63 import android.hardware.automotive.vehicle.VehicleApPowerStateReq;
64 import android.hardware.automotive.vehicle.VehicleApPowerStateShutdownParam;
65 import android.hardware.display.DisplayManager;
66 import android.net.TetheringManager;
67 import android.net.TetheringManager.TetheringRequest;
68 import android.net.wifi.WifiManager;
69 import android.os.Binder;
70 import android.os.Handler;
71 import android.os.HandlerThread;
72 import android.os.IBinder;
73 import android.os.IInterface;
74 import android.os.Looper;
75 import android.os.Message;
76 import android.os.PowerManager;
77 import android.os.Process;
78 import android.os.RemoteCallbackList;
79 import android.os.RemoteException;
80 import android.os.SystemClock;
81 import android.os.SystemProperties;
82 import android.os.UserHandle;
83 import android.os.UserManager;
84 import android.util.ArraySet;
85 import android.util.AtomicFile;
86 import android.util.SparseArray;
87 import android.util.proto.ProtoOutputStream;
88 import android.view.Display;
89 
90 import com.android.car.CarLocalServices;
91 import com.android.car.CarLog;
92 import com.android.car.CarOccupantZoneService;
93 import com.android.car.CarServiceBase;
94 import com.android.car.CarServiceUtils;
95 import com.android.car.CarStatsLogHelper;
96 import com.android.car.ICarImpl;
97 import com.android.car.R;
98 import com.android.car.hal.PowerHalService;
99 import com.android.car.hal.PowerHalService.BootupReason;
100 import com.android.car.hal.PowerHalService.PowerState;
101 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
102 import com.android.car.internal.util.DebugUtils;
103 import com.android.car.internal.util.IndentingPrintWriter;
104 import com.android.car.internal.util.Lists;
105 import com.android.car.power.CarPowerDumpProto.CpmsStateProto;
106 import com.android.car.systeminterface.SystemInterface;
107 import com.android.car.user.CarUserNoticeService;
108 import com.android.car.user.CarUserService;
109 import com.android.car.user.UserHandleHelper;
110 import com.android.internal.annotations.GuardedBy;
111 import com.android.internal.annotations.VisibleForTesting;
112 import com.android.internal.util.Preconditions;
113 
114 import org.xmlpull.v1.XmlPullParserException;
115 
116 import java.io.BufferedReader;
117 import java.io.BufferedWriter;
118 import java.io.File;
119 import java.io.FileOutputStream;
120 import java.io.IOException;
121 import java.io.InputStream;
122 import java.io.InputStreamReader;
123 import java.io.OutputStreamWriter;
124 import java.lang.ref.WeakReference;
125 import java.nio.charset.StandardCharsets;
126 import java.util.ArrayList;
127 import java.util.Collection;
128 import java.util.LinkedList;
129 import java.util.List;
130 import java.util.Objects;
131 import java.util.concurrent.CountDownLatch;
132 import java.util.concurrent.ExecutorService;
133 import java.util.concurrent.Executors;
134 import java.util.concurrent.Semaphore;
135 import java.util.concurrent.TimeUnit;
136 import java.util.concurrent.atomic.AtomicBoolean;
137 import java.util.concurrent.atomic.AtomicInteger;
138 import java.util.function.BiFunction;
139 import java.util.function.Consumer;
140 
141 /**
142  * Power Management service class for cars. Controls the power states and interacts with other
143  * parts of the system to ensure its own state.
144  */
145 public class CarPowerManagementService extends ICarPower.Stub implements
146         CarServiceBase, PowerHalService.PowerEventListener {
147     public static final String SILENT_MODE_FORCED_SILENT =
148             SilentModeHandler.SILENT_MODE_FORCED_SILENT;
149     public static final String SILENT_MODE_FORCED_NON_SILENT =
150             SilentModeHandler.SILENT_MODE_FORCED_NON_SILENT;
151     public static final String SILENT_MODE_NON_FORCED = SilentModeHandler.SILENT_MODE_NON_FORCED;
152 
153     public static final long INVALID_TIMEOUT = -1L;
154 
155     public static final int NO_WAKEUP_BY_TIMER = -1;
156 
157     static final String TAG = CarLog.tagFor(CarPowerManagementService.class);
158 
159     private static final String WIFI_STATE_FILENAME = "wifi_state";
160     private static final String TETHERING_STATE_FILENAME = "tethering_state";
161     private static final String COMPONENT_STATE_MODIFIED = "forcibly_disabled";
162     private static final String COMPONENT_STATE_ORIGINAL = "original";
163     // If Suspend to RAM fails, we retry with an exponential back-off:
164     // The wait interval will be 10 msec, 20 msec, 40 msec, ...
165     // Once the wait interval goes beyond 100 msec, it is fixed at 100 msec.
166     private static final long INITIAL_SUSPEND_RETRY_INTERVAL_MS = 10;
167     private static final long MAX_RETRY_INTERVAL_MS = 100;
168     // Minimum and maximum wait duration before the system goes into Suspend to RAM.
169     private static final long MIN_SUSPEND_WAIT_DURATION_MS = 0;
170     private static final long MAX_SUSPEND_WAIT_DURATION_MS = 3 * 60 * 1000;
171 
172     private static final long CAR_POWER_POLICY_DAEMON_FIND_MARGINAL_TIME_MS = 300;
173     private static final long CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS = 500;
174     private static final int CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY = 3;
175     private static final long CAR_POWER_POLICY_DEFINITION_TIMEOUT_MS = 500;
176     // TODO(b/286303350): remove once power policy refactor complete, replace w/refactored version
177     private static final String CAR_POWER_POLICY_DAEMON_INTERFACE =
178             "android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification/"
179                     + "default";
180     private static final String REFACTORED_CAR_POWER_POLICY_DAEMON_INTERFACE =
181             "android.automotive.powerpolicy.internal.ICarPowerPolicyDelegate/default";
182 
183     // TODO:  Make this OEM configurable.
184     private static final int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
185     private static final int SHUTDOWN_EXTEND_MAX_MS = 5000;
186 
187     // maxGarageModeRunningDurationInSecs should be equal or greater than this. 15 min for now.
188     private static final int MIN_MAX_GARAGE_MODE_DURATION_MS = 15 * 60 * 1000;
189 
190     // in secs
191     private static final String PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE =
192             "android.car.garagemodeduration";
193     // Constants for action on finish
194     private static final int ACTION_ON_FINISH_SHUTDOWN = 0;
195     private static final int ACTION_ON_FINISH_DEEP_SLEEP = 1;
196     private static final int ACTION_ON_FINISH_HIBERNATION = 2;
197 
198     // Default timeout for listener completion during shutdown.
199     private static final int DEFAULT_COMPLETION_WAIT_TIMEOUT = 5_000;
200 
201     // Default timeout for power policy change requests
202     private static final int DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS = 5_000;
203 
204     private static final int INDEX_WAIT_FOR_VHAL = 0;
205     private static final int INDEX_ON = 1;
206 
207     private final Object mLock = new Object();
208     private final Object mSimulationWaitObject = new Object();
209 
210     private final Context mContext;
211     private final PowerHalService mHal;
212     private final SystemInterface mSystemInterface;
213     private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
214             getClass().getSimpleName());
215     private final PowerHandler mHandler = new PowerHandler(mHandlerThread.getLooper(), this);
216     private final HandlerThread mBroadcastHandlerThread = CarServiceUtils.getHandlerThread(
217             getClass().getSimpleName() + " broadcasts");
218     private final Handler mBroadcastHandler = new Handler(mBroadcastHandlerThread.getLooper());
219     // The listeners that complete simply by returning from onStateChanged()
220     private final PowerManagerCallbackList<ICarPowerStateListener> mPowerManagerListeners =
221             new PowerManagerCallbackList<>(
222                     l -> CarPowerManagementService.this.doUnregisterListener(l));
223     // The listeners that must indicate asynchronous completion by calling finished().
224     private final PowerManagerCallbackList<ICarPowerStateListener>
225             mPowerManagerListenersWithCompletion = new PowerManagerCallbackList<>(
226                     l -> CarPowerManagementService.this.doUnregisterListener(l));
227     private final AtomicInteger mPolicyRequestIdCounter = new AtomicInteger(0);
228     // The internal listeners that must indicates asynchronous completion by calling
229     // completeStateChangeHandling(). Note that they are not binder objects.
230     @GuardedBy("mLock")
231     private final ArrayList<ICarPowerStateListener> mInternalPowerListeners = new ArrayList<>();
232 
233     @GuardedBy("mLock")
234     private final ArraySet<IBinder> mListenersWeAreWaitingFor = new ArraySet<>();
235     @GuardedBy("mLock")
236     private final LinkedList<CpmsState> mPendingPowerStates = new LinkedList<>();
237     @GuardedBy("mLock")
238     private final SparseArray<AsyncPolicyRequest> mRequestIdToPolicyRequest = new SparseArray<>();
239     private final UserManager mUserManager;
240     private final CarUserService mUserService;
241     private final WifiManager mWifiManager;
242     private final TetheringManager mTetheringManager;
243     private final AtomicFile mWifiStateFile;
244     private final AtomicFile mTetheringStateFile;
245     private final boolean mWifiAdjustmentForSuspend;
246 
247     // This is a temp work-around to reduce user switching delay after wake-up.
248     private final boolean mSwitchGuestUserBeforeSleep;
249 
250     // CPMS tries to enter Suspend to RAM within the duration specified at
251     // mMaxSuspendWaitDurationMs. The default max duration is MAX_SUSPEND_WAIT_DRATION, and can be
252     // overridden by setting config_maxSuspendWaitDuration in an overrlay resource.
253     // The valid range is MIN_SUSPEND_WAIT_DRATION to MAX_SUSPEND_WAIT_DURATION.
254     private final long mMaxSuspendWaitDurationMs;
255 
256     @GuardedBy("mSimulationWaitObject")
257     private boolean mWakeFromSimulatedSleep;
258     @GuardedBy("mSimulationWaitObject")
259     private boolean mInSimulatedDeepSleepMode;
260     @GuardedBy("mSimulationWaitObject")
261     private int mResumeDelayFromSimulatedSuspendSec = NO_WAKEUP_BY_TIMER;
262     @GuardedBy("mSimulationWaitObject")
263     private int mCancelDelayFromSimulatedSuspendSec = NO_WAKEUP_BY_TIMER;
264     @GuardedBy("mSimulationWaitObject")
265     private boolean mFreeMemoryBeforeSuspend;
266 
267     @GuardedBy("mLock")
268     private CpmsState mCurrentState;
269     @GuardedBy("mLock")
270     private long mShutdownStartTime;
271     @GuardedBy("mLock")
272     private long mLastSleepEntryTime;
273 
274     @GuardedBy("mLock")
275     private int mNextWakeupSec;
276     @GuardedBy("mLock")
277     private int mActionOnFinish;
278     @GuardedBy("mLock")
279     private boolean mShutdownOnNextSuspend;
280     @GuardedBy("mLock")
281     private boolean mShouldResumeUserService;
282     @GuardedBy("mLock")
283     private int mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS;
284     @GuardedBy("mLock")
285     private int mShutdownPollingIntervalMs = SHUTDOWN_POLLING_INTERVAL_MS;
286     @GuardedBy("mLock")
287     private boolean mRebootAfterGarageMode;
288     @GuardedBy("mLock")
289     private boolean mGarageModeShouldExitImmediately;
290     // TODO(b/286303350): remove once power policy refactor complete
291     @GuardedBy("mLock")
292     private ICarPowerPolicySystemNotification mCarPowerPolicyDaemon;
293     // TODO(b/286303350): rename "mCarPowerPolicyDaemon" once power policy refactor complete
294     @GuardedBy("mLock")
295     private ICarPowerPolicyDelegate mRefactoredCarPowerPolicyDaemon;
296     @GuardedBy("mLock")
297     private boolean mConnectionInProgress;
298     // After ICarPowerPolicyDelegateCallback is set, mReadyForCallback is set to true;
299     private AtomicBoolean mReadyForCallback = new AtomicBoolean(false);
300     private BinderHandler mBinderHandler;
301     private boolean mPowerPoliciesInitialized;
302     // TODO(b/286303350): remove after policy refactor, since daemon will be source of truth
303     @GuardedBy("mLock")
304     private String mCurrentPowerPolicyId;
305     // TODO(b/286303350): remove after policy refactor, since daemon will control power policy
306     @GuardedBy("mLock")
307     private String mPendingPowerPolicyId;
308     @GuardedBy("mLock")
309     private String mCurrentPowerPolicyGroupId;
310     @GuardedBy("mLock")
311     private boolean mIsPowerPolicyLocked;
312     // TODO(b/286303350): remove after policy refactor, since daemon will control power policy
313     @GuardedBy("mLock")
314     private boolean mHasControlOverDaemon;
315     private final CountDownLatch mPowerPolicyInitializationLatch = new CountDownLatch(1);
316     @GuardedBy("mLock")
317     private CarPowerPolicy mCurrentAccumulatedPowerPolicy = getInitialAccumulatedPowerPolicy();
318     private AtomicBoolean mIsListenerWaitingCancelled = new AtomicBoolean(false);
319     private final Semaphore mListenerCompletionSem = new Semaphore(/* permits= */ 0);
320     @GuardedBy("mLock")
321     @CarPowerManager.CarPowerState
322     private int mStateForCompletion = CarPowerManager.STATE_INVALID;
323     @GuardedBy("mLock")
324     @CarRemoteAccessManager.NextPowerState
325     private int mLastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_OFF;
326 
327     @GuardedBy("mLock")
328     @Nullable
329     private ICarResultReceiver mFactoryResetCallback;
330     @GuardedBy("mLock")
331     private boolean mIsEmergencyShutdown;
332 
333     private final PowerManagerCallbackList<ICarPowerPolicyListener> mPowerPolicyListeners =
334             new PowerManagerCallbackList<>(
335                     l -> CarPowerManagementService.this.mPowerPolicyListeners.unregister(l));
336 
337     private final PowerComponentHandler mPowerComponentHandler;
338     private final PolicyReader mPolicyReader = new PolicyReader();
339     private final SilentModeHandler mSilentModeHandler;
340     private final ScreenOffHandler mScreenOffHandler;
341 
342     // Allows for injecting feature flag values during testing
343     private FeatureFlags mFeatureFlags = new FeatureFlagsImpl();
344     @GuardedBy("mSimulationWaitObject")
345     private boolean mBlockFromSimulatedCancelEvent;
346 
347     @VisibleForTesting
readPowerPolicyFromXml(InputStream inputStream)348     void readPowerPolicyFromXml(InputStream inputStream)
349             throws IOException, PolicyReader.PolicyXmlException, XmlPullParserException {
350         mPolicyReader.readPowerPolicyFromXml(inputStream);
351         Integer[] customComponents =
352                 new Integer[mPolicyReader.getCustomComponents().values().size()];
353         mPolicyReader.getCustomComponents().values().toArray(customComponents);
354         mPowerComponentHandler.registerCustomComponents(customComponents);
355     }
356 
357     interface ActionOnDeath<T extends IInterface> {
take(T listener)358         void take(T listener);
359     }
360 
361     private static final class PowerManagerCallbackList<T extends IInterface> extends
362             RemoteCallbackList<T> {
363         private ActionOnDeath<T> mActionOnDeath;
364 
PowerManagerCallbackList(ActionOnDeath<T> action)365         PowerManagerCallbackList(ActionOnDeath<T> action) {
366             mActionOnDeath = action;
367         }
368 
369         /**
370          * Old version of {@link #onCallbackDied(E, Object)} that
371          * does not provide a cookie.
372          */
373         @Override
onCallbackDied(T listener)374         public void onCallbackDied(T listener) {
375             Slogf.i(TAG, "binderDied %s", listener.asBinder());
376             mActionOnDeath.take(listener);
377         }
378     }
379 
380     /**
381      * Builder for {@link android.car.power.CarPowerManagementService}.
382      */
383     public static final class Builder {
384         private Context mContext;
385         private PowerHalService mPowerHalService;
386         private SystemInterface mSystemInterface;
387         private UserManager mUserManager;
388         private CarUserService mCarUserService;
389         private PowerComponentHandler mPowerComponentHandler;
390         private @Nullable IInterface mPowerPolicyDaemon;
391         private @Nullable FeatureFlags mFeatureFlags;
392         private @Nullable ScreenOffHandler mScreenOffHandler;
393         private @Nullable String mSilentModeHwStatePath;
394         private @Nullable String mSilentModeKernelStatePath;
395         private @Nullable String mBootReason;
396         private Resources mResources;
397         private boolean mBuilt;
398 
399         /**
400          * Sets the {@link Context}.
401          */
setContext(Context context)402         public Builder setContext(Context context) {
403             mContext = context;
404             return this;
405         }
406 
407         /**
408          * Sets the {@link PowerHalService}.
409          */
setPowerHalService(PowerHalService powerHalService)410         public Builder setPowerHalService(PowerHalService powerHalService) {
411             mPowerHalService = powerHalService;
412             return this;
413         }
414 
415         /**
416          * Sets the {@link SystemInterface}.
417          */
setSystemInterface(SystemInterface systemInterface)418         public Builder setSystemInterface(SystemInterface systemInterface) {
419             mSystemInterface = systemInterface;
420             return this;
421         }
422 
423         /**
424          * Sets the {@link CarUserService}.
425          */
setCarUserService(CarUserService carUserService)426         public Builder setCarUserService(CarUserService carUserService) {
427             mCarUserService = carUserService;
428             return this;
429         }
430 
431         /**
432          * Sets the {@link IInterface} for power policy daemon.
433          */
setPowerPolicyDaemon(@ullable IInterface powerPolicyDaemon)434         public Builder setPowerPolicyDaemon(@Nullable IInterface powerPolicyDaemon) {
435             mPowerPolicyDaemon = powerPolicyDaemon;
436             return this;
437         }
438 
439         /**
440          * Builds the object.
441          */
build()442         public CarPowerManagementService build() {
443             if (mBuilt) {
444                 throw new IllegalStateException("Only allowed to be built once");
445             }
446             mBuilt = true;
447             return new CarPowerManagementService(this);
448         }
449 
450         /**
451          * Sets the {@link PowerComponentHandler}.
452          */
453         @VisibleForTesting
setPowerComponentHandler(PowerComponentHandler powerComponentHandler)454         public Builder setPowerComponentHandler(PowerComponentHandler powerComponentHandler) {
455             mPowerComponentHandler = powerComponentHandler;
456             return this;
457         }
458 
459         /**
460          * Sets the {@link UserManager}.
461          */
462         @VisibleForTesting
setUserManager(UserManager userManager)463         public Builder setUserManager(UserManager userManager) {
464             mUserManager = userManager;
465             return this;
466         }
467 
468         /**
469          * Sets the {@link FeatureFlags}.
470          */
471         @VisibleForTesting
setFeatureFlags(FeatureFlags featureFlags)472         public Builder setFeatureFlags(FeatureFlags featureFlags) {
473             mFeatureFlags = featureFlags;
474             return this;
475         }
476 
477         /**
478          * Sets the {@link ScreenOffHandler}.
479          */
480         @VisibleForTesting
setScreenOffHandler(ScreenOffHandler screenOffHandler)481         public Builder setScreenOffHandler(ScreenOffHandler screenOffHandler) {
482             mScreenOffHandler = screenOffHandler;
483             return this;
484         }
485 
486         /**
487          * Sets the silent mode hardware state path.
488          */
489         @VisibleForTesting
setSilentModeHwStatePath(String silentModeHwStatePath)490         public Builder setSilentModeHwStatePath(String silentModeHwStatePath) {
491             mSilentModeHwStatePath = silentModeHwStatePath;
492             return this;
493         }
494 
495         /**
496          * Sets the silent mode kernel state path.
497          */
498         @VisibleForTesting
setSilentModeKernelStatePath(String silentModeKernelStatePath)499         public Builder setSilentModeKernelStatePath(String silentModeKernelStatePath) {
500             mSilentModeKernelStatePath = silentModeKernelStatePath;
501             return this;
502         }
503 
504         /**
505          * Sets the boot reason.
506          */
507         @VisibleForTesting
setBootReason(String bootReason)508         public Builder setBootReason(String bootReason) {
509             mBootReason = bootReason;
510             return this;
511         }
512 
513         /**
514          * Sets the {@link Resources}.
515          */
516         @VisibleForTesting
setResources(Resources resources)517         public Builder setResources(Resources resources) {
518             mResources = resources;
519             return this;
520         }
521     }
522 
CarPowerManagementService(Context context, PowerHalService powerHalService, SystemInterface systemInterface, CarUserService carUserService, IInterface powerPolicyDaemon)523     public CarPowerManagementService(Context context, PowerHalService powerHalService,
524             SystemInterface systemInterface, CarUserService carUserService,
525             IInterface powerPolicyDaemon) {
526         this(new Builder().setContext(context).setPowerHalService(powerHalService)
527                 .setSystemInterface(systemInterface).setCarUserService(carUserService)
528                 .setPowerPolicyDaemon(powerPolicyDaemon));
529     }
530 
CarPowerManagementService(Builder builder)531     private CarPowerManagementService(Builder builder) {
532         mContext = Objects.requireNonNull(builder.mContext);
533         mHal = Objects.requireNonNull(builder.mPowerHalService);
534         mSystemInterface = Objects.requireNonNull(builder.mSystemInterface);
535         mUserManager = Objects.requireNonNullElseGet(builder.mUserManager,
536                 () -> builder.mContext.getSystemService(UserManager.class));
537         Resources resources =  Objects.requireNonNullElseGet(builder.mResources,
538                 () -> builder.mContext.getResources());
539         mShutdownPrepareTimeMs = resources.getInteger(
540                 R.integer.maxGarageModeRunningDurationInSecs) * 1000;
541         mSwitchGuestUserBeforeSleep = resources.getBoolean(
542                 R.bool.config_switchGuestUserBeforeGoingSleep);
543         if (mShutdownPrepareTimeMs < MIN_MAX_GARAGE_MODE_DURATION_MS) {
544             Slogf.w(TAG,
545                     "maxGarageModeRunningDurationInSecs smaller than minimum required, "
546                             + "resource:%d(ms) while should exceed:%d(ms), Ignore resource.",
547                     mShutdownPrepareTimeMs, MIN_MAX_GARAGE_MODE_DURATION_MS);
548             mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS;
549         }
550         mUserService = Objects.requireNonNull(builder.mCarUserService);
551         if (builder.mFeatureFlags != null) {
552             mFeatureFlags = builder.mFeatureFlags;
553         }
554         // In a real situation, this should be null.
555         IInterface powerPolicyDaemon = builder.mPowerPolicyDaemon;
556         if (mFeatureFlags.carPowerPolicyRefactoring()) {
557             mRefactoredCarPowerPolicyDaemon = (ICarPowerPolicyDelegate) powerPolicyDaemon;
558             mPowerPoliciesInitialized = false;
559         } else {
560             mCarPowerPolicyDaemon = (ICarPowerPolicySystemNotification) powerPolicyDaemon;
561             if (powerPolicyDaemon != null) {
562                 // For testing purpose
563                 mHasControlOverDaemon = true;
564             }
565         }
566         mWifiManager = mContext.getSystemService(WifiManager.class);
567         mTetheringManager = mContext.getSystemService(TetheringManager.class);
568         mWifiStateFile = new AtomicFile(
569                 new File(mSystemInterface.getSystemCarDir(), WIFI_STATE_FILENAME));
570         mTetheringStateFile = new AtomicFile(
571                 new File(mSystemInterface.getSystemCarDir(), TETHERING_STATE_FILENAME));
572         mWifiAdjustmentForSuspend = isWifiAdjustmentForSuspendConfig();
573         mPowerComponentHandler = Objects.requireNonNullElseGet(builder.mPowerComponentHandler,
574                 () -> new PowerComponentHandler(mContext, mSystemInterface));
575         mSilentModeHandler = new SilentModeHandler(this, mFeatureFlags,
576                 builder.mSilentModeHwStatePath, builder.mSilentModeKernelStatePath,
577                 builder.mBootReason);
578         mMaxSuspendWaitDurationMs = Math.max(MIN_SUSPEND_WAIT_DURATION_MS,
579                 Math.min(getMaxSuspendWaitDurationConfig(), MAX_SUSPEND_WAIT_DURATION_MS));
580         mScreenOffHandler = Objects.requireNonNullElseGet(builder.mScreenOffHandler, () ->
581                 new ScreenOffHandler(mContext, mSystemInterface, mHandler.getLooper()));
582     }
583 
584     /**
585      * Overrides timers to keep testing time short.
586      *
587      * <p>Passing in {@code 0} resets the value to the default.
588      */
589     @VisibleForTesting
setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs)590     public void setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs) {
591         synchronized (mLock) {
592             mShutdownPollingIntervalMs =
593                     (pollingIntervalMs == 0) ? SHUTDOWN_POLLING_INTERVAL_MS : pollingIntervalMs;
594             mShutdownPrepareTimeMs =
595                     (shutdownTimeoutMs == 0) ? SHUTDOWN_EXTEND_MAX_MS : shutdownTimeoutMs;
596         }
597     }
598 
599     @VisibleForTesting
getHandlerThread()600     protected HandlerThread getHandlerThread() {
601         return mHandlerThread;
602     }
603 
604     @Override
init()605     public void init() {
606         mPolicyReader.init(mFeatureFlags);
607         mPowerComponentHandler.init(mPolicyReader.getCustomComponents());
608         mHal.setListener(this);
609         mSystemInterface.init(this, mUserService);
610         mScreenOffHandler.init();
611         if (mHal.isPowerStateSupported()) {
612             // Initialize CPMS in WAIT_FOR_VHAL state
613             onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, CarPowerManager.STATE_WAIT_FOR_VHAL);
614         } else {
615             Slogf.w(TAG, "Vehicle hal does not support power state yet.");
616             onApPowerStateChange(CpmsState.ON, CarPowerManager.STATE_ON);
617         }
618         mSystemInterface.startDisplayStateMonitoring();
619         connectToPowerPolicyDaemon();
620     }
621 
622     @Override
release()623     public void release() {
624         if (mBinderHandler != null) {
625             mBinderHandler.unlinkToDeath();
626         }
627         mReadyForCallback.set(false);
628         synchronized (mLock) {
629             clearWaitingForCompletion(/*clearQueue=*/false);
630             mCurrentState = null;
631             if (mFeatureFlags.carPowerPolicyRefactoring()) {
632                 mRefactoredCarPowerPolicyDaemon = null;
633             } else {
634                 mCarPowerPolicyDaemon = null;
635             }
636             mHandler.cancelAll();
637             mListenersWeAreWaitingFor.clear();
638         }
639         mSystemInterface.stopDisplayStateMonitoring();
640         mPowerManagerListeners.kill();
641         mPowerPolicyListeners.kill();
642         forEachDisplay(mContext, mSystemInterface::releaseAllWakeLocks);
643     }
644 
645     @Override
646     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dump(IndentingPrintWriter writer)647     public void dump(IndentingPrintWriter writer) {
648         synchronized (mLock) {
649             writer.println("*CarPowerManagementService*");
650             writer.printf("mCurrentState: %s\n", mCurrentState);
651             writer.printf("mShutdownStartTime: %d\n", mShutdownStartTime);
652             writer.printf("mLastSleepEntryTime: %d\n", mLastSleepEntryTime);
653             writer.printf("mNextWakeupSec: %d\n", mNextWakeupSec);
654             writer.printf("mShutdownOnNextSuspend: %b\n", mShutdownOnNextSuspend);
655             writer.printf("mActionOnFinish: %s\n", actionOnFinishToString(mActionOnFinish));
656             writer.printf("mShutdownPollingIntervalMs: %d\n", mShutdownPollingIntervalMs);
657             writer.printf("mShutdownPrepareTimeMs: %d\n", mShutdownPrepareTimeMs);
658             writer.printf("mRebootAfterGarageMode: %b\n", mRebootAfterGarageMode);
659             writer.printf("mSwitchGuestUserBeforeSleep: %b\n", mSwitchGuestUserBeforeSleep);
660             writer.printf("mCurrentPowerPolicyId: %s\n", mCurrentPowerPolicyId);
661             writer.printf("mPendingPowerPolicyId: %s\n", mPendingPowerPolicyId);
662             writer.printf("mCurrentPowerPolicyGroupId: %s\n", mCurrentPowerPolicyGroupId);
663             writer.printf("mIsPowerPolicyLocked: %b\n", mIsPowerPolicyLocked);
664             writer.printf("mMaxSuspendWaitDurationMs: %d\n", mMaxSuspendWaitDurationMs);
665             writer.printf("config_maxSuspendWaitDuration: %d\n", getMaxSuspendWaitDurationConfig());
666             writer.printf("mWifiStateFile: %s\n", mWifiStateFile);
667             writer.printf("mTetheringStateFile: %s\n", mTetheringStateFile);
668             writer.printf("mWifiAdjustmentForSuspend: %b\n", mWifiAdjustmentForSuspend);
669             writer.printf("# of power policy change listener: %d\n",
670                     mPowerPolicyListeners.getRegisteredCallbackCount());
671             writer.printf("mFactoryResetCallback: %s\n", mFactoryResetCallback);
672             writer.printf("mIsListenerWaitingCancelled: %b\n", mIsListenerWaitingCancelled.get());
673             writer.printf("kernel support S2R: %b\n",
674                     mSystemInterface.isSystemSupportingDeepSleep());
675             writer.printf("kernel support S2D: %b\n",
676                     mSystemInterface.isSystemSupportingHibernation());
677             writer.printf("mLastShutdownState: %d\n", mLastShutdownState);
678             writer.printf("mReadyForCallback: %b\n", mReadyForCallback.get());
679         }
680 
681         synchronized (mSimulationWaitObject) {
682             writer.printf("mWakeFromSimulatedSleep: %b\n", mWakeFromSimulatedSleep);
683             writer.printf("mInSimulatedDeepSleepMode: %b\n", mInSimulatedDeepSleepMode);
684             writer.printf("mResumeDelayFromSimulatedSuspendSec: %d\n",
685                     mResumeDelayFromSimulatedSuspendSec);
686             writer.printf("mFreeMemoryBeforeSuspend: %b\n", mFreeMemoryBeforeSuspend);
687         }
688 
689         mPolicyReader.dump(writer);
690         mPowerComponentHandler.dump(writer);
691         mSilentModeHandler.dump(writer);
692         mScreenOffHandler.dump(writer);
693     }
694 
695     @Override
696     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dumpProto(ProtoOutputStream proto)697     public void dumpProto(ProtoOutputStream proto) {
698         synchronized (mLock) {
699             long currentStateToken = proto.start(CarPowerDumpProto.CURRENT_STATE);
700             proto.write(CpmsStateProto.CAN_POSTPONE, mCurrentState.mCanPostpone);
701             proto.write(CpmsStateProto.CAR_POWER_MANAGER_STATE,
702                     mCurrentState.mCarPowerStateListenerState);
703             proto.write(CpmsStateProto.SHUTDOWN_TYPE, mCurrentState.mShutdownType);
704             proto.write(CpmsStateProto.STATE, mCurrentState.mState);
705             proto.write(CpmsStateProto.STATE_NAME, mCurrentState.stateToString());
706             proto.end(currentStateToken);
707             proto.write(CarPowerDumpProto.SHUTDOWN_START_TIME, mShutdownStartTime);
708             proto.write(CarPowerDumpProto.LAST_SLEEP_ENTRY_TIME, mLastSleepEntryTime);
709             proto.write(CarPowerDumpProto.NEXT_WAKEUP_SEC, mNextWakeupSec);
710             proto.write(CarPowerDumpProto.SHUTDOWN_ON_NEXT_SUSPEND, mShutdownOnNextSuspend);
711             proto.write(
712                     CarPowerDumpProto.ACTION_ON_FINISH, actionOnFinishToString(mActionOnFinish));
713             proto.write(CarPowerDumpProto.SHUTDOWN_POLLING_INTERVAL_MS, mShutdownPollingIntervalMs);
714             proto.write(CarPowerDumpProto.SHUTDOWN_PREPARE_TIME_MS, mShutdownPrepareTimeMs);
715             proto.write(CarPowerDumpProto.REBOOT_AFTER_GARAGE_MODE, mRebootAfterGarageMode);
716             proto.write(
717                     CarPowerDumpProto.SWITCH_GUEST_USER_BEFORE_SLEEP, mSwitchGuestUserBeforeSleep);
718             proto.write(CarPowerDumpProto.CURRENT_POWER_POLICY_ID, mCurrentPowerPolicyId);
719             proto.write(CarPowerDumpProto.PENDING_POWER_POLICY_ID, mPendingPowerPolicyId);
720             proto.write(
721                     CarPowerDumpProto.CURRENT_POWER_POLICY_GROUP_ID, mCurrentPowerPolicyGroupId);
722             proto.write(CarPowerDumpProto.IS_POWER_POLICY_LOCKED, mIsPowerPolicyLocked);
723             proto.write(CarPowerDumpProto.MAX_SUSPEND_WAIT_DURATION_MS, mMaxSuspendWaitDurationMs);
724             proto.write(CarPowerDumpProto.MAX_SUSPEND_WAIT_DURATION_CONFIG,
725                     getMaxSuspendWaitDurationConfig());
726             proto.write(CarPowerDumpProto.WIFI_STATE_FILE, mWifiStateFile.toString());
727             proto.write(CarPowerDumpProto.TETHERING_STATE_FILE, mTetheringStateFile.toString());
728             proto.write(CarPowerDumpProto.WIFI_ADJUSTMENT_FOR_SUSPEND, mWifiAdjustmentForSuspend);
729             proto.write(CarPowerDumpProto.POWER_POLICY_LISTENERS,
730                     mPowerPolicyListeners.getRegisteredCallbackCount());
731             proto.write(CarPowerDumpProto.FACTORY_RESET_CALLBACK,
732                     mFactoryResetCallback != null ? mFactoryResetCallback.toString() : "");
733             proto.write(CarPowerDumpProto.IS_LISTENER_WAITING_CANCELLED,
734                     mIsListenerWaitingCancelled.get());
735             proto.write(CarPowerDumpProto.KERNEL_SUPPORTS_DEEP_SLEEP,
736                     mSystemInterface.isSystemSupportingDeepSleep());
737             proto.write(CarPowerDumpProto.KERNEL_SUPPORTS_HIBERNATION,
738                     mSystemInterface.isSystemSupportingHibernation());
739         }
740 
741         synchronized (mSimulationWaitObject) {
742             proto.write(CarPowerDumpProto.WAKE_FROM_SIMULATED_SLEEP, mWakeFromSimulatedSleep);
743             proto.write(CarPowerDumpProto.IN_SIMULATED_DEEP_SLEEP_MODE, mInSimulatedDeepSleepMode);
744             proto.write(CarPowerDumpProto.RESUME_DELAY_FROM_SIMULATED_SUSPEND_SEC,
745                     mResumeDelayFromSimulatedSuspendSec);
746             proto.write(CarPowerDumpProto.FREE_MEMORY_BEFORE_SUSPEND, mFreeMemoryBeforeSuspend);
747         }
748 
749         mPolicyReader.dumpProto(proto);
750         mPowerComponentHandler.dumpProto(proto);
751         mSilentModeHandler.dumpProto(proto);
752         mScreenOffHandler.dumpProto(proto);
753     }
754 
755     @Override
onApPowerStateChange(PowerState state)756     public void onApPowerStateChange(PowerState state) {
757         EventLogHelper.writeCarPowerManagerStateRequest(state.mState, state.mParam);
758         synchronized (mLock) {
759             mPendingPowerStates.addFirst(new CpmsState(state));
760             mLock.notifyAll();
761         }
762         mHandler.handlePowerStateChange();
763     }
764 
765     @VisibleForTesting
setStateForWakeUp()766     void setStateForWakeUp() {
767         mSilentModeHandler.init();
768         synchronized (mLock) {
769             mShouldResumeUserService = true;
770         }
771         handleWaitForVhal(new CpmsState(CpmsState.WAIT_FOR_VHAL,
772                 CarPowerManager.STATE_WAIT_FOR_VHAL, /* canPostpone= */ false));
773         Slogf.d(TAG,
774                 "setStateForTesting(): mShouldResumeUserService is set to false and power state "
775                         + "is switched "
776                         + "to Wait For Vhal");
777     }
778 
779     /**
780      * Initiate state change from CPMS directly.
781      */
onApPowerStateChange(int apState, @CarPowerManager.CarPowerState int carPowerStateListenerState)782     private void onApPowerStateChange(int apState,
783             @CarPowerManager.CarPowerState int carPowerStateListenerState) {
784         CpmsState newState = new CpmsState(apState, carPowerStateListenerState,
785                 /* canPostpone= */ false);
786         BiFunction<CpmsState, CpmsState, Boolean> eventFilter = null;
787 
788         // We are ready to shut down. Suppress this transition if
789         // there is a request to cancel the shutdown (WAIT_FOR_VHAL).
790         // Completely ignore this WAIT_FOR_FINISH
791         if (newState.mState == CpmsState.WAIT_FOR_FINISH) {
792             eventFilter = (stateToAdd, pendingSate) ->
793                     stateToAdd.mState == CpmsState.WAIT_FOR_FINISH
794                     && pendingSate.mState == CpmsState.WAIT_FOR_VHAL;
795         }
796 
797         // Check if there is another pending SHUTDOWN_PREPARE.
798         // This could happen, when another SHUTDOWN_PREPARE request is received from VHAL
799         // while notifying PRE_SHUTDOWN_PREPARE.
800         // If SHUTDOWN_PREPARE request already exist in the queue, and it skips Garage Mode,
801         // then newState is ignored .
802         if (newState.mState == CpmsState.SHUTDOWN_PREPARE) {
803             eventFilter = (stateToAdd, pendingState) ->
804                     pendingState.mState == CpmsState.SHUTDOWN_PREPARE
805                             && !pendingState.mCanPostpone
806                             && pendingState.mCarPowerStateListenerState
807                             == STATE_PRE_SHUTDOWN_PREPARE;
808         }
809 
810         synchronized (mLock) {
811             // If eventFilter exists, lets check if event that satisfies filter is in queue.
812             if (eventFilter != null) {
813                 for (int idx = 0; idx < mPendingPowerStates.size(); idx++) {
814                     CpmsState pendingState = mPendingPowerStates.get(idx);
815                     if (eventFilter.apply(newState, pendingState)) {
816                         return;
817                     }
818                 }
819             }
820             mPendingPowerStates.addFirst(newState);
821             mLock.notifyAll();
822         }
823         mHandler.handlePowerStateChange();
824     }
825 
doHandlePowerStateChange()826     private void doHandlePowerStateChange() {
827         CpmsState newState;
828         CpmsState prevState;
829         synchronized (mLock) {
830             prevState = mCurrentState;
831             newState = mPendingPowerStates.pollFirst();
832             if (newState == null) {
833                 Slogf.w(TAG, "No more power state to process");
834                 return;
835             }
836             Slogf.i(TAG, "doHandlePowerStateChange: newState=%s", newState.name());
837             if (!needPowerStateChangeLocked(newState)) {
838                 // We may need to process the pending power state request.
839                 if (!mPendingPowerStates.isEmpty()) {
840                     Slogf.i(TAG, "There is a pending power state change request. requesting the "
841                             + "processing...");
842                     mHandler.handlePowerStateChange();
843                 }
844                 return;
845             }
846 
847             // now real power change happens. Whatever was queued before should be all cancelled.
848             mPendingPowerStates.clear();
849 
850             // Received updated SHUTDOWN_PREPARE there could be several reasons for that
851             //  1. CPMS is in SHUTDOWN_PREPARE, and received state change to perform transition
852             //     from PRE_SHUTDOWN_PREPARE into SHUTDOWN_PREPARE
853             //  2. New SHUTDOWN_PREPARE request is received, and it is different from existing one.
854             if (newState.mState == CpmsState.SHUTDOWN_PREPARE && newState.mState == prevState.mState
855                     && newState.mCarPowerStateListenerState == STATE_PRE_SHUTDOWN_PREPARE) {
856                 // Nothing to do here, skipping clearing completion queue
857             } else {
858                 clearWaitingForCompletion(/*clearQueue=*/false);
859             }
860 
861             mCurrentState = newState;
862         }
863         mHandler.cancelProcessingComplete();
864 
865         Slogf.i(TAG, "setCurrentState %s", newState);
866         CarStatsLogHelper.logPowerState(newState.mState);
867         EventLogHelper.writeCarPowerManagerStateChange(newState.mState);
868         switch (newState.mState) {
869             case CpmsState.WAIT_FOR_VHAL:
870                 handleWaitForVhal(newState);
871                 break;
872             case CpmsState.ON:
873                 handleOn();
874                 break;
875             case CpmsState.SHUTDOWN_PREPARE:
876                 handleShutdownPrepare(newState, prevState);
877                 break;
878             case CpmsState.SIMULATE_SLEEP:
879             case CpmsState.SIMULATE_HIBERNATION:
880                 simulateShutdownPrepare(newState, prevState);
881                 break;
882             case CpmsState.WAIT_FOR_FINISH:
883                 handleWaitForFinish(newState);
884                 break;
885             case CpmsState.SUSPEND:
886                 // Received FINISH from VHAL
887                 handleFinish();
888                 break;
889             default:
890                 // Illegal state
891                 // TODO(b/202414427): Add handling of illegal state
892                 break;
893         }
894     }
895 
notifyPowerStateChangeToDaemon(@arPowerManager.CarPowerState int powerState)896     private void notifyPowerStateChangeToDaemon(@CarPowerManager.CarPowerState int powerState) {
897         ICarPowerPolicyDelegate daemon;
898         synchronized (mLock) {
899             daemon = mRefactoredCarPowerPolicyDaemon;
900         }
901         if (daemon == null) {
902             Slogf.e(TAG, "Failed to notify car power policy daemon of power state change, "
903                     + "daemon unavailable");
904             return;
905         }
906         notifyPowerStateChangeToDaemon(daemon, powerState);
907     }
908 
notifyPowerStateChangeToDaemon(ICarPowerPolicyDelegate daemon, @CarPowerManager.CarPowerState int powerState)909     private void notifyPowerStateChangeToDaemon(ICarPowerPolicyDelegate daemon,
910             @CarPowerManager.CarPowerState int powerState) {
911         Slogf.i(TAG, "Notifying CPPD of power state(%s)", powerStateToString(powerState));
912 
913         String powerStateName = powerStateToString(powerState);
914         if (!mReadyForCallback.get()) {
915             Slogf.w(TAG, "Cannot notify power state(%S) of CPPD: not ready for calling to CPPD",
916                     powerStateName);
917             return;
918         }
919         AsyncPolicyRequest request = generateAsyncPolicyRequest(
920                 DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS);
921         int requestId = request.getRequestId();
922         synchronized (mLock) {
923             mRequestIdToPolicyRequest.put(requestId, request);
924         }
925         try {
926             Slogf.i(TAG, "Request(%d) of applying power policy for power state(%s) to CPPD in "
927                     + "async", requestId, powerStateName);
928             daemon.applyPowerPolicyPerPowerStateChangeAsync(requestId, (byte) powerState);
929             boolean policyRequestServed = request.await();
930             if (!policyRequestServed) {
931                 Slogf.w(TAG, "Power policy request (ID: %d) for power state(%s) timed out after %d "
932                         + "ms", requestId, powerStateName, DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS);
933                 return;
934             }
935         } catch (IllegalArgumentException e) {
936             Slogf.w(TAG, e, "Failed to apply power policy for power state(%s)", powerStateName);
937             return;
938         } catch (InterruptedException e) {
939             Slogf.w(TAG, e, "Wait for power policy change request for power state(%s) interrupted",
940                     powerStateName);
941             Thread.currentThread().interrupt();
942             return;
943         } catch (RemoteException e) {
944             Slogf.w(TAG, e, "Failed to apply power policy for power state(%s), connection issue",
945                     powerStateName);
946             return;
947         } finally {
948             synchronized (mLock) {
949                 mRequestIdToPolicyRequest.remove(requestId);
950             }
951         }
952         if (!request.isSuccessful()) {
953             Slogf.w(TAG, "Failed to apply power policy for power state(%s), failure reason = %d",
954                     powerStateName, request.getFailureReason());
955             return;
956         }
957         if (request.isDeferred()) {
958             Slogf.i(TAG, "Applying power policy for power state(%s) is deferred", powerStateName);
959             return;
960         }
961         CarPowerPolicy accumulatedPolicy = request.getAccumulatedPolicy();
962         updateCurrentPowerPolicy(accumulatedPolicy);
963         notifyPowerPolicyChange(accumulatedPolicy);
964     }
965 
handleWaitForVhal(CpmsState state)966     private void handleWaitForVhal(CpmsState state) {
967         @CarPowerManager.CarPowerState int carPowerStateListenerState =
968                 state.mCarPowerStateListenerState;
969         // TODO(b/177478420): Restore Wifi, Audio, Location, and Bluetooth, if they are artificially
970         // modified for S2R.
971         mSilentModeHandler.querySilentModeHwState();
972 
973         if (mFeatureFlags.carPowerPolicyRefactoring()) {
974             notifyPowerStateChangeToDaemon(CarPowerManager.STATE_WAIT_FOR_VHAL);
975         } else {
976             applyDefaultPowerPolicyForState(CarPowerManager.STATE_WAIT_FOR_VHAL,
977                     PolicyReader.POWER_POLICY_ID_INITIAL_ON);
978             if (!mSilentModeHandler.isSilentMode()) {
979                 cancelPreemptivePowerPolicy();
980             }
981         }
982 
983         sendPowerManagerEvent(carPowerStateListenerState, INVALID_TIMEOUT);
984         // Inspect CarPowerStateListenerState to decide which message to send via VHAL
985         int lastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_OFF;
986         switch (carPowerStateListenerState) {
987             case CarPowerManager.STATE_WAIT_FOR_VHAL:
988                 lastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_OFF;
989                 mHal.sendWaitForVhal();
990                 break;
991             case CarPowerManager.STATE_SHUTDOWN_CANCELLED:
992                 synchronized (mLock) {
993                     mShutdownOnNextSuspend = false; // This cancels the "NextSuspend"
994                     mIsEmergencyShutdown = false; // TODO add cancel test
995                 }
996                 mHal.sendShutdownCancel();
997                 Slogf.d(TAG, "reset mIsEmergencyShutdown");
998                 break;
999             case CarPowerManager.STATE_SUSPEND_EXIT:
1000                 lastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_RAM;
1001                 mHal.sendSleepExit();
1002                 break;
1003             case CarPowerManager.STATE_HIBERNATION_EXIT:
1004                 lastShutdownState = CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_DISK;
1005                 mHal.sendHibernationExit();
1006                 break;
1007             default:
1008                 Slogf.w(TAG, "Invalid action when handling wait for VHAL: %d",
1009                         carPowerStateListenerState);
1010                 break;
1011         }
1012         synchronized (mLock) {
1013             mLastShutdownState = lastShutdownState;
1014         }
1015         if (mWifiAdjustmentForSuspend) {
1016             restoreWifiFully();
1017         }
1018     }
1019 
updateCarUserNoticeServiceIfNecessary()1020     private void updateCarUserNoticeServiceIfNecessary() {
1021         try {
1022             int currentUserId = ActivityManager.getCurrentUser();
1023             UserHandleHelper userHandleHelper = new UserHandleHelper(mContext, mUserManager);
1024             UserHandle currentUser = userHandleHelper.getExistingUserHandle(currentUserId);
1025             CarUserNoticeService carUserNoticeService =
1026                     CarLocalServices.getService(CarUserNoticeService.class);
1027             if (currentUser != null && userHandleHelper.isGuestUser(currentUser)
1028                     && carUserNoticeService != null) {
1029                 Slogf.i(TAG, "Car user notice service will ignore all messages before user "
1030                         + "switch.");
1031                 Intent intent = new Intent();
1032                 intent.setComponent(ComponentName.unflattenFromString(
1033                         mContext.getResources().getString(R.string.continuousBlankActivity)));
1034                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1035                 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
1036                 carUserNoticeService.ignoreUserNotice(currentUserId);
1037             }
1038         } catch (Exception e) {
1039             Slogf.w(TAG, e, "Cannot ignore user notice for current user");
1040         }
1041     }
1042 
1043     @VisibleForTesting
handleOn()1044     void handleOn() {
1045         if (factoryResetIfNeeded()) return;
1046 
1047         // If current user is a Guest User, we want to inform CarUserNoticeService not to show
1048         // notice for current user, and show user notice only for the target user.
1049         if (!mSwitchGuestUserBeforeSleep) {
1050             updateCarUserNoticeServiceIfNecessary();
1051         }
1052 
1053         if (mFeatureFlags.carPowerPolicyRefactoring()) {
1054             notifyPowerStateChangeToDaemon(CarPowerManager.STATE_ON);
1055         } else {
1056             if (!mSilentModeHandler.isSilentMode()) {
1057                 cancelPreemptivePowerPolicy();
1058             }
1059             applyDefaultPowerPolicyForState(VehicleApPowerStateReport.ON,
1060                     PolicyReader.POWER_POLICY_ID_ALL_ON);
1061         }
1062 
1063         sendPowerManagerEvent(CarPowerManager.STATE_ON, INVALID_TIMEOUT);
1064 
1065         mHal.sendOn();
1066 
1067         synchronized (mLock) {
1068             if (!mShouldResumeUserService) {
1069                 Slogf.d(TAG, "handleOn(): called on boot");
1070                 return;
1071             } else {
1072                 mShouldResumeUserService = false;
1073             }
1074         }
1075 
1076         try {
1077             mUserService.onResume();
1078         } catch (Exception e) {
1079             Slogf.e(TAG, e, "Could not switch user on resume");
1080         }
1081     }
1082 
factoryResetIfNeeded()1083     private boolean factoryResetIfNeeded() {
1084         ICarResultReceiver callback;
1085         synchronized (mLock) {
1086             if (mFactoryResetCallback == null) return false;
1087             callback = mFactoryResetCallback;
1088         }
1089 
1090         try {
1091             Slogf.i(TAG, "Factory resetting as it was delayed by user");
1092             callback.send(/* resultCode= */ 0, /* resultData= */ null);
1093             return true;
1094         } catch (Exception e) {
1095             Slogf.wtf(TAG, e, "Should have factory reset, but failed");
1096             return false;
1097         }
1098     }
1099 
1100     // TODO(b/286303350): remove once power policy refactor is complete, CPPD will handle applying
1101     //                    default power policies according to state
applyDefaultPowerPolicyForState(@arPowerManager.CarPowerState int state, @Nullable String fallbackPolicyId)1102     private void applyDefaultPowerPolicyForState(@CarPowerManager.CarPowerState int state,
1103             @Nullable String fallbackPolicyId) {
1104         Slogf.i(TAG, "Applying the default power policy for %s", powerStateToString(state));
1105         CarPowerPolicy policy;
1106         synchronized (mLock) {
1107             policy = mPolicyReader
1108                     .getDefaultPowerPolicyForState(mCurrentPowerPolicyGroupId, state);
1109         }
1110         if (policy == null && fallbackPolicyId == null) {
1111             Slogf.w(TAG, "No default power policy for %s is found", powerStateToString(state));
1112             return;
1113         }
1114         String policyId = policy == null ? fallbackPolicyId : policy.getPolicyId();
1115         applyPowerPolicy(policyId, /* delayNotification= */ false, /* upToDaemon= */ true,
1116                 /* force= */ false);
1117     }
1118 
1119     /**
1120      * Sets the callback used to factory reset the device on resume when the user delayed it.
1121      */
setFactoryResetCallback(ICarResultReceiver callback)1122     public void setFactoryResetCallback(ICarResultReceiver callback) {
1123         synchronized (mLock) {
1124             mFactoryResetCallback = callback;
1125         }
1126     }
1127 
1128     /**
1129      * Tells Garage Mode if it should run normally, or just
1130      * exit immediately without indicating 'idle'
1131      * @return True if no idle jobs should be run
1132      * @hide
1133      */
garageModeShouldExitImmediately()1134     public boolean garageModeShouldExitImmediately() {
1135         synchronized (mLock) {
1136             return mGarageModeShouldExitImmediately;
1137         }
1138     }
1139 
1140     /**
1141      * This method is required for testing
1142      * Gets {@code PolicyReader} that reads {@code power_policy.xml}.
1143      * @return {@link PolicyReader}
1144      */
1145     @VisibleForTesting
getPolicyReader()1146     public PolicyReader getPolicyReader() {
1147         return mPolicyReader;
1148     }
1149 
handleShutdownPrepare(CpmsState currentState, CpmsState prevState)1150     private void handleShutdownPrepare(CpmsState currentState, CpmsState prevState) {
1151         switch (currentState.mCarPowerStateListenerState) {
1152             case CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE:
1153                 updateShutdownPrepareStatus(currentState);
1154                 if (prevState.mCarPowerStateListenerState == STATE_SHUTDOWN_PREPARE) {
1155                     // Received request to update SHUTDOWN target
1156                     currentState = new CpmsState(currentState.mState,
1157                             prevState.mCarPowerStateListenerState,
1158                             prevState.mCanPostpone, currentState.mShutdownType);
1159                     synchronized (mLock) {
1160                         mCurrentState = currentState;
1161                     }
1162                     clearWaitingForCompletion(/*clearQueue=*/true);
1163                 } else if (prevState.mCarPowerStateListenerState == STATE_PRE_SHUTDOWN_PREPARE) {
1164                     // Update of state occurred while in PRE_SHUTDOWN_PREPARE
1165                     boolean areListenersEmpty;
1166                     synchronized (mLock) {
1167                         areListenersEmpty = mListenersWeAreWaitingFor.isEmpty();
1168                     }
1169                     if (areListenersEmpty) {
1170                         handleCoreShutdownPrepare();
1171                     } else {
1172                         // PRE_SHUTDOWN_PREPARE is still being processed, no actions required
1173                         return;
1174                     }
1175                 } else {
1176                     handlePreShutdownPrepare();
1177                 }
1178                 break;
1179             case CarPowerManager.STATE_SHUTDOWN_PREPARE:
1180                 handleCoreShutdownPrepare();
1181                 break;
1182             default:
1183                 Slogf.w(TAG, "Not supported listener state(%d)",
1184                         currentState.mCarPowerStateListenerState);
1185         }
1186     }
1187 
updateShutdownPrepareStatus(CpmsState newState)1188     private void updateShutdownPrepareStatus(CpmsState newState) {
1189         // Shutdown on finish if the system doesn't support deep sleep/hibernation
1190         // or doesn't allow it.
1191         synchronized (mLock) {
1192             if (mShutdownOnNextSuspend || (
1193                     newState.mShutdownType == PowerState.SHUTDOWN_TYPE_POWER_OFF
1194                             || newState.mShutdownType == PowerState.SHUTDOWN_TYPE_EMERGENCY)) {
1195                 mActionOnFinish = ACTION_ON_FINISH_SHUTDOWN;
1196             } else if (newState.mShutdownType == PowerState.SHUTDOWN_TYPE_DEEP_SLEEP) {
1197                 boolean isDeepSleepOnFinish =
1198                         isDeepSleepAvailable() || newState.mState == CpmsState.SIMULATE_SLEEP;
1199                 mActionOnFinish = isDeepSleepOnFinish ? ACTION_ON_FINISH_DEEP_SLEEP
1200                         : ACTION_ON_FINISH_SHUTDOWN;
1201             } else if (newState.mShutdownType == PowerState.SHUTDOWN_TYPE_HIBERNATION) {
1202                 boolean isHibernationOnFinish = isHibernationAvailable()
1203                         || newState.mState == CpmsState.SIMULATE_HIBERNATION;
1204                 mActionOnFinish = isHibernationOnFinish ? ACTION_ON_FINISH_HIBERNATION
1205                         : ACTION_ON_FINISH_SHUTDOWN;
1206             } else {
1207                 Slogf.wtf(TAG, "handleShutdownPrepare - incorrect state " + newState);
1208             }
1209             mGarageModeShouldExitImmediately = !newState.mCanPostpone;
1210             if (!mIsEmergencyShutdown) {
1211                 mIsEmergencyShutdown = newState.mShutdownType == PowerState.SHUTDOWN_TYPE_EMERGENCY;
1212                 Slogf.d(TAG, "set mIsEmergencyShutdown to " + mIsEmergencyShutdown);
1213             } else {
1214                 // Emergency shutdown can be cancelled only via SHUTDOWN_CANCEL request");
1215                 Slogf.d(TAG, "mIsEmergencyShutdown is already set");
1216             }
1217         }
1218     }
1219 
handlePreShutdownPrepare()1220     private void handlePreShutdownPrepare() {
1221         int intervalMs;
1222         long timeoutMs;
1223         synchronized (mLock) {
1224             intervalMs = mShutdownPollingIntervalMs;
1225             Slogf.i(TAG, mGarageModeShouldExitImmediately
1226                     ? "starting shutdown prepare without Garage Mode"
1227                     : "starting shutdown prepare with Garage Mode");
1228 
1229             // in case of emergency shutdown CPMS will not wait for
1230             timeoutMs = mIsEmergencyShutdown ? 0 : getPreShutdownPrepareTimeoutConfig();
1231         }
1232 
1233         int state = CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE;
1234         sendPowerManagerEvent(state, timeoutMs);
1235         Runnable taskAtCompletion = () -> {
1236             // The next power state is still SHUTDOWN_PREPARE, and the listener state is
1237             // SHUTDOW_PREPARE.
1238             Slogf.i(TAG, "All listeners completed for %s", powerStateToString(state));
1239             onApPowerStateChange(CpmsState.SHUTDOWN_PREPARE,
1240                     CarPowerManager.STATE_SHUTDOWN_PREPARE);
1241         };
1242 
1243         waitForCompletionWithShutdownPostpone(state, timeoutMs, taskAtCompletion, intervalMs);
1244     }
1245 
handleCoreShutdownPrepare()1246     private void handleCoreShutdownPrepare() {
1247         Slogf.i(TAG, "Handling core part of shutdown prepare");
1248         doShutdownPrepare();
1249     }
1250 
1251     // Simulates system shutdown to suspend
simulateShutdownPrepare(CpmsState newState, CpmsState oldState)1252     private void simulateShutdownPrepare(CpmsState newState, CpmsState oldState) {
1253         Slogf.i(TAG, "Simulating shutdown prepare");
1254         handleShutdownPrepare(newState, oldState);
1255     }
1256 
doShutdownPrepare()1257     private void doShutdownPrepare() {
1258         long timeoutMs;
1259         long intervalMs;
1260         boolean isEmergencyShutdown;
1261         synchronized (mLock) {
1262             timeoutMs = mShutdownPrepareTimeMs;
1263             intervalMs = mShutdownPollingIntervalMs;
1264             mShutdownStartTime = SystemClock.elapsedRealtime();
1265             isEmergencyShutdown = mIsEmergencyShutdown;
1266         }
1267 
1268         if (isEmergencyShutdown) {
1269             timeoutMs = 0;  // do not wait for listeners to complete during emergency shutdown
1270         } else if (BuildHelper.isUserDebugBuild() || BuildHelper.isEngBuild()) {
1271             int shutdownPrepareTimeOverrideInSecs =
1272                     SystemProperties.getInt(PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE, -1);
1273             if (shutdownPrepareTimeOverrideInSecs >= 0) {
1274                 timeoutMs = shutdownPrepareTimeOverrideInSecs * 1000L;
1275             }
1276         }
1277         makeSureNoUserInteraction();
1278         sendPowerManagerEvent(CarPowerManager.STATE_SHUTDOWN_PREPARE, timeoutMs);
1279         mHal.sendShutdownPrepare();
1280         waitForShutdownPrepareListenersToComplete(timeoutMs, intervalMs);
1281     }
1282 
forceSimulatedCancel()1283     private void forceSimulatedCancel() {
1284         synchronized (mLock) {
1285             mPendingPowerStates.addFirst(new CpmsState(CpmsState.WAIT_FOR_VHAL,
1286                     CarPowerManager.STATE_SHUTDOWN_CANCELLED,
1287                     /* canPostpone= */ false));
1288         }
1289         mHandler.handlePowerStateChange();
1290         synchronized (mSimulationWaitObject) {
1291             mBlockFromSimulatedCancelEvent = true;
1292             mSimulationWaitObject.notifyAll();
1293         }
1294     }
1295 
handleWaitForFinish(CpmsState state)1296     private void handleWaitForFinish(CpmsState state) {
1297         int timeoutMs = getShutdownEnterTimeoutConfig();
1298         sendPowerManagerEvent(state.mCarPowerStateListenerState, timeoutMs);
1299         Runnable taskAtCompletion = () -> {
1300             Slogf.i(TAG, "All listeners completed for %s",
1301                     powerStateToString(state.mCarPowerStateListenerState));
1302             if (mFeatureFlags.carPowerCancelShellCommand()) {
1303                 synchronized (mSimulationWaitObject) {
1304                     if (mInSimulatedDeepSleepMode && mCancelDelayFromSimulatedSuspendSec >= 0) {
1305                         mHandler.postDelayed(() -> forceSimulatedCancel(),
1306                                 mCancelDelayFromSimulatedSuspendSec * 1000L);
1307                         while (!mBlockFromSimulatedCancelEvent) {
1308                             try {
1309                                 mSimulationWaitObject.wait();
1310                             } catch (InterruptedException ignored) {
1311                                 Thread.currentThread().interrupt(); // Restore interrupted status
1312                             }
1313                         }
1314                         mInSimulatedDeepSleepMode = false;
1315                         return;
1316                     }
1317                 }
1318             }
1319             int wakeupSec;
1320             synchronized (mLock) {
1321                 // If we're shutting down immediately, don't schedule a wakeup time.
1322                 wakeupSec = mGarageModeShouldExitImmediately ? 0 : mNextWakeupSec;
1323             }
1324             switch (state.mCarPowerStateListenerState) {
1325                 case CarPowerManager.STATE_SUSPEND_ENTER:
1326                     mHal.sendSleepEntry(wakeupSec);
1327                     break;
1328                 case CarPowerManager.STATE_SHUTDOWN_ENTER:
1329                     mHal.sendShutdownStart(wakeupSec);
1330                     break;
1331                 case CarPowerManager.STATE_HIBERNATION_ENTER:
1332                     mHal.sendHibernationEntry(wakeupSec);
1333                     break;
1334                 default:
1335                     Slogf.w(TAG, "Invalid action when handling wait for finish: %d",
1336                             state.mCarPowerStateListenerState);
1337                     break;
1338             }
1339         };
1340 
1341         int intervalMs;
1342         synchronized (mLock) {
1343             intervalMs = mShutdownPollingIntervalMs;
1344         }
1345 
1346         waitForCompletionWithShutdownPostpone(state.mCarPowerStateListenerState, timeoutMs,
1347                 taskAtCompletion, intervalMs);
1348     }
1349 
handleFinish()1350     private void handleFinish() {
1351         int listenerState;
1352         synchronized (mLock) {
1353             switch (mActionOnFinish) {
1354                 case ACTION_ON_FINISH_SHUTDOWN:
1355                     listenerState = CarPowerManager.STATE_POST_SHUTDOWN_ENTER;
1356                     break;
1357                 case ACTION_ON_FINISH_DEEP_SLEEP:
1358                     listenerState = CarPowerManager.STATE_POST_SUSPEND_ENTER;
1359                     break;
1360                 case ACTION_ON_FINISH_HIBERNATION:
1361                     listenerState = CarPowerManager.STATE_POST_HIBERNATION_ENTER;
1362                     break;
1363                 default:
1364                     Slogf.w(TAG, "Invalid action on finish: %d", mActionOnFinish);
1365                     return;
1366             }
1367         }
1368         int timeoutMs = getPostShutdownEnterTimeoutConfig();
1369         sendPowerManagerEvent(listenerState, timeoutMs);
1370         Runnable taskAtCompletion = () -> {
1371             Slogf.i(TAG, "All listeners completed for %s", powerStateToString(listenerState));
1372             doHandleFinish();
1373         };
1374         Slogf.i(TAG, "Start waiting for listener completion for %s",
1375                 powerStateToString(listenerState));
1376         waitForCompletion(taskAtCompletion, /* taskAtInterval= */ null, timeoutMs,
1377                 /* intervalMs= */ -1);
1378     }
1379 
doHandleFinish()1380     private void doHandleFinish() {
1381         boolean simulatedMode;
1382         synchronized (mSimulationWaitObject) {
1383             simulatedMode = mInSimulatedDeepSleepMode;
1384         }
1385         boolean mustShutDown;
1386         boolean forceReboot;
1387         synchronized (mLock) {
1388             mustShutDown = (mActionOnFinish == ACTION_ON_FINISH_SHUTDOWN) && !simulatedMode;
1389             forceReboot = mRebootAfterGarageMode;
1390             mRebootAfterGarageMode = false;
1391         }
1392         if (forceReboot) {
1393             PowerManager powerManager = mContext.getSystemService(PowerManager.class);
1394             if (powerManager == null) {
1395                 Slogf.wtf(TAG, "No PowerManager. Cannot reboot.");
1396             } else {
1397                 Slogf.i(TAG, "GarageMode has completed. Forcing reboot.");
1398                 powerManager.reboot("GarageModeReboot");
1399                 throw new AssertionError("Should not return from PowerManager.reboot()");
1400             }
1401         }
1402         // To make Kernel implementation simpler when going into sleep.
1403         if (mWifiAdjustmentForSuspend) {
1404             disableWifiFully();
1405         }
1406 
1407         if (mustShutDown) {
1408             // shutdown HU
1409             mSystemInterface.shutdown();
1410         } else {
1411             doHandleSuspend(simulatedMode);
1412         }
1413         synchronized (mLock) {
1414             mShutdownOnNextSuspend = false;
1415         }
1416     }
1417 
disableWifiFully()1418     private void disableWifiFully() {
1419         disableWifi();
1420         disableTethering();
1421     }
1422 
restoreWifiFully()1423     private void restoreWifiFully() {
1424         restoreTethering();
1425         restoreWifi();
1426     }
1427 
restoreWifi()1428     private void restoreWifi() {
1429         boolean needToRestore = readWifiModifiedState(mWifiStateFile);
1430         if (!needToRestore) return;
1431         if (!mWifiManager.isWifiEnabled()) {
1432             Slogf.i(TAG, "Wifi has been enabled to restore the last setting");
1433             mWifiManager.setWifiEnabled(true);
1434         }
1435         // Update the persistent data as wifi is not modified by car framework.
1436         saveWifiModifiedState(mWifiStateFile, /* forciblyDisabled= */ false);
1437     }
1438 
disableWifi()1439     private void disableWifi() {
1440         boolean wifiEnabled = mWifiManager.isWifiEnabled();
1441         boolean wifiModifiedState = readWifiModifiedState(mWifiStateFile);
1442         if (wifiEnabled != wifiModifiedState) {
1443             Slogf.i(TAG, "Saving the current Wifi state");
1444             saveWifiModifiedState(mWifiStateFile, wifiEnabled);
1445         }
1446 
1447         // In some devices, enabling a tether temporarily turns off Wifi. To make sure that Wifi is
1448         // disabled, we call this method in all cases.
1449         mWifiManager.setWifiEnabled(false);
1450         Slogf.i(TAG, "Wifi has been disabled and the last setting was saved");
1451     }
1452 
restoreTethering()1453     private void restoreTethering() {
1454         boolean needToRestore = readWifiModifiedState(mTetheringStateFile);
1455         if (!needToRestore) return;
1456         if (!mWifiManager.isWifiApEnabled()) {
1457             Slogf.i(TAG, "Tethering has been enabled to restore the last setting");
1458             startTethering();
1459         }
1460         // Update the persistent data as wifi is not modified by car framework.
1461         saveWifiModifiedState(mTetheringStateFile, /*forciblyDisabled= */ false);
1462     }
1463 
disableTethering()1464     private void disableTethering() {
1465         boolean tetheringEnabled = mWifiManager.isWifiApEnabled();
1466         boolean tetheringModifiedState = readWifiModifiedState(mTetheringStateFile);
1467         if (tetheringEnabled != tetheringModifiedState) {
1468             Slogf.i(TAG, "Saving the current tethering state: tetheringEnabled=%b",
1469                     tetheringEnabled);
1470             saveWifiModifiedState(mTetheringStateFile, tetheringEnabled);
1471         }
1472         if (!tetheringEnabled) return;
1473 
1474         mTetheringManager.stopTethering(TETHERING_WIFI);
1475         Slogf.i(TAG, "Tethering has been disabled and the last setting was saved");
1476     }
1477 
saveWifiModifiedState(AtomicFile file, boolean forciblyDisabled)1478     private void saveWifiModifiedState(AtomicFile file, boolean forciblyDisabled) {
1479         FileOutputStream fos;
1480         try {
1481             fos = file.startWrite();
1482         } catch (IOException e) {
1483             Slogf.e(TAG, e, "Cannot create %s", file);
1484             return;
1485         }
1486 
1487         try (BufferedWriter writer = new BufferedWriter(
1488                 new OutputStreamWriter(fos, StandardCharsets.UTF_8))) {
1489             writer.write(forciblyDisabled ? COMPONENT_STATE_MODIFIED : COMPONENT_STATE_ORIGINAL);
1490             writer.newLine();
1491             writer.flush();
1492             file.finishWrite(fos);
1493         } catch (IOException e) {
1494             file.failWrite(fos);
1495             Slogf.e(TAG, e, "Writing %s failed", file);
1496         }
1497     }
1498 
readWifiModifiedState(AtomicFile file)1499     private boolean readWifiModifiedState(AtomicFile file) {
1500         boolean needToRestore = false;
1501         boolean invalidState = false;
1502 
1503         try (BufferedReader reader = new BufferedReader(
1504                 new InputStreamReader(file.openRead(), StandardCharsets.UTF_8))) {
1505             String line = reader.readLine();
1506             if (line == null) {
1507                 needToRestore = false;
1508                 invalidState = true;
1509             } else {
1510                 line = line.trim();
1511                 needToRestore = COMPONENT_STATE_MODIFIED.equals(line);
1512                 invalidState = !(needToRestore || COMPONENT_STATE_ORIGINAL.equals(line));
1513             }
1514         } catch (IOException e) {
1515             // If a file named wifi_state doesn't exist, we will not modify Wifi at system start.
1516             Slogf.w(TAG, "Failed to read %s: %s", file, e);
1517             return false;
1518         }
1519         if (invalidState) {
1520             file.delete();
1521         }
1522 
1523         return needToRestore;
1524     }
1525 
startTethering()1526     private void startTethering() {
1527         TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
1528                 .setShouldShowEntitlementUi(false).build();
1529         mTetheringManager.startTethering(request, mContext.getMainExecutor(),
1530                 new TetheringManager.StartTetheringCallback() {
1531                     @Override
1532                     public void onTetheringFailed(int error) {
1533                         Slogf.w(TAG, "Starting tethering failed: %d", error);
1534                     }
1535                 });
1536     }
1537 
waitForShutdownPrepareListenersToComplete(long timeoutMs, long intervalMs)1538     private void waitForShutdownPrepareListenersToComplete(long timeoutMs, long intervalMs) {
1539         int state = CarPowerManager.STATE_SHUTDOWN_PREPARE;
1540         Runnable taskAtCompletion = () -> {
1541             finishShutdownPrepare();
1542             Slogf.i(TAG, "All listeners completed for %s", powerStateToString(state));
1543         };
1544 
1545         waitForCompletionWithShutdownPostpone(state, timeoutMs, taskAtCompletion, intervalMs);
1546 
1547         // allowUserSwitch value doesn't matter for onSuspend = true
1548         mUserService.onSuspend();
1549         synchronized (mLock) {
1550             mShouldResumeUserService = true;
1551         }
1552     }
1553 
waitForCompletion(Runnable taskAtCompletion, Runnable taskAtInterval, long timeoutMs, long intervalMs)1554     private void waitForCompletion(Runnable taskAtCompletion, Runnable taskAtInterval,
1555             long timeoutMs, long intervalMs) {
1556         boolean isComplete = false;
1557         synchronized (mLock) {
1558             isComplete = mListenersWeAreWaitingFor.isEmpty();
1559         }
1560         if (isComplete) {
1561             taskAtCompletion.run();
1562         } else {
1563             // Reset a flag to signal that waiting for completion is cancelled.
1564             mIsListenerWaitingCancelled.set(false);
1565             waitForCompletionAsync(taskAtCompletion, taskAtInterval, timeoutMs, intervalMs);
1566         }
1567     }
1568 
1569     // Waits for listeners to complete.
1570     // If {@code intervalMs} is non-positive value, it is ignored and the method waits up to
1571     // {@code timeoutMs}.
waitForCompletionAsync(Runnable taskAtCompletion, Runnable taskAtInterval, long timeoutMs, long intervalMs)1572     private void waitForCompletionAsync(Runnable taskAtCompletion, Runnable taskAtInterval,
1573             long timeoutMs, long intervalMs) {
1574         ExecutorService executor = Executors.newSingleThreadExecutor();
1575         executor.submit(() -> {
1576             long startTimeMs = SystemClock.elapsedRealtime();
1577             while (true) {
1578                 try {
1579                     long waitTimeMs = timeoutMs - (SystemClock.elapsedRealtime() - startTimeMs);
1580                     boolean isLastWait = true;
1581                     if (intervalMs > 0 && waitTimeMs > intervalMs) {
1582                         isLastWait = false;
1583                         waitTimeMs = intervalMs;
1584                     }
1585                     boolean isNotified = mListenerCompletionSem.tryAcquire(waitTimeMs,
1586                             TimeUnit.MILLISECONDS);
1587                     mListenerCompletionSem.drainPermits();
1588                     if (!isNotified) {
1589                         if (isLastWait) {
1590                             Slogf.w(TAG, "Waiting for listener completion is timeout(%d)",
1591                                     waitTimeMs);
1592                             taskAtCompletion.run();
1593                             return;
1594                         } else if (taskAtInterval != null) {
1595                             taskAtInterval.run();
1596                         }
1597                     }
1598                     boolean isComplete = false;
1599                     synchronized (mLock) {
1600                         if (mIsListenerWaitingCancelled.get()) {
1601                             Slogf.i(TAG, "Waiting for listener completion is cancelled");
1602                             mIsListenerWaitingCancelled.set(false);
1603                             return;
1604                         }
1605                         isComplete = mListenersWeAreWaitingFor.isEmpty();
1606                     }
1607                     if (isComplete) {
1608                         Slogf.i(TAG, "All listeners completed");
1609                         taskAtCompletion.run();
1610                         mIsListenerWaitingCancelled.set(false);
1611                         return;
1612                     }
1613                 } catch (InterruptedException e) {
1614                     Slogf.w(TAG, e, "Thread interrupted while waiting for listener completion");
1615                     Thread.currentThread().interrupt();
1616                 }
1617             }
1618         });
1619         executor.shutdown();
1620     }
1621 
clearWaitingForCompletion(boolean clearQueue)1622     private void clearWaitingForCompletion(boolean clearQueue) {
1623         if (clearQueue) {
1624             synchronized (mLock) {
1625                 mListenersWeAreWaitingFor.clear();
1626             }
1627         } else {
1628             mIsListenerWaitingCancelled.set(true);
1629         }
1630 
1631         mListenerCompletionSem.release();
1632     }
1633 
sendPowerManagerEvent(@arPowerManager.CarPowerState int newState, long timeoutMs)1634     private void sendPowerManagerEvent(@CarPowerManager.CarPowerState int newState,
1635             long timeoutMs) {
1636         // Broadcasts to the listeners that do not signal completion.
1637         notifyListeners(mPowerManagerListeners, newState, INVALID_TIMEOUT);
1638 
1639         boolean allowCompletion;
1640         boolean isShutdownPrepare = newState == CarPowerManager.STATE_SHUTDOWN_PREPARE;
1641         long internalListenerExpirationTimeMs = INVALID_TIMEOUT;
1642         long binderListenerExpirationTimeMs = INVALID_TIMEOUT;
1643 
1644         // Fully populates mListenersWeAreWaitingFor before calling any onStateChanged()
1645         // for the listeners that signal completion.
1646         // Otherwise, if the first listener calls finish() synchronously, we will
1647         // see the list go empty and we will think that we are done.
1648         PowerManagerCallbackList<ICarPowerStateListener> completingInternalListeners =
1649                 new PowerManagerCallbackList(l -> {
1650                 });
1651         PowerManagerCallbackList<ICarPowerStateListener> completingBinderListeners =
1652                 new PowerManagerCallbackList(l -> {
1653                 });
1654         synchronized (mLock) {
1655             if (isCompletionAllowed(newState)) {
1656                 if (timeoutMs < 0) {
1657                     Slogf.wtf(TAG, "Completion timeout(%d) for state(%d) should be "
1658                             + "non-negative", timeoutMs, newState);
1659                     return;
1660                 }
1661                 mStateForCompletion = newState;
1662                 allowCompletion = true;
1663                 internalListenerExpirationTimeMs = SystemClock.elapsedRealtime() + timeoutMs;
1664                 binderListenerExpirationTimeMs =
1665                         isShutdownPrepare ? INVALID_TIMEOUT : internalListenerExpirationTimeMs;
1666             } else {
1667                 allowCompletion = false;
1668                 mStateForCompletion = CarPowerManager.STATE_INVALID;
1669             }
1670 
1671             mListenersWeAreWaitingFor.clear();
1672             for (int i = 0; i < mInternalPowerListeners.size(); i++) {
1673                 ICarPowerStateListener listener = mInternalPowerListeners.get(i);
1674                 completingInternalListeners.register(listener);
1675                 if (allowCompletion) {
1676                     mListenersWeAreWaitingFor.add(listener.asBinder());
1677                 }
1678             }
1679             mBroadcastHandler.post(() -> {
1680                 int idx = mPowerManagerListenersWithCompletion.beginBroadcast();
1681                 while (idx-- > 0) {
1682                     ICarPowerStateListener listener =
1683                             mPowerManagerListenersWithCompletion.getBroadcastItem(idx);
1684                     completingBinderListeners.register(listener);
1685                     // For binder listeners, listener completion is not allowed for SHUTDOWN_PREPARE
1686                     if (allowCompletion && !isShutdownPrepare) {
1687                         synchronized (mLock) {
1688                             mListenersWeAreWaitingFor.add(listener.asBinder());
1689                         }
1690                     }
1691                 }
1692                 mPowerManagerListenersWithCompletion.finishBroadcast();
1693             });
1694         }
1695         // Resets the semaphore's available permits to 0.
1696         mListenerCompletionSem.drainPermits();
1697         // Broadcasts to the listeners that DO signal completion.
1698         notifyListeners(completingInternalListeners, newState, internalListenerExpirationTimeMs);
1699         notifyListeners(completingBinderListeners, newState, binderListenerExpirationTimeMs);
1700 
1701         // Call unlinkToDeath inside RemoteCallbackList
1702         completingInternalListeners.kill();
1703         completingBinderListeners.kill();
1704     }
1705 
notifyListeners(PowerManagerCallbackList<ICarPowerStateListener> listenerList, @CarPowerManager.CarPowerState int newState, long expirationTimeMs)1706     private void notifyListeners(PowerManagerCallbackList<ICarPowerStateListener> listenerList,
1707             @CarPowerManager.CarPowerState int newState, long expirationTimeMs) {
1708         CountDownLatch listenerLatch = new CountDownLatch(1);
1709         mBroadcastHandler.post(() -> {
1710             int idx = listenerList.beginBroadcast();
1711             while (idx-- > 0) {
1712                 ICarPowerStateListener listener = listenerList.getBroadcastItem(idx);
1713                 try {
1714                     listener.onStateChanged(newState, expirationTimeMs);
1715                 } catch (RemoteException e) {
1716                     // It's likely the connection snapped. Let binder death handle the situation.
1717                     Slogf.e(TAG, e, "onStateChanged() call failed");
1718                 }
1719             }
1720             listenerList.finishBroadcast();
1721             listenerLatch.countDown();
1722         });
1723         try {
1724             listenerLatch.await(DEFAULT_COMPLETION_WAIT_TIMEOUT, TimeUnit.MILLISECONDS);
1725         } catch (InterruptedException e) {
1726             Slogf.w(TAG, e, "Wait for power state listener completion interrupted");
1727             Thread.currentThread().interrupt();
1728         }
1729     }
1730 
doHandleSuspend(boolean simulatedMode)1731     private void doHandleSuspend(boolean simulatedMode) {
1732         int status;
1733         if (mFeatureFlags.carPowerPolicyRefactoring()) {
1734             status = applyPowerPolicy(PolicyReader.POWER_POLICY_ID_SUSPEND_PREP,
1735                     /* delayNotification= */ false, /* upToDaemon= */ false, /* force= */ true);
1736         } else {
1737             status = applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_SUSPEND_PREP);
1738         }
1739         if (status != PolicyOperationStatus.OK) {
1740             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
1741         }
1742         // Keeps holding partial wakelock to prevent entering sleep before enterDeepSleep/
1743         // enterHibernation call. enterDeepSleep/enterHibernation should force sleep entry even if
1744         // wake lock is kept.
1745         forEachDisplay(mContext, mSystemInterface::switchToPartialWakeLock);
1746         mHandler.cancelProcessingComplete();
1747         synchronized (mLock) {
1748             mLastSleepEntryTime = SystemClock.elapsedRealtime();
1749         }
1750         if (simulatedMode) {
1751             simulateSleepByWaiting();
1752         } else {
1753             boolean sleepSucceeded = suspendWithRetries();
1754             if (!sleepSucceeded) {
1755                 // Suspend failed and we shut down instead.
1756                 // We either won't get here at all or we will power off very soon.
1757                 return;
1758             }
1759         }
1760         @CarPowerManager.CarPowerState int nextListenerState;
1761         synchronized (mLock) {
1762             nextListenerState = (mActionOnFinish == ACTION_ON_FINISH_DEEP_SLEEP)
1763                             ? CarPowerManager.STATE_SUSPEND_EXIT
1764                             : CarPowerManager.STATE_HIBERNATION_EXIT;
1765             // Any wakeup time from before is no longer valid.
1766             mNextWakeupSec = 0;
1767         }
1768         Slogf.i(TAG, "Resuming after suspending");
1769         forEachDisplay(mContext, mSystemInterface::refreshDisplayBrightness);
1770         onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, nextListenerState);
1771     }
1772 
1773     @GuardedBy("mLock")
needPowerStateChangeLocked(@onNull CpmsState newState)1774     private boolean needPowerStateChangeLocked(@NonNull CpmsState newState) {
1775         if (mCurrentState == null) {
1776             return true;
1777         } else if (mCurrentState.equals(newState)) {
1778             Slogf.d(TAG, "Requested state is already in effect: %s", newState.name());
1779             return false;
1780         }
1781 
1782         // The following switch/case enforces the allowed state transitions.
1783         boolean transitionAllowed = false;
1784         switch (mCurrentState.mState) {
1785             case CpmsState.WAIT_FOR_VHAL:
1786                 transitionAllowed = (newState.mState == CpmsState.ON)
1787                     || (newState.mState == CpmsState.SHUTDOWN_PREPARE);
1788                 break;
1789             case CpmsState.SUSPEND:
1790                 transitionAllowed = newState.mState == CpmsState.WAIT_FOR_VHAL;
1791                 break;
1792             case CpmsState.ON:
1793                 transitionAllowed = (newState.mState == CpmsState.SHUTDOWN_PREPARE)
1794                     || (newState.mState == CpmsState.SIMULATE_SLEEP)
1795                     || (newState.mState == CpmsState.SIMULATE_HIBERNATION);
1796                 break;
1797             case CpmsState.SHUTDOWN_PREPARE:
1798                 // If VHAL sends SHUTDOWN_IMMEDIATELY or SLEEP_IMMEDIATELY while in
1799                 // SHUTDOWN_PREPARE state, do it.
1800                 transitionAllowed =
1801                         ((newState.mState == CpmsState.SHUTDOWN_PREPARE) && !newState.mCanPostpone)
1802                                 || (newState.mState == CpmsState.WAIT_FOR_FINISH)
1803                                 || (newState.mState == CpmsState.WAIT_FOR_VHAL);
1804                 break;
1805             case CpmsState.SIMULATE_SLEEP:
1806             case CpmsState.SIMULATE_HIBERNATION:
1807                 transitionAllowed = true;
1808                 break;
1809             case CpmsState.WAIT_FOR_FINISH:
1810                 transitionAllowed = (newState.mState == CpmsState.SUSPEND
1811                         || newState.mState == CpmsState.WAIT_FOR_VHAL);
1812                 break;
1813             default:
1814                 Slogf.e(TAG, "Unexpected current state: currentState=%s, newState=%s",
1815                         mCurrentState.name(), newState.name());
1816                 transitionAllowed = true;
1817         }
1818         if (!transitionAllowed) {
1819             Slogf.e(TAG, "Requested power transition is not allowed: %s --> %s",
1820                     mCurrentState.name(), newState.name());
1821         }
1822         return transitionAllowed;
1823     }
1824 
doHandleProcessingComplete()1825     private void doHandleProcessingComplete() {
1826         int listenerState = CarPowerManager.STATE_SHUTDOWN_ENTER;
1827         synchronized (mLock) {
1828             clearWaitingForCompletion(/*clearQueue=*/false);
1829             boolean shutdownOnFinish = (mActionOnFinish == ACTION_ON_FINISH_SHUTDOWN);
1830             if (!shutdownOnFinish && mLastSleepEntryTime > mShutdownStartTime) {
1831                 // entered sleep after processing start. So this could be duplicate request.
1832                 Slogf.w(TAG, "Duplicate sleep entry request, ignore");
1833                 return;
1834             }
1835             if (shutdownOnFinish) {
1836                 listenerState = CarPowerManager.STATE_SHUTDOWN_ENTER;
1837             } else if (mActionOnFinish == ACTION_ON_FINISH_DEEP_SLEEP) {
1838                 listenerState = CarPowerManager.STATE_SUSPEND_ENTER;
1839             } else if (mActionOnFinish == ACTION_ON_FINISH_HIBERNATION) {
1840                 listenerState = CarPowerManager.STATE_HIBERNATION_ENTER;
1841             }
1842         }
1843 
1844         onApPowerStateChange(CpmsState.WAIT_FOR_FINISH, listenerState);
1845     }
1846 
1847     @Override
onDisplayBrightnessChange(int brightness)1848     public void onDisplayBrightnessChange(int brightness) {
1849         mHandler.handleDisplayBrightnessChange(Display.DEFAULT_DISPLAY, brightness);
1850     }
1851 
1852     @Override
onDisplayBrightnessChange(int displayId, int brightness)1853     public void onDisplayBrightnessChange(int displayId, int brightness) {
1854         mHandler.handleDisplayBrightnessChange(displayId, brightness);
1855     }
1856 
doHandleDisplayBrightnessChange(int displayId, int brightness)1857     private void doHandleDisplayBrightnessChange(int displayId, int brightness) {
1858         mSystemInterface.setDisplayBrightness(displayId, brightness);
1859     }
1860 
doHandleDisplayStateChange(int displayId, boolean on)1861     private void doHandleDisplayStateChange(int displayId, boolean on) {
1862         mScreenOffHandler.handleDisplayStateChange(displayId, on);
1863     }
1864 
doHandlePowerPolicyNotification(String policyId)1865     private void doHandlePowerPolicyNotification(String policyId) {
1866         // Sending notification of power policy change triggered through CarPowerManager API.
1867         notifyPowerPolicyChange(policyId, /* upToDaemon= */ true, /* force= */ false);
1868     }
1869 
doHandlePowerPolicyNotification(CarPowerPolicy accumulatedPolicy)1870     private void doHandlePowerPolicyNotification(CarPowerPolicy accumulatedPolicy) {
1871         notifyPowerPolicyChange(accumulatedPolicy);
1872     }
1873 
1874     /**
1875      * Handles when display changes.
1876      */
handleDisplayChanged(int displayId, boolean on)1877     public void handleDisplayChanged(int displayId, boolean on) {
1878         mHandler.handleDisplayStateChange(displayId, on);
1879     }
1880 
1881     /**
1882      * Gets display display power mode to turn on display.
1883      *
1884      * @return {@code false}, if the display power mode is OFF. Otherwise, {@code true}.
1885      */
canTurnOnDisplay(int displayId)1886     public boolean canTurnOnDisplay(int displayId) {
1887         return mScreenOffHandler.canTurnOnDisplay(displayId);
1888     }
1889 
1890     /**
1891      * Notifies that user activity has happened.
1892      */
notifyUserActivity(int displayId, long eventTime)1893     public void notifyUserActivity(int displayId, long eventTime) {
1894         mScreenOffHandler.updateUserActivity(displayId, eventTime);
1895     }
1896 
1897     @Override
notifyUserActivity(int displayId)1898     public void notifyUserActivity(int displayId) {
1899         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1900         notifyUserActivity(displayId, SystemClock.uptimeMillis());
1901     }
1902 
1903     /**
1904      * Sends display brightness to VHAL.
1905      * @param brightness value 0-100%
1906      */
sendDisplayBrightness(int brightness)1907     public void sendDisplayBrightness(int brightness) {
1908         mHal.sendDisplayBrightness(brightness);
1909     }
1910 
1911     /**
1912      * Sends display brightness to VHAL.
1913      * @param displayId the target display
1914      * @param brightness value 0-100%
1915      */
sendDisplayBrightness(int displayId, int brightness)1916     public void sendDisplayBrightness(int displayId, int brightness) {
1917         mHal.sendDisplayBrightness(displayId, brightness);
1918     }
1919 
1920     /**
1921      * Gets the PowerHandler that we use to change power states
1922      */
getHandler()1923     public Handler getHandler() {
1924         return mHandler;
1925 
1926     }
1927 
1928     /**
1929      * Registers power state change listeners running in CarService, which is not a binder
1930      * interfaces.
1931      */
registerInternalListener(ICarPowerStateListener listener)1932     public void registerInternalListener(ICarPowerStateListener listener) {
1933         CarServiceUtils.assertCallingFromSystemProcessOrSelf();
1934         synchronized (mLock) {
1935             mInternalPowerListeners.add(listener);
1936         }
1937     }
1938 
1939     /**
1940      * Unregisters power state change listeners running in CarService, which is not a binder
1941      * interface.
1942      */
unregisterInternalListener(ICarPowerStateListener listener)1943     public void unregisterInternalListener(ICarPowerStateListener listener) {
1944         CarServiceUtils.assertCallingFromSystemProcessOrSelf();
1945         boolean found = false;
1946         synchronized (mLock) {
1947             found = mInternalPowerListeners.remove(listener);
1948         }
1949         if (found) {
1950             removeListenerFromWaitingList(listener.asBinder());
1951         }
1952     }
1953 
1954     /**
1955      * Tells {@link CarPowerManagementService} that the listener running in CarService completes
1956      * handling power state change.
1957      */
completeHandlingPowerStateChange(int state, ICarPowerStateListener listener)1958     public void completeHandlingPowerStateChange(int state, ICarPowerStateListener listener) {
1959         CarServiceUtils.assertCallingFromSystemProcessOrSelf();
1960         handleListenerCompletion(state, listener,
1961                 new ArraySet(new Integer[] {CarPowerManager.STATE_INVALID}));
1962     }
1963 
1964     // Binder interface for general use.
1965     // The listener is not required (or allowed) to call finished().
1966     @Override
registerListener(ICarPowerStateListener listener)1967     public void registerListener(ICarPowerStateListener listener) {
1968         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1969         mPowerManagerListeners.register(listener);
1970     }
1971 
1972     // Binder interface for Car services only.
1973     // After the listener completes its processing, it must call finished().
1974     @Override
registerListenerWithCompletion(ICarPowerStateListener listener)1975     public void registerListenerWithCompletion(ICarPowerStateListener listener) {
1976         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS);
1977 
1978         mPowerManagerListenersWithCompletion.register(listener);
1979         // TODO: Need to send current state to newly registered listener? If so, need to handle
1980         //       completion for SHUTDOWN_PREPARE state
1981     }
1982 
1983     @Override
unregisterListener(ICarPowerStateListener listener)1984     public void unregisterListener(ICarPowerStateListener listener) {
1985         CarServiceUtils.assertAnyPermission(mContext, Car.PERMISSION_CAR_POWER,
1986                 Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS);
1987         doUnregisterListener(listener);
1988     }
1989 
1990     @Override
requestShutdownOnNextSuspend()1991     public void requestShutdownOnNextSuspend() {
1992         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1993         synchronized (mLock) {
1994             mShutdownOnNextSuspend = true;
1995         }
1996     }
1997 
1998     @Override
finished(int state, ICarPowerStateListener listener)1999     public void finished(int state, ICarPowerStateListener listener) {
2000         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_SHUTDOWN_PROCESS);
2001         handleListenerCompletion(state, listener, new ArraySet(new Integer[]
2002                 {CarPowerManager.STATE_INVALID, CarPowerManager.STATE_SHUTDOWN_PREPARE}));
2003     }
2004 
2005     @Override
scheduleNextWakeupTime(int seconds)2006     public void scheduleNextWakeupTime(int seconds) {
2007         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
2008         if (seconds < 0) {
2009             Slogf.w(TAG, "Next wake up time is negative. Ignoring!");
2010             return;
2011         }
2012         boolean timedWakeupAllowed = mHal.isTimedWakeupAllowed();
2013         synchronized (mLock) {
2014             if (!timedWakeupAllowed) {
2015                 Slogf.w(TAG, "Setting timed wakeups are disabled in HAL. Skipping");
2016                 mNextWakeupSec = 0;
2017                 return;
2018             }
2019             if (mNextWakeupSec == 0 || mNextWakeupSec > seconds) {
2020                 // The new value is sooner than the old value. Take the new value.
2021                 mNextWakeupSec = seconds;
2022             } else {
2023                 Slogf.d(TAG, "Tried to schedule next wake up, but already had shorter "
2024                         + "scheduled time");
2025             }
2026         }
2027     }
2028 
2029     @Override
getPowerState()2030     public @CarPowerManager.CarPowerState int getPowerState() {
2031         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
2032         synchronized (mLock) {
2033             return (mCurrentState == null) ? CarPowerManager.STATE_INVALID
2034                     : mCurrentState.mCarPowerStateListenerState;
2035         }
2036     }
2037 
2038     /**
2039      * @see android.car.hardware.power.CarPowerManager#getCurrentPowerPolicy
2040      */
2041     @Override
getCurrentPowerPolicy()2042     public CarPowerPolicy getCurrentPowerPolicy() {
2043         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
2044         if (mFeatureFlags.carPowerPolicyRefactoring()) {
2045             synchronized (mLock) {
2046                 return mCurrentAccumulatedPowerPolicy;
2047             }
2048         } else {
2049             return mPowerComponentHandler.getAccumulatedPolicy();
2050         }
2051     }
2052 
2053     /**
2054      * @see android.car.hardware.power.CarPowerManager#applyPowerPolicy
2055      */
2056     @Override
applyPowerPolicy(String policyId)2057     public void applyPowerPolicy(String policyId) {
2058         Slogf.i(TAG, "applyPowerPolicy(%s) from binder", policyId);
2059         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_POWER_POLICY);
2060         Preconditions.checkArgument(policyId != null, "policyId cannot be null");
2061         Preconditions.checkArgument(!policyId.startsWith(PolicyReader.SYSTEM_POWER_POLICY_PREFIX),
2062                 "System power policy cannot be applied by apps");
2063         // notify daemon of power policy change not needed after policy refactor
2064         boolean upToDaemon = !mFeatureFlags.carPowerPolicyRefactoring();
2065         int status = applyPowerPolicy(policyId, /* delayNotification= */ true, upToDaemon,
2066                 /* force= */ false);
2067         if (status != PolicyOperationStatus.OK) {
2068             throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status));
2069         }
2070     }
2071 
2072     /**
2073      * @see android.car.hardware.power.CarPowerManager#setPowerPolicyGroup
2074      */
2075     @Override
setPowerPolicyGroup(String policyGroupId)2076     public void setPowerPolicyGroup(String policyGroupId) throws RemoteException {
2077         Slogf.i(TAG, "setPowerPolicyGroup(%s)", policyGroupId);
2078         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_POWER_POLICY);
2079         Preconditions.checkArgument(policyGroupId != null, "policyGroupId cannot be null");
2080         if (mFeatureFlags.carPowerPolicyRefactoring()) {
2081             ICarPowerPolicyDelegate daemon;
2082             synchronized (mLock) {
2083                 daemon = mRefactoredCarPowerPolicyDaemon;
2084             }
2085             try {
2086                 daemon.setPowerPolicyGroup(policyGroupId);
2087             } catch (IllegalArgumentException e) {
2088                 throw new IllegalArgumentException("Policy group ID is invalid");
2089             } catch (SecurityException e) {
2090                 Slogf.e(TAG, e, "Failed to set power policy group, insufficient permissions");
2091             }
2092             synchronized (mLock) {
2093                 mCurrentPowerPolicyGroupId = policyGroupId;
2094             }
2095         } else {
2096             int status = setCurrentPowerPolicyGroup(policyGroupId);
2097             if (status != PolicyOperationStatus.OK) {
2098                 throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status));
2099             }
2100         }
2101     }
2102 
2103     @VisibleForTesting
getCurrentPowerPolicyGroupId()2104     String getCurrentPowerPolicyGroupId() {
2105         synchronized (mLock) {
2106             return mCurrentPowerPolicyGroupId;
2107         }
2108     }
2109 
2110     @VisibleForTesting
getNumberOfCurrentPolicyRequests()2111     int getNumberOfCurrentPolicyRequests() {
2112         synchronized (mLock) {
2113             return mRequestIdToPolicyRequest.size();
2114         }
2115     }
2116 
2117     /**
2118      * @see android.car.hardware.power.CarPowerManager#addPowerPolicyListener
2119      */
2120     @Override
addPowerPolicyListener(CarPowerPolicyFilter filter, ICarPowerPolicyListener listener)2121     public void addPowerPolicyListener(CarPowerPolicyFilter filter,
2122             ICarPowerPolicyListener listener) {
2123         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
2124         mPowerPolicyListeners.register(listener, filter);
2125     }
2126 
2127     /**
2128      * @see android.car.hardware.power.CarPowerManager#removePowerPolicyListener
2129      */
2130     @Override
removePowerPolicyListener(ICarPowerPolicyListener listener)2131     public void removePowerPolicyListener(ICarPowerPolicyListener listener) {
2132         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
2133         mPowerPolicyListeners.unregister(listener);
2134     }
2135 
2136     /**
2137      * @see android.car.hardware.power.CarPowerManager#setDisplayPowerState
2138      */
2139     @Override
setDisplayPowerState(int displayId, boolean enable)2140     public void setDisplayPowerState(int displayId, boolean enable) {
2141         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
2142         boolean isNotSelf = Binder.getCallingUid() != Process.myUid();
2143         CarOccupantZoneService occupantZoneService =
2144                 CarLocalServices.getService(CarOccupantZoneService.class);
2145         long token = Binder.clearCallingIdentity();
2146         try {
2147             int driverDisplayId = occupantZoneService.getDisplayIdForDriver(
2148                     CarOccupantZoneManager.DISPLAY_TYPE_MAIN);
2149             if (displayId == driverDisplayId && isNotSelf) {
2150                 throw new UnsupportedOperationException("Driver display control is not supported");
2151             }
2152         } finally {
2153             Binder.restoreCallingIdentity(token);
2154         }
2155         mSystemInterface.setDisplayState(displayId, enable);
2156     }
2157 
2158     // TODO(b/286303350): remove once power policy refactor complete; CPPD will handle power policy
2159     //                    change in response to silent mode status changes
notifySilentModeChange(boolean silent)2160     void notifySilentModeChange(boolean silent) {
2161         Slogf.i(TAG, "Silent mode is set to %b", silent);
2162         if (silent) {
2163             applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION);
2164         } else {
2165             cancelPreemptivePowerPolicy();
2166         }
2167     }
2168 
handleListenerCompletion(int state, ICarPowerStateListener listener, ArraySet<Integer> notAllowedStates)2169     private void handleListenerCompletion(int state, ICarPowerStateListener listener,
2170             ArraySet<Integer> notAllowedStates) {
2171         synchronized (mLock) {
2172             if (notAllowedStates.contains(mStateForCompletion)) {
2173                 Slogf.w(TAG, "The current state(%d) doesn't allow listener completion",
2174                         mStateForCompletion);
2175                 return;
2176             }
2177             if (state != mStateForCompletion) {
2178                 Slogf.w(TAG, "Given state(%d) doesn't match the current state(%d) for completion",
2179                         state, mStateForCompletion);
2180                 return;
2181             }
2182         }
2183         removeListenerFromWaitingList(listener.asBinder());
2184     }
2185 
2186 
doUnregisterListener(ICarPowerStateListener listener)2187     private void doUnregisterListener(ICarPowerStateListener listener) {
2188         mPowerManagerListeners.unregister(listener);
2189         boolean found = mPowerManagerListenersWithCompletion.unregister(listener);
2190         if (found) {
2191             // Remove this from the completion list (if it's there)
2192             removeListenerFromWaitingList(listener.asBinder());
2193         }
2194     }
2195 
removeListenerFromWaitingList(IBinder binderListener)2196     private void removeListenerFromWaitingList(IBinder binderListener) {
2197         synchronized (mLock) {
2198             mListenersWeAreWaitingFor.remove(binderListener);
2199         }
2200         // Signals a thread to check if all listeners complete.
2201         mListenerCompletionSem.release();
2202     }
2203 
finishShutdownPrepare()2204     private void finishShutdownPrepare() {
2205         boolean shouldHandleProcessingComplete = false;
2206         synchronized (mLock) {
2207             if (mCurrentState != null
2208                     && (mCurrentState.mState == CpmsState.SHUTDOWN_PREPARE
2209                             || mCurrentState.mState == CpmsState.SIMULATE_SLEEP
2210                             || mCurrentState.mState == CpmsState.SIMULATE_HIBERNATION)) {
2211                 // All apps are ready to shutdown/suspend.
2212                 if (mActionOnFinish != ACTION_ON_FINISH_SHUTDOWN) {
2213                     if (mLastSleepEntryTime > mShutdownStartTime
2214                             && mLastSleepEntryTime < SystemClock.elapsedRealtime()) {
2215                         Slogf.d(TAG, "finishShutdownPrepare: Already slept!");
2216                         return;
2217                     }
2218                 }
2219                 shouldHandleProcessingComplete = true;
2220             }
2221         }
2222 
2223         if (shouldHandleProcessingComplete) {
2224             Slogf.i(TAG, "Apps are finished, call handleProcessingComplete()");
2225             mHandler.handleProcessingComplete();
2226         }
2227     }
2228 
2229     /**
2230      * Converts a given power policy from power policy type returned by the car power policy daemon
2231      * to the one used within car service.
2232      * @param policy of type android.frameworks.automotive.powerpolicy.CarPowerPolicy
2233      * @return policy converted to type android.car.hardware.power.CarPowerPolicy
2234      */
convertPowerPolicyFromDaemon( android.frameworks.automotive.powerpolicy.CarPowerPolicy policy)2235     private CarPowerPolicy convertPowerPolicyFromDaemon(
2236             android.frameworks.automotive.powerpolicy.CarPowerPolicy policy) {
2237         return new CarPowerPolicy(policy.policyId, policy.enabledComponents,
2238                 policy.disabledComponents);
2239     }
2240 
2241     private final class PowerPolicyCallback extends ICarPowerPolicyDelegateCallback.Stub {
2242         @Override
updatePowerComponents( android.frameworks.automotive.powerpolicy.CarPowerPolicy policy)2243         public void updatePowerComponents(
2244                 android.frameworks.automotive.powerpolicy.CarPowerPolicy policy) {
2245             mPowerComponentHandler.applyPowerPolicy(convertPowerPolicyFromDaemon(policy));
2246         }
2247 
2248         @Override
onApplyPowerPolicySucceeded(int requestId, android.frameworks.automotive.powerpolicy.CarPowerPolicy accumulatedPolicy, boolean deferred)2249         public void onApplyPowerPolicySucceeded(int requestId,
2250                 android.frameworks.automotive.powerpolicy.CarPowerPolicy accumulatedPolicy,
2251                 boolean deferred) {
2252             Slogf.i(TAG, "onApplyPowerPolicySucceeded: requestId = %d, policyId = %s, "
2253                     + "deferred = %b", requestId, accumulatedPolicy.policyId, deferred);
2254             AsyncPolicyRequest policyRequest;
2255             synchronized (mLock) {
2256                 policyRequest = mRequestIdToPolicyRequest.get(requestId);
2257             }
2258             if (policyRequest == null) {
2259                 Slogf.e(TAG, "No power policy request exists for request ID %d", requestId);
2260                 return;
2261             }
2262             CarPowerPolicy accumulatedPowerPolicy = convertPowerPolicyFromDaemon(accumulatedPolicy);
2263             policyRequest.onPolicyRequestSucceeded(accumulatedPowerPolicy, deferred);
2264         }
2265 
2266         @Override
onApplyPowerPolicyFailed(int requestId, int reason)2267         public void onApplyPowerPolicyFailed(int requestId, int reason) {
2268             Slogf.i(TAG, "onApplyPowerPolicyFailed: requestId = %d, reason = %d", requestId,
2269                     reason);
2270             AsyncPolicyRequest policyRequest;
2271             synchronized (mLock) {
2272                 policyRequest = mRequestIdToPolicyRequest.get(requestId);
2273             }
2274             if (policyRequest == null) {
2275                 Slogf.e(TAG, "No power policy request exists for request ID %d", requestId);
2276                 return;
2277             }
2278             policyRequest.onPolicyRequestFailed(reason);
2279         }
2280 
2281         @Override
onPowerPolicyChanged( android.frameworks.automotive.powerpolicy.CarPowerPolicy accumulatedPolicy)2282         public void onPowerPolicyChanged(
2283                 android.frameworks.automotive.powerpolicy.CarPowerPolicy accumulatedPolicy) {
2284             CarPowerPolicy currentAccumulatedPolicy =
2285                     convertPowerPolicyFromDaemon(accumulatedPolicy);
2286             updateCurrentPowerPolicy(currentAccumulatedPolicy);
2287             String policyId = accumulatedPolicy.policyId;
2288             Slogf.i(TAG, "Queueing power policy notification (ID: %s) in the handler", policyId);
2289             mHandler.handlePowerPolicyNotification(currentAccumulatedPolicy);
2290         }
2291 
2292         @Override
getInterfaceHash()2293         public String getInterfaceHash() {
2294             return ICarPowerPolicyDelegateCallback.HASH;
2295         }
2296 
2297         @Override
getInterfaceVersion()2298         public int getInterfaceVersion() {
2299             return ICarPowerPolicyDelegateCallback.VERSION;
2300         }
2301     }
2302 
getInitialAccumulatedPowerPolicy()2303     private static CarPowerPolicy getInitialAccumulatedPowerPolicy() {
2304         String initialPolicyId = "";
2305         int[] enabledComponents = new int[0];
2306         int[] disabledComponents = new int[LAST_POWER_COMPONENT - FIRST_POWER_COMPONENT + 1];
2307         int disabledIndex = 0;
2308         for (int component = FIRST_POWER_COMPONENT; component <= LAST_POWER_COMPONENT;
2309                 component++) {
2310             disabledComponents[disabledIndex++] = component;
2311         }
2312         return new CarPowerPolicy(initialPolicyId, enabledComponents, disabledComponents);
2313     }
2314 
initializeRegisteredPowerPolicies( android.frameworks.automotive.powerpolicy.CarPowerPolicy[] policies)2315     private void initializeRegisteredPowerPolicies(
2316             android.frameworks.automotive.powerpolicy.CarPowerPolicy[] policies) {
2317         for (int i = 0; i < policies.length; i++) {
2318             CarPowerPolicy policy = convertPowerPolicyFromDaemon(policies[i]);
2319             List<String> enabledComponents = PowerComponentUtil.powerComponentsToStrings(
2320                     Lists.asImmutableList(policy.getEnabledComponents()));
2321             List<String> disabledComponents = PowerComponentUtil.powerComponentsToStrings(
2322                     Lists.asImmutableList(policy.getDisabledComponents()));
2323             mPolicyReader.definePowerPolicy(policy.getPolicyId(),
2324                     enabledComponents.toArray(String[]::new),
2325                     disabledComponents.toArray(String[]::new));
2326         }
2327         mPowerPoliciesInitialized = true;
2328         mPowerPolicyInitializationLatch.countDown();
2329     }
2330 
2331     @VisibleForTesting
initializePowerPolicy()2332     public void initializePowerPolicy() {
2333         if (mFeatureFlags.carPowerPolicyRefactoring()) {
2334             ICarPowerPolicyDelegate daemon;
2335             synchronized (mLock) {
2336                 daemon = mRefactoredCarPowerPolicyDaemon;
2337             }
2338             PowerPolicyInitData powerPolicyInitData;
2339             if (daemon != null) {
2340                 try {
2341                     PowerPolicyCallback powerPolicyCallback = new PowerPolicyCallback();
2342                     powerPolicyInitData = daemon.notifyCarServiceReady(powerPolicyCallback);
2343                 } catch (RemoteException e) {
2344                     Slogf.e(TAG, e, "Failed to tell car power policy daemon that CarService is"
2345                             + " ready");
2346                     return;
2347                 }
2348             } else {
2349                 Slogf.w(TAG, "Failed to notify car service is ready, car power policy daemon"
2350                                 + " is not available");
2351                 return;
2352             }
2353             mReadyForCallback.set(true);
2354             int[] registeredCustomComponents = powerPolicyInitData.registeredCustomComponents;
2355             Integer[] customComponents = new Integer[registeredCustomComponents.length];
2356             for (int i = 0; i < customComponents.length; i++) {
2357                 customComponents[i] = registeredCustomComponents[i];
2358             }
2359             mPowerComponentHandler.registerCustomComponents(customComponents);
2360             initializeRegisteredPowerPolicies(powerPolicyInitData.registeredPolicies);
2361             CarPowerPolicy currentPowerPolicy = convertPowerPolicyFromDaemon(
2362                     powerPolicyInitData.currentPowerPolicy);
2363             updateCurrentPowerPolicy(currentPowerPolicy);
2364             mPowerComponentHandler.applyPowerPolicy(currentPowerPolicy);
2365             notifyPowerPolicyChange(currentPowerPolicy);
2366             // To cover the case where power state changed before connecting to CPPD.
2367             int currentPowerState = getPowerState();
2368             if (currentPowerState != CarPowerManager.STATE_WAIT_FOR_VHAL
2369                     && currentPowerState != CarPowerManager.STATE_ON) {
2370                 Slogf.w(TAG, "Current power state is %s, doesn't correspond to wait for VHAL "
2371                         + "or on state, skipping notification of power state to daemon.",
2372                         powerStateToString(currentPowerState));
2373             } else {
2374                 notifyPowerStateChangeToDaemon(daemon, currentPowerState);
2375             }
2376         } else {
2377             Slogf.i(TAG, "CPMS is taking control from carpowerpolicyd");
2378             ICarPowerPolicySystemNotification daemon;
2379             synchronized (mLock) {
2380                 daemon = mCarPowerPolicyDaemon;
2381             }
2382             PolicyState state;
2383             if (daemon != null) {
2384                 try {
2385                     state = daemon.notifyCarServiceReady();
2386                 } catch (RemoteException e) {
2387                     Slogf.e(TAG, e,
2388                             "Failed to tell car power policy daemon that CarService is ready");
2389                     return;
2390                 }
2391             } else {
2392                 Slogf.w(TAG,
2393                         "Failed to notify car service is ready. car power policy daemon is not "
2394                                 + "available");
2395                 return;
2396             }
2397 
2398             String currentPowerPolicyId;
2399             String currentPolicyGroupId;
2400             synchronized (mLock) {
2401                 mHasControlOverDaemon = true;
2402                 currentPowerPolicyId = mCurrentPowerPolicyId;
2403                 currentPolicyGroupId = mCurrentPowerPolicyGroupId;
2404             }
2405             // If the current power policy or the policy group has been modified by CPMS, we ignore
2406             // the power policy or the policy group passed from car power policy daemon, and
2407             // notifies the current power policy to the daemon.
2408             if (currentPowerPolicyId == null || currentPowerPolicyId.isEmpty()) {
2409                 Slogf.i(TAG, "Attempting to apply the power policy(%s) from the daemon",
2410                         state.policyId);
2411                 int status = applyPowerPolicy(state.policyId, /* delayNotification= */ false,
2412                         /* upToDaemon= */ false, /* force= */ false);
2413                 if (status != PolicyOperationStatus.OK) {
2414                     Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
2415                 }
2416             } else {
2417                 Slogf.i(TAG,
2418                         "CPMS applied power policy(%s) before connecting to the daemon. Notifying "
2419                                 + "to the daemon...", currentPowerPolicyId);
2420                 notifyPowerPolicyChangeToDaemon(currentPowerPolicyId, /* force= */ true);
2421             }
2422             if (currentPolicyGroupId == null || currentPolicyGroupId.isEmpty()) {
2423                 int status = setCurrentPowerPolicyGroup(state.policyGroupId);
2424                 if (status != PolicyOperationStatus.OK) {
2425                     Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
2426                 }
2427             }
2428         }
2429         mSilentModeHandler.init();
2430     }
2431 
2432     @PolicyOperationStatus.ErrorCode
setCurrentPowerPolicyGroup(String policyGroupId)2433     private int setCurrentPowerPolicyGroup(String policyGroupId) {
2434         if (!mPolicyReader.isPowerPolicyGroupAvailable(policyGroupId)) {
2435             int error = PolicyOperationStatus.ERROR_SET_POWER_POLICY_GROUP;
2436             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error,
2437                     policyGroupId + " is not registered"));
2438             return error;
2439         }
2440         synchronized (mLock) {
2441             mCurrentPowerPolicyGroupId = policyGroupId;
2442         }
2443         return PolicyOperationStatus.OK;
2444     }
2445 
2446     private static final class AsyncPolicyRequest {
2447         private final Object mLock = new Object();
2448         private final int mRequestId;
2449         private final long mTimeoutMs;
2450         private final CountDownLatch mPolicyRequestLatch = new CountDownLatch(1);
2451         @GuardedBy("mLock")
2452         private boolean mPolicyRequestSucceeded;
2453         @GuardedBy("mLock")
2454         @Nullable
2455         private CarPowerPolicy mAccumulatedPolicy;
2456         @GuardedBy("mLock")
2457         @PowerPolicyFailureReason
2458         private int mFailureReason;
2459         @GuardedBy("mLock")
2460         private boolean mIsDeferred;
2461 
AsyncPolicyRequest(int requestId, long timeoutMs)2462         AsyncPolicyRequest(int requestId, long timeoutMs) {
2463             mRequestId = requestId;
2464             mTimeoutMs = timeoutMs;
2465         }
2466 
getRequestId()2467         public int getRequestId() {
2468             return mRequestId;
2469         }
2470 
isSuccessful()2471         public boolean isSuccessful() {
2472             synchronized (mLock) {
2473                 return mPolicyRequestSucceeded;
2474             }
2475         }
2476 
2477         @Nullable
getAccumulatedPolicy()2478         public CarPowerPolicy getAccumulatedPolicy() {
2479             synchronized (mLock) {
2480                 return mAccumulatedPolicy;
2481             }
2482         }
2483 
2484         @PowerPolicyFailureReason
getFailureReason()2485         public int getFailureReason() {
2486             synchronized (mLock) {
2487                 return mFailureReason;
2488             }
2489         }
2490 
isDeferred()2491         public boolean isDeferred() {
2492             synchronized (mLock) {
2493                 return mIsDeferred;
2494             }
2495         }
2496 
await()2497         public boolean await() throws InterruptedException {
2498             return mPolicyRequestLatch.await(mTimeoutMs, TimeUnit.MILLISECONDS);
2499         }
2500 
onPolicyRequestSucceeded(CarPowerPolicy accumulatedPolicy, boolean deferred)2501         public void onPolicyRequestSucceeded(CarPowerPolicy accumulatedPolicy, boolean deferred) {
2502             synchronized (mLock) {
2503                 mPolicyRequestSucceeded = true;
2504                 if (!deferred) {
2505                     mAccumulatedPolicy = accumulatedPolicy;
2506                 }
2507                 mIsDeferred = deferred;
2508             }
2509             mPolicyRequestLatch.countDown();
2510         }
2511 
onPolicyRequestFailed(@owerPolicyFailureReason int reason)2512         public void onPolicyRequestFailed(@PowerPolicyFailureReason int reason) {
2513             synchronized (mLock) {
2514                 mFailureReason = reason;
2515             }
2516             mPolicyRequestLatch.countDown();
2517         }
2518     }
2519 
generateAsyncPolicyRequest(long timeoutMs)2520     private AsyncPolicyRequest generateAsyncPolicyRequest(long timeoutMs) {
2521         int requestId = mPolicyRequestIdCounter.getAndIncrement();
2522         return new AsyncPolicyRequest(requestId, timeoutMs);
2523     }
2524 
2525     @PolicyOperationStatus.ErrorCode
getPolicyRequestError(int requestId, @PowerPolicyFailureReason int reason)2526     private int getPolicyRequestError(int requestId, @PowerPolicyFailureReason int reason) {
2527         switch(reason) {
2528             case PowerPolicyFailureReason.POWER_POLICY_FAILURE_UNKNOWN:
2529                 Slogf.w(TAG, "Power policy request %d failed for unknown reason",
2530                         requestId);
2531                 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2532             case PowerPolicyFailureReason.POWER_POLICY_FAILURE_NOT_REGISTERED_ID:
2533                 Slogf.w(TAG, "Power policy request %d failed due to unregistered"
2534                         + "power policy ID", requestId);
2535                 return PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID;
2536             case PowerPolicyFailureReason.POWER_POLICY_FAILURE_CANNOT_OVERRIDE:
2537                 Slogf.w(TAG, "Power policy request %d failed because current non-"
2538                         + "preemptive power policy cannot be overridden", requestId);
2539                 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2540             default:
2541                 Slogf.w(TAG, "Reason for power policy request %d failing is "
2542                         + "undefined", requestId);
2543                 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2544         }
2545     }
2546 
2547     @PolicyOperationStatus.ErrorCode
applyPowerPolicy(@ullable String policyId, boolean delayNotification, boolean upToDaemon, boolean force)2548     private int applyPowerPolicy(@Nullable String policyId, boolean delayNotification,
2549             boolean upToDaemon, boolean force) {
2550         if (mFeatureFlags.carPowerPolicyRefactoring()) {
2551             AsyncPolicyRequest request = generateAsyncPolicyRequest(
2552                     DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS);
2553             int requestId = request.getRequestId();
2554             ICarPowerPolicyDelegate daemon;
2555             synchronized (mLock) {
2556                 daemon = mRefactoredCarPowerPolicyDaemon;
2557                 mRequestIdToPolicyRequest.put(requestId, request);
2558             }
2559             if (daemon == null) {
2560                 Slogf.w(TAG, "Cannot call applyPowerPolicyAsync(requestId=%d, policyId=%s) to CPPD:"
2561                         + " CPPD is not available", requestId, policyId);
2562                 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2563             }
2564             if (!mReadyForCallback.get()) {
2565                 Slogf.w(TAG, "Cannot call applyPowerPolicyAsync(requestId=%d, policyId=%s) to CPPD:"
2566                         + " not ready for calling to CPPD", requestId, policyId);
2567                 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2568             }
2569             try {
2570                 Slogf.i(TAG, "Request(%d) of applying power policy(%s) to CPPD in async", requestId,
2571                         policyId);
2572                 daemon.applyPowerPolicyAsync(requestId, policyId, force);
2573                 boolean policyRequestServed = request.await();
2574                 if (!policyRequestServed) {
2575                     Slogf.w(TAG, "Power policy request (ID: %d) successful application timed out"
2576                             + " after %d ms", requestId, DEFAULT_POWER_POLICY_REQUEST_TIMEOUT_MS);
2577                     return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2578                 }
2579             } catch (IllegalArgumentException e) {
2580                 int error = PolicyOperationStatus.ERROR_INVALID_POWER_POLICY_ID;
2581                 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId));
2582                 return error;
2583             } catch (IllegalStateException e) {
2584                 int error = PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2585                 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId));
2586                 return error;
2587             } catch (SecurityException e) {
2588                 Slogf.w(TAG, e, "Failed to apply power policy, insufficient permissions");
2589                 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2590             } catch (InterruptedException e) {
2591                 Slogf.w(TAG, e, "Wait for power policy change request interrupted");
2592                 Thread.currentThread().interrupt();
2593                 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2594             } catch (RemoteException e) {
2595                 Slogf.w(TAG, e, "Failed to apply power policy, connection issue");
2596                 return PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
2597             } finally {
2598                 synchronized (mLock) {
2599                     mRequestIdToPolicyRequest.remove(requestId);
2600                 }
2601             }
2602             if (!request.isSuccessful()) {
2603                 Slogf.w(TAG, "Failed to apply power policy, failure reason = %d",
2604                         request.getFailureReason());
2605                 return getPolicyRequestError(requestId, request.getFailureReason());
2606             }
2607             if (request.isDeferred()) {
2608                 Slogf.i(TAG, "Applying power policy(%s) is deferred", policyId);
2609                 return PolicyOperationStatus.OK;
2610             }
2611             CarPowerPolicy accumulatedPolicy = request.getAccumulatedPolicy();
2612             updateCurrentPowerPolicy(accumulatedPolicy);
2613             if (delayNotification) {
2614                 Slogf.d(TAG,
2615                         "Queueing power policy notification (id: %s) in the handler", policyId);
2616                 mHandler.handlePowerPolicyNotification(accumulatedPolicy);
2617             } else {
2618                 notifyPowerPolicyChange(accumulatedPolicy);
2619             }
2620         } else {
2621             CarPowerPolicy policy = mPolicyReader.getPowerPolicy(policyId);
2622             if (policy == null) {
2623                 int error = PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID;
2624                 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId));
2625                 return error;
2626             }
2627             synchronized (mLock) {
2628                 if (mIsPowerPolicyLocked) {
2629                     Slogf.i(TAG, "Power policy is locked. The request policy(%s) will be applied "
2630                             + "when power policy becomes unlocked", policyId);
2631                     mPendingPowerPolicyId = policyId;
2632                     return PolicyOperationStatus.OK;
2633                 }
2634                 mCurrentPowerPolicyId = policyId;
2635             }
2636             mPowerComponentHandler.applyPowerPolicy(policy);
2637             if (delayNotification) {
2638                 Slogf.d(TAG,
2639                         "Queueing power policy notification (id: %s) in the handler", policyId);
2640                 mHandler.handlePowerPolicyNotification(policyId);
2641             } else {
2642                 notifyPowerPolicyChange(policyId, upToDaemon, force);
2643             }
2644         }
2645         Slogf.i(TAG, "The current power policy is %s", policyId);
2646         return PolicyOperationStatus.OK;
2647     }
2648 
2649     @PolicyOperationStatus.ErrorCode
applyPreemptivePowerPolicy(String policyId)2650     private int applyPreemptivePowerPolicy(String policyId) {
2651         CarPowerPolicy policy = mPolicyReader.getPreemptivePowerPolicy(policyId);
2652         if (policy == null) {
2653             int error = PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID;
2654             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId));
2655             return error;
2656         }
2657         synchronized (mLock) {
2658             mIsPowerPolicyLocked = true;
2659             if (!mPolicyReader.isPreemptivePowerPolicy(mCurrentPowerPolicyId)) {
2660                 mPendingPowerPolicyId = mCurrentPowerPolicyId;
2661             }
2662             mCurrentPowerPolicyId = policyId;
2663         }
2664         mPowerComponentHandler.applyPowerPolicy(policy);
2665         notifyPowerPolicyChange(policyId, /* upToDaemon= */ true, /* force= */ true);
2666         Slogf.i(TAG, "The current power policy is %s", policyId);
2667         return PolicyOperationStatus.OK;
2668     }
2669 
cancelPreemptivePowerPolicy()2670     private void cancelPreemptivePowerPolicy() {
2671         Slogf.i(TAG, "Canceling preemptive power policy");
2672         String policyId;
2673         synchronized (mLock) {
2674             if (!mIsPowerPolicyLocked) {
2675                 Slogf.w(TAG, "Failed to cancel system power policy: the current policy is not the "
2676                         + "system power policy");
2677                 return;
2678             }
2679             mIsPowerPolicyLocked = false;
2680             policyId = mPendingPowerPolicyId;
2681             mPendingPowerPolicyId = null;
2682         }
2683         if (policyId != null) { // Pending policy exist
2684             int status = applyPowerPolicy(policyId, /* delayNotification= */ false,
2685                     /* upToDaemon= */ true, /* force= */ true);
2686             if (status != PolicyOperationStatus.OK) {
2687                 Slogf.w(TAG, "Failed to cancel system power policy: %s",
2688                         PolicyOperationStatus.errorCodeToString(status));
2689             }
2690         } else {
2691             Slogf.w(TAG, "cancelPreemptivePowerPolicy(), no pending power policy");
2692         }
2693     }
2694 
notifyPowerPolicyChangeToDaemon(String policyId, boolean force)2695     private void notifyPowerPolicyChangeToDaemon(String policyId, boolean force) {
2696         ICarPowerPolicySystemNotification daemon;
2697         synchronized (mLock) {
2698             daemon = mCarPowerPolicyDaemon;
2699             if (daemon == null) {
2700                 Slogf.e(TAG, "Failed to notify car power policy daemon: the daemon is not ready");
2701                 return;
2702             }
2703             if (!mHasControlOverDaemon) {
2704                 Slogf.w(TAG, "Notifying policy change is deferred: CPMS has not yet taken control");
2705                 return;
2706             }
2707         }
2708         try {
2709             daemon.notifyPowerPolicyChange(policyId, force);
2710         } catch (RemoteException | IllegalStateException e) {
2711             Slogf.e(TAG, e, "Failed to notify car power policy daemon of a new power policy(%s)",
2712                     policyId);
2713         }
2714     }
2715 
2716     // TODO(b/286303350): remove after power policy refactor is complete - will only use version
2717     //                    that takes 'accumulatedPowerPolicy' as input
notifyPowerPolicyChange(String policyId, boolean upToDaemon, boolean force)2718     private void notifyPowerPolicyChange(String policyId, boolean upToDaemon, boolean force) {
2719         // Notify system clients
2720         if (upToDaemon) {
2721             notifyPowerPolicyChangeToDaemon(policyId, force);
2722         }
2723         // Notify Java clients
2724         CarPowerPolicy appliedPolicy = mPolicyReader.isPreemptivePowerPolicy(policyId)
2725                 ? mPolicyReader.getPreemptivePowerPolicy(policyId)
2726                 : mPolicyReader.getPowerPolicy(policyId);
2727         CarPowerPolicy accumulatedPolicy = mPowerComponentHandler.getAccumulatedPolicy();
2728         notifyPowerPolicyChange(policyId, appliedPolicy, accumulatedPolicy);
2729     }
2730 
2731     @Nullable
getPowerPolicyDefinition(String policyId, long timeoutMs)2732     private CarPowerPolicy getPowerPolicyDefinition(String policyId, long timeoutMs)
2733             throws InterruptedException {
2734         if (!mPowerPoliciesInitialized) {
2735             boolean result =
2736                     mPowerPolicyInitializationLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
2737             if (!result) {
2738                 Slogf.e(TAG, "Failed to get power policy initialization after waiting %d ms",
2739                         timeoutMs);
2740                 return null;
2741             }
2742         }
2743         return mPolicyReader.getPowerPolicy(policyId);
2744     }
2745 
notifyPowerPolicyChange(CarPowerPolicy accumulatedPowerPolicy)2746     private void notifyPowerPolicyChange(CarPowerPolicy accumulatedPowerPolicy) {
2747         String policyId = accumulatedPowerPolicy.getPolicyId();
2748         try {
2749             CarPowerPolicy appliedPolicy =
2750                     getPowerPolicyDefinition(policyId, CAR_POWER_POLICY_DEFINITION_TIMEOUT_MS);
2751             if (appliedPolicy == null) {
2752                 Slogf.wtf(TAG, "The new power policy(%s) should exist", policyId);
2753                 return;
2754             }
2755             notifyPowerPolicyChange(policyId, appliedPolicy, accumulatedPowerPolicy);
2756         } catch (InterruptedException e) {
2757             Slogf.e(TAG, e, "Failed to get power policy definition for policy ID %s", policyId);
2758         }
2759     }
2760 
2761     // TODO(b/286303350): after power policy refactor is complete, remove this function and replace
2762     //                    the inner call to it by notifyPowerPolicyChange(accumulatedPowerPolicy)
2763     //                    with this function's code contents
notifyPowerPolicyChange(String policyId, CarPowerPolicy appliedPolicy, CarPowerPolicy accumulatedPolicy)2764     private void notifyPowerPolicyChange(String policyId, CarPowerPolicy appliedPolicy,
2765             CarPowerPolicy accumulatedPolicy) {
2766         EventLogHelper.writePowerPolicyChange(policyId);
2767         if (appliedPolicy == null) {
2768             Slogf.wtf(TAG, "The new power policy(%s) should exist", policyId);
2769         }
2770         Slogf.i(TAG, "Power policy change to %s is notified to apps", policyId);
2771         mBroadcastHandler.post(() -> {
2772             int idx = mPowerPolicyListeners.beginBroadcast();
2773 
2774             while (idx-- > 0) {
2775                 ICarPowerPolicyListener listener = mPowerPolicyListeners.getBroadcastItem(idx);
2776                 CarPowerPolicyFilter filter =
2777                         (CarPowerPolicyFilter) mPowerPolicyListeners.getBroadcastCookie(idx);
2778                 if (!mPowerComponentHandler.isComponentChanged(filter)) {
2779                     continue;
2780                 }
2781                 try {
2782                     listener.onPolicyChanged(appliedPolicy, accumulatedPolicy);
2783                 } catch (RemoteException e) {
2784                     // It's likely the connection snapped. Let binder death handle the situation.
2785                     Slogf.e(TAG, e, "onPolicyChanged() call failed: policyId = %s", policyId);
2786                 }
2787             }
2788             mPowerPolicyListeners.finishBroadcast();
2789         });
2790     }
2791 
makeSureNoUserInteraction()2792     private void makeSureNoUserInteraction() {
2793         mSilentModeHandler.updateKernelSilentMode(true);
2794         int status;
2795         if (mFeatureFlags.carPowerPolicyRefactoring()) {
2796             status = applyPowerPolicy(PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION,
2797                     /* delayNotification= */ false, /* upToDaemon= */ false, /* force= */ true);
2798         } else {
2799             status = applyPreemptivePowerPolicy(
2800                     PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION);
2801         }
2802         if (status != PolicyOperationStatus.OK) {
2803             Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
2804         }
2805     }
2806 
2807     @GuardedBy("mLock")
getPowerPolicyDaemonLocked()2808     private android.os.IInterface getPowerPolicyDaemonLocked() {
2809         if (mFeatureFlags.carPowerPolicyRefactoring()) {
2810             return mRefactoredCarPowerPolicyDaemon;
2811         } else {
2812             return mCarPowerPolicyDaemon;
2813         }
2814     }
2815 
connectToPowerPolicyDaemon()2816     private void connectToPowerPolicyDaemon() {
2817         synchronized (mLock) {
2818             android.os.IInterface powerPolicyDaemon = getPowerPolicyDaemonLocked();
2819             if (powerPolicyDaemon != null || mConnectionInProgress) {
2820                 return;
2821             }
2822             mConnectionInProgress = true;
2823         }
2824         connectToDaemonHelper(CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY);
2825     }
2826 
connectToDaemonHelper(int retryCount)2827     private void connectToDaemonHelper(int retryCount) {
2828         if (retryCount <= 0) {
2829             synchronized (mLock) {
2830                 mConnectionInProgress = false;
2831             }
2832             Slogf.e(TAG, "Cannot reconnect to car power policyd daemon after retrying %d times",
2833                     CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY);
2834             return;
2835         }
2836         if (makeBinderConnection()) {
2837             Slogf.i(TAG, "Connected to car power policy daemon");
2838             initializePowerPolicy();
2839             return;
2840         }
2841         final int numRetry = retryCount - 1;
2842         mHandler.postDelayed(() -> connectToDaemonHelper(numRetry),
2843                 CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS);
2844     }
2845 
makeBinderConnection()2846     private boolean makeBinderConnection() {
2847         long currentTimeMs = SystemClock.uptimeMillis();
2848         IBinder binder;
2849         if (mFeatureFlags.carPowerPolicyRefactoring()) {
2850             binder = ServiceManagerHelper.getService(REFACTORED_CAR_POWER_POLICY_DAEMON_INTERFACE);
2851         } else {
2852             binder = ServiceManagerHelper.getService(CAR_POWER_POLICY_DAEMON_INTERFACE);
2853         }
2854         if (binder == null) {
2855             Slogf.w(TAG, "Finding car power policy daemon failed. Power policy management is not "
2856                     + "supported");
2857             return false;
2858         }
2859         long elapsedTimeMs = SystemClock.uptimeMillis() - currentTimeMs;
2860         if (elapsedTimeMs > CAR_POWER_POLICY_DAEMON_FIND_MARGINAL_TIME_MS) {
2861             Slogf.wtf(TAG, "Finding car power policy daemon took too long(%dms)", elapsedTimeMs);
2862         }
2863 
2864         if (mFeatureFlags.carPowerPolicyRefactoring()) {
2865             ICarPowerPolicyDelegate daemon = ICarPowerPolicyDelegate.Stub.asInterface(binder);
2866             if (daemon == null) {
2867                 Slogf.w(TAG, "Getting car power policy daemon interface failed. Power policy "
2868                         + "management is not supported");
2869                 return false;
2870             }
2871             synchronized (mLock) {
2872                 mRefactoredCarPowerPolicyDaemon = daemon;
2873                 mConnectionInProgress = false;
2874             }
2875             mBinderHandler = new BinderHandler(daemon);
2876         } else {
2877             ICarPowerPolicySystemNotification daemon =
2878                     ICarPowerPolicySystemNotification.Stub.asInterface(binder);
2879             if (daemon == null) {
2880                 Slogf.w(TAG, "Getting car power policy daemon interface failed. Power policy "
2881                         + "management is not supported");
2882                 return false;
2883             }
2884             synchronized (mLock) {
2885                 mCarPowerPolicyDaemon = daemon;
2886                 mConnectionInProgress = false;
2887             }
2888             mBinderHandler = new BinderHandler(daemon);
2889         }
2890         mBinderHandler.linkToDeath();
2891         return true;
2892     }
2893 
updateCurrentPowerPolicy(CarPowerPolicy accumulatedPolicy)2894     private void updateCurrentPowerPolicy(CarPowerPolicy accumulatedPolicy) {
2895         synchronized (mLock) {
2896             mCurrentPowerPolicyId = accumulatedPolicy.getPolicyId();
2897             mCurrentAccumulatedPowerPolicy = accumulatedPolicy;
2898         }
2899     }
2900 
2901     private final class BinderHandler implements IBinder.DeathRecipient {
2902         // TODO(b/286303350): replace with refactored daemon once power policy refactor is complete
2903         private ICarPowerPolicySystemNotification mDaemon;
2904         private ICarPowerPolicyDelegate mRefactoredDaemon;
2905 
BinderHandler(ICarPowerPolicySystemNotification daemon)2906         private BinderHandler(ICarPowerPolicySystemNotification daemon) {
2907             mDaemon = daemon;
2908         }
2909 
BinderHandler(ICarPowerPolicyDelegate daemon)2910         private BinderHandler(ICarPowerPolicyDelegate daemon) {
2911             mRefactoredDaemon = daemon;
2912         }
2913 
2914         @Override
binderDied()2915         public void binderDied() {
2916             Slogf.w(TAG, "Car power policy daemon died: reconnecting");
2917             unlinkToDeath();
2918             if (mFeatureFlags.carPowerPolicyRefactoring()) {
2919                 mRefactoredDaemon = null;
2920             } else {
2921                 mDaemon = null;
2922             }
2923             mReadyForCallback.set(false);
2924             synchronized (mLock) {
2925                 if (mFeatureFlags.carPowerPolicyRefactoring()) {
2926                     mRefactoredCarPowerPolicyDaemon = null;
2927                 } else {
2928                     mCarPowerPolicyDaemon = null;
2929                     mHasControlOverDaemon = false;
2930                 }
2931             }
2932             mHandler.postDelayed(
2933                     () -> connectToDaemonHelper(CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY),
2934                     CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS);
2935         }
2936 
linkToDeath()2937         private void linkToDeath() {
2938             if (mFeatureFlags.carPowerPolicyRefactoring()) {
2939                 if (mRefactoredDaemon == null) {
2940                     return;
2941                 }
2942             } else {
2943                 if (mDaemon == null) {
2944                     return;
2945                 }
2946             }
2947             IBinder binder;
2948             if (mFeatureFlags.carPowerPolicyRefactoring()) {
2949                 binder = mRefactoredDaemon.asBinder();
2950             } else {
2951                 binder = mDaemon.asBinder();
2952             }
2953             if (binder == null) {
2954                 Slogf.w(TAG, "Linking to binder death recipient skipped");
2955                 return;
2956             }
2957             try {
2958                 binder.linkToDeath(this, 0);
2959             } catch (RemoteException e) {
2960                 if (mFeatureFlags.carPowerPolicyRefactoring()) {
2961                     mRefactoredDaemon = null;
2962                 } else {
2963                     mDaemon = null;
2964                 }
2965                 Slogf.w(TAG, e, "Linking to binder death recipient failed: %s");
2966             }
2967         }
2968 
unlinkToDeath()2969         private void unlinkToDeath() {
2970             if (mFeatureFlags.carPowerPolicyRefactoring()) {
2971                 if (mRefactoredDaemon == null) {
2972                     return;
2973                 }
2974             } else {
2975                 if (mDaemon == null) {
2976                     return;
2977                 }
2978             }
2979             IBinder binder;
2980             if (mFeatureFlags.carPowerPolicyRefactoring()) {
2981                 binder = mRefactoredDaemon.asBinder();
2982             } else {
2983                 binder = mDaemon.asBinder();
2984             }
2985             if (binder == null) {
2986                 Slogf.w(TAG, "Unlinking from binder death recipient skipped");
2987                 return;
2988             }
2989             binder.unlinkToDeath(this, 0);
2990         }
2991     }
2992 
2993     private final class PowerHandler extends Handler {
2994         private static final String TAG = PowerHandler.class.getSimpleName();
2995         private static final int MSG_POWER_STATE_CHANGE = 0;
2996         private static final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1;
2997         private static final int MSG_DISPLAY_STATE_CHANGE = 2;
2998         private static final int MSG_PROCESSING_COMPLETE = 3;
2999         private static final int MSG_POWER_POLICY_NOTIFICATION = 4;
3000 
3001         // Do not handle this immediately but with some delay as there can be a race between
3002         // display off due to rear view camera and delivery to here.
3003         private static final long MAIN_DISPLAY_EVENT_DELAY_MS = 500;
3004 
3005         private final WeakReference<CarPowerManagementService> mService;
3006 
PowerHandler(Looper looper, CarPowerManagementService service)3007         private PowerHandler(Looper looper, CarPowerManagementService service) {
3008             super(looper);
3009             mService = new WeakReference<CarPowerManagementService>(service);
3010         }
3011 
handlePowerStateChange()3012         private void handlePowerStateChange() {
3013             Message msg = obtainMessage(MSG_POWER_STATE_CHANGE);
3014             sendMessage(msg);
3015         }
3016 
handleDisplayBrightnessChange(int displayId, int brightness)3017         private void handleDisplayBrightnessChange(int displayId, int brightness) {
3018             Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, displayId, brightness);
3019             sendMessage(msg);
3020         }
3021 
handleDisplayStateChange(int displayId, boolean on)3022         private void handleDisplayStateChange(int displayId, boolean on) {
3023             HandlerHelper.removeEqualMessages(this, MSG_DISPLAY_STATE_CHANGE, displayId);
3024             Message msg = obtainMessage(MSG_DISPLAY_STATE_CHANGE, displayId);
3025             msg.arg1 = on ? Display.STATE_ON : Display.STATE_OFF;
3026             sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS);
3027         }
3028 
handleProcessingComplete()3029         private void handleProcessingComplete() {
3030             removeMessages(MSG_PROCESSING_COMPLETE);
3031             Message msg = obtainMessage(MSG_PROCESSING_COMPLETE);
3032             sendMessage(msg);
3033         }
3034 
cancelProcessingComplete()3035         private void cancelProcessingComplete() {
3036             removeMessages(MSG_PROCESSING_COMPLETE);
3037         }
3038 
handlePowerPolicyNotification(String policyId)3039         private void handlePowerPolicyNotification(String policyId) {
3040             Message msg = obtainMessage(MSG_POWER_POLICY_NOTIFICATION, policyId);
3041             sendMessage(msg);
3042         }
3043 
handlePowerPolicyNotification(CarPowerPolicy accumulatedPolicy)3044         private void handlePowerPolicyNotification(CarPowerPolicy accumulatedPolicy) {
3045             Message msg = obtainMessage(MSG_POWER_POLICY_NOTIFICATION, accumulatedPolicy);
3046             sendMessage(msg);
3047         }
3048 
cancelAll()3049         private void cancelAll() {
3050             removeMessages(MSG_POWER_STATE_CHANGE);
3051             removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE);
3052             removeMessages(MSG_DISPLAY_STATE_CHANGE);
3053             removeMessages(MSG_PROCESSING_COMPLETE);
3054             removeMessages(MSG_POWER_POLICY_NOTIFICATION);
3055         }
3056 
3057         @Override
handleMessage(Message msg)3058         public void handleMessage(Message msg) {
3059             CarPowerManagementService service = mService.get();
3060             if (service == null) {
3061                 Slogf.i(TAG, "handleMessage null service");
3062                 return;
3063             }
3064             switch (msg.what) {
3065                 case MSG_POWER_STATE_CHANGE:
3066                     service.doHandlePowerStateChange();
3067                     break;
3068                 case MSG_DISPLAY_BRIGHTNESS_CHANGE:
3069                     service.doHandleDisplayBrightnessChange(
3070                             /* displayId= */ msg.arg1, /* brightness= */ msg.arg2);
3071                     break;
3072                 case MSG_DISPLAY_STATE_CHANGE:
3073                     int displayId = (Integer) msg.obj;
3074                     boolean on = msg.arg1 == Display.STATE_ON;
3075                     service.doHandleDisplayStateChange(displayId, on);
3076                     break;
3077                 case MSG_PROCESSING_COMPLETE:
3078                     service.doHandleProcessingComplete();
3079                     break;
3080                 case MSG_POWER_POLICY_NOTIFICATION:
3081                     if (mFeatureFlags.carPowerPolicyRefactoring()) {
3082                         service.doHandlePowerPolicyNotification((CarPowerPolicy) msg.obj);
3083                     } else {
3084                         service.doHandlePowerPolicyNotification((String) msg.obj);
3085                     }
3086                     break;
3087                 default:
3088                     Slogf.w(TAG, "handleMessage invalid message type: %d", msg.what);
3089                     break;
3090             }
3091         }
3092     }
3093 
3094     // Send the command to enter Suspend to RAM.
3095     // If the command is not successful, try again with an exponential back-off.
3096     // If it fails repeatedly, send the command to shut down.
3097     // If we decide to go to a different power state, abort this retry mechanism.
3098     // Returns true if we successfully suspended.
suspendWithRetries()3099     private boolean suspendWithRetries() {
3100         boolean isSuspendToDisk;
3101         synchronized (mLock) {
3102             isSuspendToDisk = mActionOnFinish == ACTION_ON_FINISH_HIBERNATION;
3103         }
3104 
3105         String suspendTarget = isSuspendToDisk ? "Suspend-to-Disk" : "Suspend-to-RAM";
3106         long retryIntervalMs = INITIAL_SUSPEND_RETRY_INTERVAL_MS;
3107         long totalWaitDurationMs = 0;
3108         while (true) {
3109             long suspendStartTime = SystemClock.elapsedRealtime();
3110             Slogf.i(TAG, "Entering %s", suspendTarget);
3111             if (isSuspendToDisk) {
3112                 freeMemory();
3113             }
3114             boolean suspendSucceeded = isSuspendToDisk ? mSystemInterface.enterHibernation()
3115                     : mSystemInterface.enterDeepSleep();
3116 
3117             if (suspendSucceeded) {
3118                 return true;
3119             }
3120             if (totalWaitDurationMs >= mMaxSuspendWaitDurationMs) {
3121                 break;
3122             }
3123             // We failed to suspend. Block the thread briefly and try again.
3124             synchronized (mLock) {
3125                 if (!mPendingPowerStates.isEmpty()) {
3126                     // Check for a new power state now, before going around the loop again.
3127                     CpmsState state = mPendingPowerStates.peekFirst();
3128                     if (state != null && needPowerStateChangeLocked(state)) {
3129                         Slogf.i(TAG, "Terminating the attempt to suspend target = %s,"
3130                                         + " currentState = %s, pendingState = %s", suspendTarget,
3131                                 mCurrentState.stateToString(), state.stateToString());
3132                         return false;
3133                     }
3134                 }
3135                 long suspendStopTime = SystemClock.elapsedRealtime();
3136                 Slogf.w(TAG, "Failed to Suspend; will retry after %dms", retryIntervalMs);
3137                 try {
3138                     mLock.wait(retryIntervalMs);
3139                 } catch (InterruptedException ignored) {
3140                     Thread.currentThread().interrupt();
3141                 }
3142                 totalWaitDurationMs += retryIntervalMs;
3143                 totalWaitDurationMs += (suspendStopTime - suspendStartTime);
3144                 retryIntervalMs = Math.min(retryIntervalMs * 2, MAX_RETRY_INTERVAL_MS);
3145             }
3146         }
3147         // Too many failures trying to suspend. Shut down.
3148         Slogf.w(TAG, "Could not %s after %dms long trial. Shutting down.", suspendTarget,
3149                 totalWaitDurationMs);
3150         mSystemInterface.shutdown();
3151         return false;
3152     }
3153 
3154     private static final class CpmsState {
3155         // NOTE: When modifying states below, make sure to update CarPowerStateChanged.State in
3156         //   frameworks/proto_logging/stats/atoms.proto also.
3157         public static final int WAIT_FOR_VHAL = 0;
3158         public static final int ON = 1;
3159         public static final int SHUTDOWN_PREPARE = 2;
3160         public static final int WAIT_FOR_FINISH = 3;
3161         public static final int SUSPEND = 4;
3162         public static final int SIMULATE_SLEEP = 5;
3163         public static final int SIMULATE_HIBERNATION = 6;
3164 
3165         /* Config values from AP_POWER_STATE_REQ */
3166         public final boolean mCanPostpone;
3167 
3168         @PowerState.ShutdownType
3169         public final int mShutdownType;
3170 
3171         /* Message sent to CarPowerStateListener in response to this state */
3172         @CarPowerManager.CarPowerState
3173         public final int mCarPowerStateListenerState;
3174         /* One of the above state variables */
3175         public final int mState;
3176 
3177         /**
3178           * This constructor takes a PowerHalService.PowerState object and creates the corresponding
3179           * CPMS state from it.
3180           */
CpmsState(PowerState halPowerState)3181         CpmsState(PowerState halPowerState) {
3182             switch (halPowerState.mState) {
3183                 case VehicleApPowerStateReq.ON:
3184                     this.mCanPostpone = false;
3185                     this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED;
3186                     this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(ON);
3187                     this.mState = ON;
3188                     break;
3189                 case VehicleApPowerStateReq.SHUTDOWN_PREPARE:
3190                     this.mCanPostpone = halPowerState.canPostponeShutdown();
3191                     this.mShutdownType = halPowerState.getShutdownType();
3192                     this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(
3193                             SHUTDOWN_PREPARE);
3194                     this.mState = SHUTDOWN_PREPARE;
3195                     break;
3196                 case VehicleApPowerStateReq.CANCEL_SHUTDOWN:
3197                     this.mCanPostpone = false;
3198                     this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED;
3199                     this.mCarPowerStateListenerState = CarPowerManager.STATE_SHUTDOWN_CANCELLED;
3200                     this.mState = WAIT_FOR_VHAL;
3201                     break;
3202                 case VehicleApPowerStateReq.FINISHED:
3203                     this.mCanPostpone = false;
3204                     this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED;
3205                     this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(SUSPEND);
3206                     this.mState = SUSPEND;
3207                     break;
3208                 default:
3209                     // Illegal state from PowerState.  Throw an exception?
3210                     // TODO(b/202414427): Add handling of illegal state
3211                     this.mCanPostpone = false;
3212                     this.mShutdownType = PowerState.SHUTDOWN_TYPE_UNDEFINED;
3213                     this.mCarPowerStateListenerState = 0;
3214                     this.mState = 0;
3215                     break;
3216             }
3217         }
3218 
CpmsState(int state, int carPowerStateListenerState, boolean canPostpone)3219         CpmsState(int state, int carPowerStateListenerState, boolean canPostpone) {
3220             this.mCanPostpone = canPostpone;
3221             this.mCarPowerStateListenerState = carPowerStateListenerState;
3222             this.mState = state;
3223             this.mShutdownType = state == SIMULATE_SLEEP ? PowerState.SHUTDOWN_TYPE_DEEP_SLEEP :
3224                     (state == SIMULATE_HIBERNATION ? PowerState.SHUTDOWN_TYPE_HIBERNATION
3225                             : PowerState.SHUTDOWN_TYPE_POWER_OFF);
3226         }
3227 
CpmsState(int state, int carPowerStateListenerState, boolean canPostpone, int shutdownType)3228         CpmsState(int state, int carPowerStateListenerState, boolean canPostpone,
3229                 int shutdownType) {
3230             this.mCanPostpone = canPostpone;
3231             this.mCarPowerStateListenerState = carPowerStateListenerState;
3232             this.mState = state;
3233             this.mShutdownType = shutdownType;
3234         }
3235 
name()3236         public String name() {
3237             return new StringBuilder()
3238                     .append(stateToString())
3239                     .append('(')
3240                     .append(mState)
3241                     .append(')')
3242                     .toString();
3243         }
3244 
stateToString()3245         private String stateToString() {
3246             String baseName;
3247             switch(mState) {
3248                 case WAIT_FOR_VHAL:         baseName = "WAIT_FOR_VHAL";        break;
3249                 case ON:                    baseName = "ON";                   break;
3250                 case SHUTDOWN_PREPARE:      baseName = "SHUTDOWN_PREPARE";     break;
3251                 case WAIT_FOR_FINISH:       baseName = "WAIT_FOR_FINISH";      break;
3252                 case SUSPEND:               baseName = "SUSPEND";              break;
3253                 case SIMULATE_SLEEP:        baseName = "SIMULATE_SLEEP";       break;
3254                 case SIMULATE_HIBERNATION:  baseName = "SIMULATE_HIBERNATION"; break;
3255                 default:                    baseName = "<unknown>";            break;
3256             }
3257             return baseName;
3258         }
3259 
cpmsStateToPowerStateListenerState(int state)3260         private static int cpmsStateToPowerStateListenerState(int state) {
3261             int powerStateListenerState = 0;
3262 
3263             // Set the CarPowerStateListenerState based on current state
3264             switch (state) {
3265                 case ON:
3266                     powerStateListenerState = CarPowerManager.STATE_ON;
3267                     break;
3268                 case SHUTDOWN_PREPARE:
3269                     powerStateListenerState = CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE;
3270                     break;
3271                 case SUSPEND:
3272                     powerStateListenerState = CarPowerManager.STATE_SUSPEND_ENTER;
3273                     break;
3274                 case WAIT_FOR_VHAL:
3275                 case WAIT_FOR_FINISH:
3276                 default:
3277                     // Illegal state for this constructor. Throw an exception?
3278                     break;
3279             }
3280             return powerStateListenerState;
3281         }
3282 
3283         @Override
equals(Object o)3284         public boolean equals(Object o) {
3285             if (this == o) {
3286                 return true;
3287             }
3288             if (!(o instanceof CpmsState)) {
3289                 return false;
3290             }
3291             CpmsState that = (CpmsState) o;
3292             return this.mState == that.mState
3293                     && this.mShutdownType == that.mShutdownType
3294                     && this.mCanPostpone == that.mCanPostpone
3295                     && this.mCarPowerStateListenerState == that.mCarPowerStateListenerState;
3296         }
3297 
3298         @Override
hashCode()3299         public int hashCode() {
3300             return Objects.hash(mCanPostpone, mShutdownType, mCarPowerStateListenerState, mState);
3301         }
3302 
3303         // PowerPolicyHostTest uses the dump output of {@code CarPowerManagementService}. If the
3304         // {@code CpmsState.toString} is modifed, PowerPolicyHostTest should be updated accordingly.
3305         // TODO(b/184862429): Remove the above comment once dump in proto buffer is done.
3306         @Override
toString()3307         public String toString() {
3308             return "CpmsState canPostpone=" + mCanPostpone
3309                     + ", carPowerStateListenerState=" + mCarPowerStateListenerState
3310                     + ", mShutdownType=" + mShutdownType
3311                     + ", CpmsState=" + name();
3312         }
3313     }
3314 
3315     /**
3316      * Resume after a manually-invoked suspend.
3317      * Invoked using "adb shell dumpsys cmd car_service resume".
3318      */
forceSimulatedResume()3319     public void forceSimulatedResume() {
3320         synchronized (mLock) {
3321             // Cancel Garage Mode in case it's running
3322             boolean isSuspendToDisk = mActionOnFinish == ACTION_ON_FINISH_HIBERNATION;
3323             mPendingPowerStates.addFirst(new CpmsState(CpmsState.WAIT_FOR_VHAL,
3324                     isSuspendToDisk ? CarPowerManager.STATE_HIBERNATION_EXIT
3325                             : CarPowerManager.STATE_SUSPEND_EXIT, /* canPostpone= */ false));
3326             mLock.notifyAll();
3327         }
3328         mHandler.handlePowerStateChange();
3329 
3330         synchronized (mSimulationWaitObject) {
3331             mWakeFromSimulatedSleep = true;
3332             mSimulationWaitObject.notifyAll();
3333         }
3334     }
3335 
3336     /**
3337      * Manually enters simulated suspend (deep sleep or hibernation) mode, trigging Garage mode.
3338      *
3339      * <p>If {@code shouldReboot} is 'true', reboots the system when Garage Mode completes.
3340      *
3341      * Can be invoked using
3342      * {@code "adb shell cmd car_service suspend --simulate"} or
3343      * {@code "adb shell cmd car_service hibernate --simulate"} or
3344      * {@code "adb shell cmd car_service garage-mode reboot"}.
3345      *
3346      * This is similar to {@code 'onApPowerStateChange()'} except that it needs to create a
3347      * {@code CpmsState} that is not directly derived from a {@code VehicleApPowerStateReq}.
3348      */
simulateSuspendAndMaybeReboot(@owerState.ShutdownType int shutdownType, boolean shouldReboot, boolean skipGarageMode, int wakeupAfter, boolean freeMemory)3349     public void simulateSuspendAndMaybeReboot(@PowerState.ShutdownType int shutdownType,
3350             boolean shouldReboot, boolean skipGarageMode, int wakeupAfter, boolean freeMemory) {
3351         simulateSuspendAndMaybeReboot(shutdownType, shouldReboot, skipGarageMode, wakeupAfter,
3352                 CarPowerManagementService.NO_WAKEUP_BY_TIMER, freeMemory);
3353     }
3354 
3355     /**
3356      * Manually enters simulated suspend (deep sleep or hibernation) mode, trigging Garage mode.
3357      *
3358      * <p>If {@code shouldReboot} is 'true', reboots the system when Garage Mode completes.
3359      *
3360      * Can be invoked using
3361      * {@code "adb shell cmd car_service suspend --simulate"} or
3362      * {@code "adb shell cmd car_service hibernate --simulate"} or
3363      * {@code "adb shell cmd car_service garage-mode reboot"}.
3364      *
3365      * This is similar to {@code 'onApPowerStateChange()'} except that it needs to create a
3366      * {@code CpmsState} that is not directly derived from a {@code VehicleApPowerStateReq}.
3367      */
3368     // TODO(b/274895468): Add tests
simulateSuspendAndMaybeReboot(@owerState.ShutdownType int shutdownType, boolean shouldReboot, boolean skipGarageMode, int wakeupAfter, int cancelAfter, boolean freeMemory)3369     public void simulateSuspendAndMaybeReboot(@PowerState.ShutdownType int shutdownType,
3370             boolean shouldReboot, boolean skipGarageMode, int wakeupAfter, int cancelAfter,
3371             boolean freeMemory) {
3372         boolean isDeepSleep = shutdownType == PowerState.SHUTDOWN_TYPE_DEEP_SLEEP;
3373         if (cancelAfter >= 0) {
3374             Slogf.i(TAG, "Cancel after is: %d", cancelAfter);
3375         }
3376         if (wakeupAfter >= 0) {
3377             Slogf.i(TAG, "Wakeup after is: %d", wakeupAfter);
3378         }
3379         synchronized (mSimulationWaitObject) {
3380             mInSimulatedDeepSleepMode = true;
3381             mWakeFromSimulatedSleep = false;
3382             mBlockFromSimulatedCancelEvent = false;
3383             mResumeDelayFromSimulatedSuspendSec = wakeupAfter;
3384             mCancelDelayFromSimulatedSuspendSec = cancelAfter;
3385             mFreeMemoryBeforeSuspend = freeMemory;
3386         }
3387         synchronized (mLock) {
3388             mRebootAfterGarageMode = shouldReboot;
3389             mPendingPowerStates.addFirst(new CpmsState(isDeepSleep ? CpmsState.SIMULATE_SLEEP
3390                             : CpmsState.SIMULATE_HIBERNATION,
3391                     CarPowerManager.STATE_PRE_SHUTDOWN_PREPARE, !skipGarageMode));
3392         }
3393         mHandler.handlePowerStateChange();
3394     }
3395 
3396     /**
3397      * Manually defines a power policy.
3398      *
3399      * <p>If the given ID already exists or specified power components are invalid, it fails.
3400      *
3401      * @return {@code true}, if successful. Otherwise, {@code false}.
3402      */
definePowerPolicyFromCommand(String[] args, IndentingPrintWriter writer)3403     public boolean definePowerPolicyFromCommand(String[] args, IndentingPrintWriter writer) {
3404         if (args.length < 2) {
3405             writer.println("Too few arguments");
3406             return false;
3407         }
3408         String powerPolicyId = args[1];
3409         int index = 2;
3410         String[] enabledComponents = new String[0];
3411         String[] disabledComponents = new String[0];
3412         while (index < args.length) {
3413             switch (args[index]) {
3414                 case "--enable":
3415                     if (index == args.length - 1) {
3416                         writer.println("No components for --enable");
3417                         return false;
3418                     }
3419                     enabledComponents = args[index + 1].split(",");
3420                     break;
3421                 case "--disable":
3422                     if (index == args.length - 1) {
3423                         writer.println("No components for --disabled");
3424                         return false;
3425                     }
3426                     disabledComponents = args[index + 1].split(",");
3427                     break;
3428                 default:
3429                     writer.printf("Unrecognized argument: %s\n", args[index]);
3430                     return false;
3431             }
3432             index += 2;
3433         }
3434         int status = definePowerPolicy(powerPolicyId, enabledComponents, disabledComponents);
3435         if (status != PolicyOperationStatus.OK) {
3436             writer.println(PolicyOperationStatus.errorCodeToString(status));
3437             return false;
3438         }
3439         writer.printf("Power policy(%s) is successfully defined.\n", powerPolicyId);
3440         return true;
3441     }
3442 
3443     /**
3444      * Defines a power policy with the given id and components.
3445      *
3446      * <p> A policy defined with this method is valid until the system is rebooted/restarted.
3447      */
3448     @VisibleForTesting
3449     @PolicyOperationStatus.ErrorCode
definePowerPolicy(String powerPolicyId, String[] enabledComponents, String[] disabledComponents)3450     public int definePowerPolicy(String powerPolicyId, String[] enabledComponents,
3451             String[] disabledComponents) {
3452         Preconditions.checkArgument(!powerPolicyId.startsWith(
3453                 PolicyReader.SYSTEM_POWER_POLICY_PREFIX),
3454                 "System power policy cannot be defined by apps");
3455         int status = mPolicyReader.definePowerPolicy(powerPolicyId,
3456                 enabledComponents, disabledComponents);
3457         if (status != PolicyOperationStatus.OK) {
3458             return status;
3459         }
3460         // Get custom power components and update components list in PowerComponentHandler
3461         Collection<Integer> customComponents = mPolicyReader.getCustomComponents().values();
3462         if (customComponents.size() > 0) {
3463             mPowerComponentHandler.registerCustomComponents(
3464                     customComponents.toArray(new Integer[customComponents.size()]));
3465         }
3466         if (mFeatureFlags.carPowerPolicyRefactoring()) {
3467             ICarPowerPolicyDelegate daemon;
3468             synchronized (mLock) {
3469                 daemon = mRefactoredCarPowerPolicyDaemon;
3470             }
3471             try {
3472                 daemon.notifyPowerPolicyDefinition(powerPolicyId, enabledComponents,
3473                         disabledComponents);
3474             } catch (IllegalArgumentException e) {
3475                 int policyError = PolicyOperationStatus.ERROR_INVALID_POWER_POLICY_ID;
3476                 int componentError = PolicyOperationStatus.ERROR_INVALID_POWER_COMPONENT;
3477                 Slogf.w(TAG, e, "%s and/or %s",
3478                         PolicyOperationStatus.errorCodeToString(policyError),
3479                         PolicyOperationStatus.errorCodeToString(componentError));
3480                 return policyError;
3481             } catch (IllegalStateException | RemoteException e) {
3482                 int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY;
3483                 Slogf.w(TAG, e, PolicyOperationStatus.errorCodeToString(error));
3484                 return error;
3485             } catch (SecurityException e) {
3486                 int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY;
3487                 Slogf.w(TAG, e, "%s; insufficient permissions",
3488                         PolicyOperationStatus.errorCodeToString(error));
3489                 return error;
3490             }
3491         } else {
3492             ICarPowerPolicySystemNotification daemon;
3493             synchronized (mLock) {
3494                 daemon = mCarPowerPolicyDaemon;
3495             }
3496             try {
3497                 daemon.notifyPowerPolicyDefinition(powerPolicyId, enabledComponents,
3498                         disabledComponents);
3499             } catch (RemoteException e) {
3500                 int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY;
3501                 Slogf.w(TAG, e, PolicyOperationStatus.errorCodeToString(error));
3502                 return error;
3503             }
3504         }
3505         return PolicyOperationStatus.OK;
3506     }
3507 
3508     /**
3509      * Manually applies a power policy.
3510      *
3511      * <p>If the given ID is not defined, it fails.
3512      *
3513      * @return {@code true}, if successful. Otherwise, {@code false}.
3514      */
applyPowerPolicyFromCommand(String[] args, IndentingPrintWriter writer)3515     public boolean applyPowerPolicyFromCommand(String[] args, IndentingPrintWriter writer) {
3516         if (args.length != 2) {
3517             writer.println("Power policy ID should be given");
3518             return false;
3519         }
3520         String powerPolicyId = args[1];
3521         if (powerPolicyId == null) {
3522             writer.println("Policy ID cannot be null");
3523             return false;
3524         }
3525         int status;
3526         Slogf.i(TAG, "Applying power policy(%s) from shell command", powerPolicyId);
3527         if (mFeatureFlags.carPowerPolicyRefactoring()) {
3528             status = applyPowerPolicy(powerPolicyId, /* delayNotification= */ false,
3529                     /* upToDaemon= */ false, /* force= */ false);
3530         } else {
3531             boolean isPreemptive = mPolicyReader.isPreemptivePowerPolicy(powerPolicyId);
3532             status = isPreemptive ? applyPreemptivePowerPolicy(powerPolicyId)
3533                     : applyPowerPolicy(powerPolicyId, /* delayNotification= */ false,
3534                             /* upToDaemon= */ true, /* force= */ false);
3535         }
3536         if (status != PolicyOperationStatus.OK) {
3537             writer.println(PolicyOperationStatus.errorCodeToString(status));
3538             return false;
3539         }
3540         writer.printf("Power policy(%s) is successfully applied.\n", powerPolicyId);
3541         return true;
3542     }
3543 
3544     /**
3545      * Manually defines a power policy group.
3546      *
3547      * <p>If the given ID already exists, a wrong power state is given, or specified power policy ID
3548      * doesn't exist, it fails.
3549      *
3550      * @return {@code true}, if successful. Otherwise, {@code false}.
3551      */
definePowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer)3552     public boolean definePowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer) {
3553         if (args.length < 3 || args.length > 4) {
3554             writer.println("Invalid syntax");
3555             return false;
3556         }
3557         String policyGroupId = args[1];
3558         int index = 2;
3559         SparseArray<String> defaultPolicyPerState = new SparseArray<>();
3560         String[] powerPolicyPerState = {"", ""};
3561         while (index < args.length) {
3562             String[] tokens = args[index].split(":");
3563             if (tokens.length != 2) {
3564                 writer.println("Invalid syntax");
3565                 return false;
3566             }
3567             int state = PolicyReader.toPowerState(tokens[0]);
3568             if (state == PolicyReader.INVALID_POWER_STATE) {
3569                 writer.printf("Invalid power state: %s\n", tokens[0]);
3570                 return false;
3571             }
3572             defaultPolicyPerState.put(state, tokens[1]);
3573             switch (state) {
3574                 case VehicleApPowerStateReport.WAIT_FOR_VHAL:
3575                     powerPolicyPerState[INDEX_WAIT_FOR_VHAL] = tokens[1];
3576                     break;
3577                 case VehicleApPowerStateReport.ON:
3578                     powerPolicyPerState[INDEX_ON] = tokens[1];
3579                     break;
3580             }
3581             index++;
3582         }
3583         if (mFeatureFlags.carPowerPolicyRefactoring()) {
3584             ICarPowerPolicyDelegate daemon;
3585             synchronized (mLock) {
3586                 daemon = mRefactoredCarPowerPolicyDaemon;
3587             }
3588             try {
3589                 daemon.notifyPowerPolicyGroupDefinition(policyGroupId, powerPolicyPerState);
3590             } catch (IllegalArgumentException e) {
3591                 Slogf.w(TAG, e, "The given policy group ID(%s) or mapping between power state and"
3592                         + " policy is invalid", policyGroupId);
3593                 return false;
3594             } catch (RemoteException e) {
3595                 Slogf.w(TAG, e, "Calling ICarPowerPolicyDelegate.notifyPowerPolicyGroupDefinition"
3596                         + " failed");
3597                 return false;
3598             }
3599         }
3600         int status = mPolicyReader.definePowerPolicyGroup(policyGroupId,
3601                 defaultPolicyPerState);
3602         if (status != PolicyOperationStatus.OK) {
3603             writer.println(PolicyOperationStatus.errorCodeToString(status));
3604             return false;
3605         }
3606         writer.printf("Power policy group(%s) is successfully defined.\n", policyGroupId);
3607         return true;
3608     }
3609 
3610     /**
3611      * Manually sets a power policy group.
3612      *
3613      * <p>If the given ID is not defined, it fails.
3614      *
3615      * @return {@code true}, if successful. Otherwise, {@code false}.
3616      */
setPowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer)3617     public boolean setPowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer) {
3618         if (args.length != 2) {
3619             writer.println("Power policy group ID should be given");
3620             return false;
3621         }
3622         String policyGroupId = args[1];
3623         if (mFeatureFlags.carPowerPolicyRefactoring()) {
3624             try {
3625                 setPowerPolicyGroup(policyGroupId);
3626             } catch (RemoteException e) {
3627                 writer.println("RemoteException encountered when setting power policy group");
3628                 return false;
3629             }
3630         } else {
3631             int status = setCurrentPowerPolicyGroup(policyGroupId);
3632             if (status != PolicyOperationStatus.OK) {
3633                 writer.println(PolicyOperationStatus.errorCodeToString(status));
3634                 return false;
3635             }
3636         }
3637         writer.printf("Setting power policy group(%s) is successful.\n", policyGroupId);
3638         return true;
3639     }
3640 
3641     /**
3642      * Suspends the device.
3643      *
3644      * <p>According to the argument, the device is suspended to RAM or disk.
3645      */
suspendFromCommand(boolean isHibernation, boolean skipGarageMode)3646     public void suspendFromCommand(boolean isHibernation, boolean skipGarageMode) {
3647         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
3648         int param = 0;
3649         if (isHibernation) {
3650             if (!isHibernationAvailable()) {
3651                 throw new IllegalStateException("The device doesn't support hibernation");
3652             }
3653             param = skipGarageMode ? VehicleApPowerStateShutdownParam.HIBERNATE_IMMEDIATELY
3654                     : VehicleApPowerStateShutdownParam.CAN_HIBERNATE;
3655         } else {
3656             if (!isDeepSleepAvailable()) {
3657                 throw new IllegalStateException("The device doesn't support deep sleep");
3658             }
3659             param = skipGarageMode ? VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY
3660                     : VehicleApPowerStateShutdownParam.CAN_SLEEP;
3661         }
3662         PowerState state = new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, param);
3663         synchronized (mLock) {
3664             mRebootAfterGarageMode = false;
3665             mPendingPowerStates.addFirst(new CpmsState(state));
3666             mLock.notifyAll();
3667         }
3668         mHandler.handlePowerStateChange();
3669     }
3670 
3671     /**
3672      * Powers off the device.
3673      */
powerOffFromCommand(boolean skipGarageMode, boolean reboot)3674     public void powerOffFromCommand(boolean skipGarageMode, boolean reboot) {
3675         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
3676         Slogf.i(TAG, "%s %s Garage Mode", reboot ? "Rebooting" : "Powering off",
3677                 skipGarageMode ? "with" : "without");
3678         int param = skipGarageMode ? VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY
3679                 : VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY;
3680         PowerState state = new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, param);
3681         synchronized (mLock) {
3682             mRebootAfterGarageMode = reboot;
3683             mPendingPowerStates.addFirst(new CpmsState(state));
3684             mLock.notifyAll();
3685         }
3686         mHandler.handlePowerStateChange();
3687     }
3688 
3689     /**
3690      * Returns the last shutdown state.
3691      */
getLastShutdownState()3692     public int getLastShutdownState() {
3693         synchronized (mLock) {
3694             return mLastShutdownState;
3695         }
3696     }
3697 
3698     /**
3699      * Changes Silent Mode to the given mode.
3700      */
setSilentMode(String silentMode)3701     public void setSilentMode(String silentMode) {
3702         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
3703         mSilentModeHandler.setSilentMode(silentMode);
3704         if (mFeatureFlags.carPowerPolicyRefactoring()) {
3705             ICarPowerPolicyDelegate daemon;
3706             synchronized (mLock) {
3707                 daemon = mRefactoredCarPowerPolicyDaemon;
3708             }
3709             if (daemon != null) {
3710                 try {
3711                     daemon.setSilentMode(silentMode);
3712                 } catch (RemoteException e) {
3713                     Slogf.e(TAG, e, "Failed to notify car power policy daemon of the new silent "
3714                             + "mode(%s)", silentMode);
3715                     return;
3716                 }
3717             } else {
3718                 Slogf.w(TAG, "Failed to notify the new silent mode, car power policy daemon"
3719                                 + " is not available");
3720                 return;
3721             }
3722             Slogf.i(TAG, "Set the new silent mode(%s) to CPPD", silentMode);
3723         }
3724     }
3725 
3726     /**
3727      * Dumps the current Silent Mode.
3728      */
3729     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dumpSilentMode(IndentingPrintWriter writer)3730     public void dumpSilentMode(IndentingPrintWriter writer) {
3731         mSilentModeHandler.dump(writer);
3732     }
3733 
3734     /**
3735      * Returns whether a listener completion is allowed for the given state.
3736      *
3737      * <p>This method is used internally and is different from
3738      * {@link CarPowerManager.isCompletionAllowed} in that listener completion is allowed for
3739      * SHUTDOWN_PREPARE.
3740      */
isCompletionAllowed(@arPowerManager.CarPowerState int state)3741     public static boolean isCompletionAllowed(@CarPowerManager.CarPowerState int state) {
3742         return CarPowerManager.isCompletionAllowed(state);
3743     }
3744 
3745     /**
3746      * Returns a corresponding string of the given power state.
3747      */
powerStateToString(int state)3748     public static String powerStateToString(int state) {
3749         return DebugUtils.valueToString(CarPowerManager.class, "STATE_", state);
3750     }
3751 
3752     /**
3753      * Requests VHAL to shutdown the head unit.
3754      *
3755      * @throws UnsupportedOperationException If the system doesn't not support
3756      *         {@code nextPowerState}.
3757      */
requestShutdownAp(int nextPowerState, boolean runGarageMode)3758     public void requestShutdownAp(int nextPowerState, boolean runGarageMode) {
3759         int shutdownParam = PowerState.SHUTDOWN_TYPE_POWER_OFF;
3760         switch (nextPowerState) {
3761             case CarRemoteAccessManager.NEXT_POWER_STATE_ON:
3762                 // Do nothing.
3763                 return;
3764             case CarRemoteAccessManager.NEXT_POWER_STATE_OFF:
3765                 shutdownParam = PowerState.SHUTDOWN_TYPE_POWER_OFF;
3766                 break;
3767             case CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_RAM:
3768                 if (!isDeepSleepAvailable()) {
3769                     throw new UnsupportedOperationException("Suspend-to-RAM is not supported");
3770                 }
3771                 shutdownParam = PowerState.SHUTDOWN_TYPE_DEEP_SLEEP;
3772                 break;
3773             case CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_DISK:
3774                 if (!isHibernationAvailable()) {
3775                     throw new UnsupportedOperationException("Suspend-to-disk is not supported");
3776                 }
3777                 shutdownParam = PowerState.SHUTDOWN_TYPE_HIBERNATION;
3778                 break;
3779             default:
3780                 Slogf.w(TAG, "Unknown power state(%d)", nextPowerState);
3781                 return;
3782         }
3783         mHal.requestShutdownAp(shutdownParam, runGarageMode);
3784     }
3785 
3786     /**
3787      * Returns whether suspend (deep sleep or hibernation) is available on the device.
3788      */
isSuspendAvailable(boolean isHibernation)3789     public boolean isSuspendAvailable(boolean isHibernation) {
3790         return isHibernation ? isHibernationAvailable() : isDeepSleepAvailable();
3791     }
3792 
3793     /**
3794      * Enters garage mode if the bootup reason is ENTER_GARAGE_MODE.
3795      */
3796     @Override
onInitComplete()3797     public void onInitComplete() {
3798         if (mFeatureFlags.serverlessRemoteAccess()) {
3799             maybeEnterGarageModeOnBoot();
3800         }
3801     }
3802 
3803     /**
3804      * Shutdown the device to run garage mode if the bootup reason is ENTER_GARAGE_MODE.
3805      */
maybeEnterGarageModeOnBoot()3806     private void maybeEnterGarageModeOnBoot() {
3807         @BootupReason int bootupReason = mHal.getVehicleApBootupReason();
3808         Slogf.i(TAG, "Vehicle AP power bootup reason: " + bootupReason);
3809         if (bootupReason != BOOTUP_REASON_SYSTEM_ENTER_GARAGE_MODE) {
3810             return;
3811         }
3812         if (mHal.isVehicleInUse()) {
3813             Slogf.i(TAG, "Bootup reason is ENTER_GARAGE_MODE but vehicle is currently in use"
3814                     + ", skip entering garage mode");
3815             return;
3816         }
3817         try {
3818             requestShutdownAp(getLastShutdownState(), /* runGarageMode= */ true);
3819         } catch (Exception e) {
3820             Slogf.wtf(TAG, "Failed to call requestShutdownAp", e);
3821         }
3822     }
3823 
isDeepSleepAvailable()3824     private boolean isDeepSleepAvailable() {
3825         return mHal.isDeepSleepAllowed() && mSystemInterface.isSystemSupportingDeepSleep();
3826     }
3827 
isHibernationAvailable()3828     private boolean isHibernationAvailable() {
3829         return mHal.isHibernationAllowed() && mSystemInterface.isSystemSupportingHibernation();
3830     }
3831 
3832     // In a real Deep Sleep, the hardware removes power from the CPU (but retains power
3833     // on the RAM). This puts the processor to sleep. Upon some external signal, power
3834     // is re-applied to the CPU, and processing resumes right where it left off.
3835     // We simulate this behavior by calling wait().
3836     // We continue from wait() when forceSimulatedResume() is called.
simulateSleepByWaiting()3837     private void simulateSleepByWaiting() {
3838         Slogf.i(TAG, "Starting to simulate Deep Sleep by waiting");
3839         synchronized (mSimulationWaitObject) {
3840             if (mFreeMemoryBeforeSuspend) {
3841                 freeMemory();
3842             }
3843             if (mResumeDelayFromSimulatedSuspendSec >= 0) {
3844                 Slogf.i(TAG, "Scheduling a wakeup after %d seconds",
3845                         mResumeDelayFromSimulatedSuspendSec);
3846                 Handler handler = new Handler(Looper.getMainLooper());
3847                 handler.postDelayed(() -> forceSimulatedResume(),
3848                         mResumeDelayFromSimulatedSuspendSec * 1000L);
3849             }
3850             while (!mWakeFromSimulatedSleep) {
3851                 try {
3852                     mSimulationWaitObject.wait();
3853                 } catch (InterruptedException ignored) {
3854                     Thread.currentThread().interrupt(); // Restore interrupted status
3855                 }
3856             }
3857             mInSimulatedDeepSleepMode = false;
3858         }
3859         Slogf.i(TAG, "Exit Deep Sleep simulation");
3860     }
3861 
getMaxSuspendWaitDurationConfig()3862     private int getMaxSuspendWaitDurationConfig() {
3863         return mContext.getResources().getInteger(R.integer.config_maxSuspendWaitDuration);
3864     }
3865 
isWifiAdjustmentForSuspendConfig()3866     private boolean isWifiAdjustmentForSuspendConfig() {
3867         return mContext.getResources().getBoolean(R.bool.config_wifiAdjustmentForSuspend);
3868     }
3869 
getPreShutdownPrepareTimeoutConfig()3870     private int getPreShutdownPrepareTimeoutConfig() {
3871         return getCompletionWaitTimeoutConfig(R.integer.config_preShutdownPrepareTimeout);
3872     }
3873 
getShutdownEnterTimeoutConfig()3874     private int getShutdownEnterTimeoutConfig() {
3875         return getCompletionWaitTimeoutConfig(R.integer.config_shutdownEnterTimeout);
3876     }
3877 
getPostShutdownEnterTimeoutConfig()3878     private int getPostShutdownEnterTimeoutConfig() {
3879         return getCompletionWaitTimeoutConfig(R.integer.config_postShutdownEnterTimeout);
3880     }
3881 
getS2dImportanceLevel()3882     private int getS2dImportanceLevel() {
3883         return convertMemorySuspendConfigToValue(mContext.getResources().getString(
3884                 R.string.config_suspend_to_disk_memory_savings));
3885     }
3886 
getS2dAllowList()3887     private ArraySet<String> getS2dAllowList() {
3888         return new ArraySet<>(mContext.getResources().getStringArray(
3889                 R.array.config_packages_not_to_stop_during_suspend));
3890     }
3891 
getCompletionWaitTimeoutConfig(int resourceId)3892     private int getCompletionWaitTimeoutConfig(int resourceId) {
3893         int timeout = mContext.getResources().getInteger(resourceId);
3894         return timeout >= 0 ? timeout : DEFAULT_COMPLETION_WAIT_TIMEOUT;
3895     }
3896 
3897     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
actionOnFinishToString(int actionOnFinish)3898     private static String actionOnFinishToString(int actionOnFinish) {
3899         switch (actionOnFinish) {
3900             case ACTION_ON_FINISH_SHUTDOWN:
3901                 return "Shutdown";
3902             case ACTION_ON_FINISH_DEEP_SLEEP:
3903                 return "Deep sleep";
3904             case ACTION_ON_FINISH_HIBERNATION:
3905                 return "Hibernation";
3906             default:
3907                 return "Unknown";
3908         }
3909     }
3910 
waitForCompletionWithShutdownPostpone( @arPowerManager.CarPowerState int carPowerStateListenerState, long timeoutMs, Runnable taskAtCompletion, long intervalMs)3911     private void waitForCompletionWithShutdownPostpone(
3912             @CarPowerManager.CarPowerState int carPowerStateListenerState, long timeoutMs,
3913             Runnable taskAtCompletion, long intervalMs) {
3914         Runnable taskAtInterval = () -> {
3915             mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS);
3916         };
3917 
3918         Slogf.i(TAG, "Start waiting for listener completion for %s",
3919                 powerStateToString(carPowerStateListenerState));
3920 
3921         waitForCompletion(taskAtCompletion, taskAtInterval, timeoutMs, intervalMs);
3922     }
3923 
3924     /**
3925      * Utility method to help with memory freeing before entering Suspend-To-Disk
3926      */
freeMemory()3927     private void freeMemory() {
3928         ActivityManagerHelper.killAllBackgroundProcesses();
3929         if (!mFeatureFlags.stopProcessBeforeSuspendToDisk()) {
3930             return;
3931         }
3932         List<ActivityManager.RunningAppProcessInfo> allRunningAppProcesses =
3933                 ActivityManagerHelper.getRunningAppProcesses();
3934         ArraySet<Integer> safeUids = new ArraySet<>();
3935         ArraySet<String> suspendToDiskAllowList = getS2dAllowList();
3936         int suspendToDiskImportanceLevel = getS2dImportanceLevel();
3937         for (int i = 0; i < allRunningAppProcesses.size(); i++) {
3938             ActivityManager.RunningAppProcessInfo info = allRunningAppProcesses.get(i);
3939             boolean isCarServiceOrMyPid = ICarImpl.class.getPackage().getName()
3940                     .equals(info.processName)
3941                     || info.pid == android.os.Process.myPid();
3942             boolean isSystemOrShellUid = info.uid == Process.SYSTEM_UID
3943                     || info.uid == Process.SHELL_UID;
3944             boolean isProcessPersistent = (ActivityManagerHelper
3945                     .getFlagsForRunningAppProcessInfo(info)
3946                     & ActivityManagerHelper.PROCESS_INFO_PERSISTENT_FLAG) != 0;
3947             boolean isWithinConfig = suspendToDiskImportanceLevel > info.importance;
3948             boolean isProcessAllowListed = suspendToDiskAllowList.contains(info.processName);
3949             if (isCarServiceOrMyPid || isSystemOrShellUid || isProcessPersistent
3950                     || isWithinConfig || isProcessAllowListed) {
3951                 safeUids.add(info.uid);
3952             }
3953         }
3954 
3955         for (int i = 0; i < allRunningAppProcesses.size(); i++) {
3956             ActivityManager.RunningAppProcessInfo info = allRunningAppProcesses.get(i);
3957             if (!safeUids.contains(info.uid)) {
3958                 for (int j = 0; j < info.pkgList.length; j++) {
3959                     String pkgToStop = info.pkgList[j];
3960                     PackageManagerHelper.forceStopPackageAsUser(mContext, pkgToStop,
3961                             UserManagerHelper.USER_ALL);
3962                 }
3963             }
3964         }
3965     }
3966 
3967     /**
3968      * Helper method to accept function with one displayId argument to run on all displays.
3969      */
forEachDisplay(@onNull Context context, @NonNull Consumer<Integer> consumer)3970     private static void forEachDisplay(@NonNull Context context,
3971             @NonNull Consumer<Integer> consumer) {
3972         DisplayManager displayManager = context.getSystemService(DisplayManager.class);
3973         for (Display display : displayManager.getDisplays()) {
3974             int displayId = display.getDisplayId();
3975             consumer.accept(displayId);
3976         }
3977     }
3978 
convertMemorySuspendConfigToValue(String configValue)3979     private int convertMemorySuspendConfigToValue(String configValue) {
3980         return switch (configValue) {
3981             case "low" -> ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
3982             case "medium" -> ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
3983             case "high" -> ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
3984             // none will fallthrough
3985             default -> ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
3986         };
3987     }
3988 }
3989