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