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