blob: 92ace7d826f4a3ff05cea532681e8dafc440cfdf [file] [log] [blame]
keunyoung4b0212c2015-10-29 17:11:57 -07001/*
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 */
Eric Jeongc1f53b22021-02-18 00:40:36 -080016
Eric Jeongbc351e22020-07-31 13:54:17 -070017package com.android.car.power;
keunyoung4b0212c2015-10-29 17:11:57 -070018
Jim Kaye24ddc862020-04-30 14:05:17 -070019import android.annotation.NonNull;
Eric Jeonga2934632020-11-08 23:14:30 -080020import android.annotation.Nullable;
Anthony Hughfbb67762019-10-15 12:54:54 -070021import android.app.ActivityManager;
Steve Paik87b36fd2018-03-13 19:25:47 -070022import android.car.Car;
23import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
Eric Jeongb7003812020-12-08 11:37:55 -080024import android.car.hardware.power.CarPowerPolicy;
Eric Jeong58762682020-11-30 21:51:32 -080025import android.car.hardware.power.CarPowerPolicyFilter;
Steve Paik87b36fd2018-03-13 19:25:47 -070026import android.car.hardware.power.ICarPower;
Eric Jeongd48f7072021-02-25 18:21:06 -080027import android.car.hardware.power.ICarPowerPolicyListener;
Steve Paik87b36fd2018-03-13 19:25:47 -070028import android.car.hardware.power.ICarPowerStateListener;
Mayank Gargfc24d572020-02-14 11:32:34 -080029import android.content.ComponentName;
Steve Paik87b36fd2018-03-13 19:25:47 -070030import android.content.Context;
Mayank Gargfc24d572020-02-14 11:32:34 -080031import android.content.Intent;
Felipe Lemef45ee502019-12-19 10:00:14 -080032import android.content.pm.UserInfo;
Felipe Leme848eb652019-12-18 09:53:18 -080033import android.content.res.Resources;
Eric Jeong0d3bb4f2020-11-06 11:31:45 -080034import android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification;
35import android.frameworks.automotive.powerpolicy.internal.PolicyState;
Eric Jeong36f61d42021-02-19 22:10:45 -080036import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReport;
Steve Paik07db5ed2018-09-24 16:48:52 -070037import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
Eric Jeonge701e0d2020-12-16 17:54:00 -080038import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam;
Eric Jeong26f47c72020-07-22 15:45:24 -070039import android.net.wifi.WifiManager;
Keun young Park8c152cb2019-05-09 18:04:31 -070040import android.os.Build;
Steve Paik87b36fd2018-03-13 19:25:47 -070041import android.os.Handler;
42import android.os.HandlerThread;
43import android.os.IBinder;
Eric Jeong58762682020-11-30 21:51:32 -080044import android.os.IInterface;
Steve Paik87b36fd2018-03-13 19:25:47 -070045import android.os.Looper;
46import android.os.Message;
Jim Kaye9a834ea2020-02-07 15:50:53 -080047import android.os.PowerManager;
Steve Paik87b36fd2018-03-13 19:25:47 -070048import android.os.RemoteCallbackList;
49import android.os.RemoteException;
Eric Jeong20a13b52020-10-02 23:50:40 -070050import android.os.ServiceManager;
Steve Paik87b36fd2018-03-13 19:25:47 -070051import android.os.SystemClock;
Keun young Park8c152cb2019-05-09 18:04:31 -070052import android.os.SystemProperties;
Keun young Park9b3f2662019-03-19 10:30:25 -070053import android.os.UserHandle;
Felipe Lemef45ee502019-12-19 10:00:14 -080054import android.os.UserManager;
Eric Jeong26f47c72020-07-22 15:45:24 -070055import android.util.AtomicFile;
Felipe Leme176a5fd2021-01-20 15:48:33 -080056import android.util.IndentingPrintWriter;
Eric Jeong110c9632021-04-09 10:59:50 -070057import android.util.SparseArray;
keunyoung4b0212c2015-10-29 17:11:57 -070058
Eric Jeongbc351e22020-07-31 13:54:17 -070059import com.android.car.CarLocalServices;
60import com.android.car.CarLog;
61import com.android.car.CarServiceBase;
62import com.android.car.CarServiceUtils;
63import com.android.car.CarStatsLogHelper;
64import com.android.car.ICarImpl;
65import com.android.car.R;
Mayank Gargfc24d572020-02-14 11:32:34 -080066import com.android.car.am.ContinuousBlankActivity;
keunyoung4b0212c2015-10-29 17:11:57 -070067import com.android.car.hal.PowerHalService;
68import com.android.car.hal.PowerHalService.PowerState;
Enrico Granatab19bc322017-10-12 12:25:06 -070069import com.android.car.systeminterface.SystemInterface;
Mayank Gargfc24d572020-02-14 11:32:34 -080070import com.android.car.user.CarUserNoticeService;
Felipe Lemee3cab982020-03-12 11:39:29 -070071import com.android.car.user.CarUserService;
keunyoung4b0212c2015-10-29 17:11:57 -070072import com.android.internal.annotations.GuardedBy;
Yao Chendacd7242016-01-26 14:42:42 -080073import com.android.internal.annotations.VisibleForTesting;
Felipe Leme6162a092021-01-07 16:41:33 -080074import com.android.internal.os.IResultReceiver;
Eric Jeong4b69cf72021-01-07 21:23:16 -080075import com.android.internal.util.Preconditions;
Eric Jeong20a13b52020-10-02 23:50:40 -070076import com.android.internal.util.function.pooled.PooledLambda;
Eric Jeongd37b78b2021-04-29 00:22:36 -070077import com.android.server.utils.Slogf;
keunyoung4b0212c2015-10-29 17:11:57 -070078
Eric Jeong26f47c72020-07-22 15:45:24 -070079import java.io.BufferedReader;
80import java.io.BufferedWriter;
81import java.io.File;
82import java.io.FileOutputStream;
83import java.io.IOException;
84import java.io.InputStreamReader;
85import java.io.OutputStreamWriter;
Keun young Parkb241d022020-04-20 20:31:34 -070086import java.lang.ref.WeakReference;
Eric Jeong26f47c72020-07-22 15:45:24 -070087import java.nio.charset.StandardCharsets;
Jim Kayee5133162019-04-22 12:50:27 -070088import java.util.HashSet;
Steve Paik87b36fd2018-03-13 19:25:47 -070089import java.util.LinkedList;
Jim Kayee5133162019-04-22 12:50:27 -070090import java.util.Set;
Steve Paik87b36fd2018-03-13 19:25:47 -070091import java.util.Timer;
92import java.util.TimerTask;
keunyoung4b0212c2015-10-29 17:11:57 -070093
Serik Beketayev1d9e0d82018-09-11 08:19:33 -070094/**
95 * Power Management service class for cars. Controls the power states and interacts with other
96 * parts of the system to ensure its own state.
97 */
98public class CarPowerManagementService extends ICarPower.Stub implements
99 CarServiceBase, PowerHalService.PowerEventListener {
Eric Jeongc1f53b22021-02-18 00:40:36 -0800100 public static final String SILENT_MODE_FORCED_SILENT =
101 SilentModeHandler.SILENT_MODE_FORCED_SILENT;
102 public static final String SILENT_MODE_FORCED_NON_SILENT =
103 SilentModeHandler.SILENT_MODE_FORCED_NON_SILENT;
104 public static final String SILENT_MODE_NON_FORCED = SilentModeHandler.SILENT_MODE_NON_FORCED;
Jim Kayed22f1d62019-12-03 16:08:00 -0800105
Mayank Garg72c71d22021-02-03 23:54:45 -0800106 private static final String TAG = CarLog.tagFor(CarPowerManagementService.class);
Eric Jeong26f47c72020-07-22 15:45:24 -0700107 private static final String WIFI_STATE_FILENAME = "wifi_state";
108 private static final String WIFI_STATE_MODIFIED = "forcibly_disabled";
109 private static final String WIFI_STATE_ORIGINAL = "original";
Jim Kayebe23e542020-08-11 12:07:11 -0700110 // If Suspend to RAM fails, we retry with an exponential back-off:
Eric Jeongdecc4252020-11-19 22:05:41 -0800111 // The wait interval will be 10 msec, 20 msec, 40 msec, ...
Eric Jeonged0b7122021-03-11 17:44:28 -0800112 // Once the wait interval goes beyond 100 msec, it is fixed at 100 msec.
Jim Kayebe23e542020-08-11 12:07:11 -0700113 private static final long INITIAL_SUSPEND_RETRY_INTERVAL_MS = 10;
Eric Jeonged0b7122021-03-11 17:44:28 -0800114 private static final long MAX_RETRY_INTERVAL_MS = 100;
Eric Jeongdecc4252020-11-19 22:05:41 -0800115 // Minimum and maximum wait duration before the system goes into Suspend to RAM.
116 private static final long MIN_SUSPEND_WAIT_DURATION_MS = 0;
117 private static final long MAX_SUSPEND_WAIT_DURATION_MS = 3 * 60 * 1000;
Felipe Lemee3cab982020-03-12 11:39:29 -0700118
Eric Jeong20a13b52020-10-02 23:50:40 -0700119 private static final long CAR_POWER_POLICY_DAEMON_FIND_MARGINAL_TIME_MS = 300;
120 private static final long CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS = 500;
121 private static final int CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY = 3;
122 private static final String CAR_POWER_POLICY_DAEMON_INTERFACE =
123 "carpowerpolicy_system_notification";
124
125 // TODO: Make this OEM configurable.
126 private static final int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
127 private static final int SHUTDOWN_EXTEND_MAX_MS = 5000;
128
129 // maxGarageModeRunningDurationInSecs should be equal or greater than this. 15 min for now.
130 private static final int MIN_MAX_GARAGE_MODE_DURATION_MS = 15 * 60 * 1000;
131
132 // in secs
133 private static final String PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE =
134 "android.car.garagemodeduration";
135
Jim Kayed22f1d62019-12-03 16:08:00 -0800136 private final Object mLock = new Object();
137 private final Object mSimulationWaitObject = new Object();
138
Steve Paik388d7772018-02-12 10:54:51 -0800139 private final Context mContext;
keunyoung4b0212c2015-10-29 17:11:57 -0700140 private final PowerHalService mHal;
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700141 private final SystemInterface mSystemInterface;
Jim Kayee5133162019-04-22 12:50:27 -0700142 // The listeners that complete simply by returning from onStateChanged()
Eric Jeong58762682020-11-30 21:51:32 -0800143 private final PowerManagerCallbackList<ICarPowerStateListener> mPowerManagerListeners =
144 new PowerManagerCallbackList<>(
145 l -> CarPowerManagementService.this.doUnregisterListener(l));
Jim Kayee5133162019-04-22 12:50:27 -0700146 // The listeners that must indicate asynchronous completion by calling finished().
Eric Jeong58762682020-11-30 21:51:32 -0800147 private final PowerManagerCallbackList<ICarPowerStateListener>
148 mPowerManagerListenersWithCompletion = new PowerManagerCallbackList<>(
149 l -> CarPowerManagementService.this.doUnregisterListener(l));
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800150
Eric Jeong20a13b52020-10-02 23:50:40 -0700151 @GuardedBy("mLock")
152 private final Set<IBinder> mListenersWeAreWaitingFor = new HashSet<>();
153 @GuardedBy("mLock")
154 private final LinkedList<CpmsState> mPendingPowerStates = new LinkedList<>();
155 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
156 getClass().getSimpleName());
157 private final PowerHandler mHandler = new PowerHandler(mHandlerThread.getLooper(), this);
158
159 private final UserManager mUserManager;
160 private final CarUserService mUserService;
161
162 private final WifiManager mWifiManager;
163 private final AtomicFile mWifiStateFile;
164
165 // This is a temp work-around to reduce user switching delay after wake-up.
166 private final boolean mSwitchGuestUserBeforeSleep;
167
Eric Jeongdecc4252020-11-19 22:05:41 -0800168 // CPMS tries to enter Suspend to RAM within the duration specified at
169 // mMaxSuspendWaitDurationMs. The default max duration is MAX_SUSPEND_WAIT_DRATION, and can be
170 // overridden by setting config_maxSuspendWaitDuration in an overrlay resource.
171 // The valid range is MIN_SUSPEND_WAIT_DRATION to MAX_SUSPEND_WAIT_DURATION.
172 private final long mMaxSuspendWaitDurationMs;
173
Jim Kayed22f1d62019-12-03 16:08:00 -0800174 @GuardedBy("mSimulationWaitObject")
175 private boolean mWakeFromSimulatedSleep;
176 @GuardedBy("mSimulationWaitObject")
177 private boolean mInSimulatedDeepSleepMode;
178
179 @GuardedBy("mLock")
Steve Paik07db5ed2018-09-24 16:48:52 -0700180 private CpmsState mCurrentState;
Jim Kayed22f1d62019-12-03 16:08:00 -0800181 @GuardedBy("mLock")
keunyoung4b0212c2015-10-29 17:11:57 -0700182 private Timer mTimer;
Jim Kayed22f1d62019-12-03 16:08:00 -0800183 @GuardedBy("mLock")
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800184 private long mProcessingStartTime;
Jim Kayed22f1d62019-12-03 16:08:00 -0800185 @GuardedBy("mLock")
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800186 private long mLastSleepEntryTime;
Keun young Parkb241d022020-04-20 20:31:34 -0700187
Jim Kayed22f1d62019-12-03 16:08:00 -0800188 @GuardedBy("mLock")
Serik Beketayevf8287a02019-02-08 12:31:10 -0800189 private boolean mTimerActive;
Jim Kayed22f1d62019-12-03 16:08:00 -0800190 @GuardedBy("mLock")
191 private int mNextWakeupSec;
192 @GuardedBy("mLock")
193 private boolean mShutdownOnFinish;
194 @GuardedBy("mLock")
Jim Kayedab62d82019-12-18 14:52:19 -0800195 private boolean mShutdownOnNextSuspend;
196 @GuardedBy("mLock")
Keun young Park9b3f2662019-03-19 10:30:25 -0700197 private boolean mIsBooting = true;
Jim Kayed22f1d62019-12-03 16:08:00 -0800198 @GuardedBy("mLock")
Jim Kaye253dfff2020-01-29 09:45:22 -0800199 private int mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS;
200 @GuardedBy("mLock")
201 private int mShutdownPollingIntervalMs = SHUTDOWN_POLLING_INTERVAL_MS;
202 @GuardedBy("mLock")
Jim Kaye9a834ea2020-02-07 15:50:53 -0800203 private boolean mRebootAfterGarageMode;
Jim Kaye9889f282020-05-28 09:17:17 -0700204 @GuardedBy("mLock")
205 private boolean mGarageModeShouldExitImmediately;
Felipe Lemee3cab982020-03-12 11:39:29 -0700206
Eric Jeong20a13b52020-10-02 23:50:40 -0700207 @GuardedBy("mLock")
208 private ICarPowerPolicySystemNotification mCarPowerPolicyDaemon;
209 @GuardedBy("mLock")
210 private boolean mConnectionInProgress;
211 private BinderHandler mBinderHandler;
Eric Jeong03e0cc32020-10-28 18:21:20 -0700212 @GuardedBy("mLock")
Eric Jeong36f61d42021-02-19 22:10:45 -0800213 private String mCurrentPowerPolicyId;
Eric Jeong03e0cc32020-10-28 18:21:20 -0700214 @GuardedBy("mLock")
Eric Jeong36f61d42021-02-19 22:10:45 -0800215 private String mPendingPowerPolicyId;
Eric Jeong4b69cf72021-01-07 21:23:16 -0800216 @GuardedBy("mLock")
Eric Jeong36f61d42021-02-19 22:10:45 -0800217 private String mCurrentPowerPolicyGroupId;
Eric Jeong4b69cf72021-01-07 21:23:16 -0800218 @GuardedBy("mLock")
219 private boolean mIsPowerPolicyLocked;
Eric Jeong79930092021-04-26 23:55:59 -0700220 @GuardedBy("mLock")
221 private boolean mHasControlOverDaemon;
Felipe Leme6162a092021-01-07 16:41:33 -0800222
223 @GuardedBy("mLock")
224 @Nullable
225 private IResultReceiver mFactoryResetCallback;
226
Eric Jeongd48f7072021-02-25 18:21:06 -0800227 private final PowerManagerCallbackList<ICarPowerPolicyListener> mPowerPolicyListeners =
Eric Jeong58762682020-11-30 21:51:32 -0800228 new PowerManagerCallbackList<>(
Eric Jeongd48f7072021-02-25 18:21:06 -0800229 l -> CarPowerManagementService.this.mPowerPolicyListeners.unregister(l));
Keun young Park62de5522020-03-10 10:47:09 -0700230
Eric Jeong03e0cc32020-10-28 18:21:20 -0700231 private final PowerComponentHandler mPowerComponentHandler;
Eric Jeong91969f22020-10-05 17:47:41 -0700232 private final PolicyReader mPolicyReader = new PolicyReader();
Eric Jeong36f61d42021-02-19 22:10:45 -0800233 private final SilentModeHandler mSilentModeHandler;
Eric Jeong91969f22020-10-05 17:47:41 -0700234
Eric Jeong58762682020-11-30 21:51:32 -0800235 interface ActionOnDeath<T extends IInterface> {
236 void take(T listener);
237 }
238
239 private final class PowerManagerCallbackList<T extends IInterface> extends
240 RemoteCallbackList<T> {
241 private ActionOnDeath<T> mActionOnDeath;
242
243 PowerManagerCallbackList(ActionOnDeath<T> action) {
244 mActionOnDeath = action;
245 }
246
Steve Paik03124082018-02-16 11:19:26 -0800247 /**
248 * Old version of {@link #onCallbackDied(E, Object)} that
249 * does not provide a cookie.
250 */
251 @Override
Eric Jeong58762682020-11-30 21:51:32 -0800252 public void onCallbackDied(T listener) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700253 Slogf.i(TAG, "binderDied %s", listener.asBinder());
Eric Jeong58762682020-11-30 21:51:32 -0800254 mActionOnDeath.take(listener);
Steve Paik03124082018-02-16 11:19:26 -0800255 }
256 }
257
Felipe Leme848eb652019-12-18 09:53:18 -0800258 public CarPowerManagementService(Context context, PowerHalService powerHal,
Eric Jeong1ed55602021-02-24 11:21:14 -0800259 SystemInterface systemInterface, CarUserService carUserService,
260 ICarPowerPolicySystemNotification powerPolicyDaemon) {
felipeal283b58f2020-04-01 12:49:05 -0700261 this(context, context.getResources(), powerHal, systemInterface, UserManager.get(context),
Eric Jeong1ed55602021-02-24 11:21:14 -0800262 carUserService, powerPolicyDaemon,
Eric Jeong36f61d42021-02-19 22:10:45 -0800263 new PowerComponentHandler(context, systemInterface),
264 /* silentModeHwStatePath= */ null, /* silentModeKernelStatePath= */ null,
265 /* bootReason= */ null);
Felipe Leme848eb652019-12-18 09:53:18 -0800266 }
267
268 @VisibleForTesting
Jim Kaye18624bf2020-05-01 16:14:12 -0700269 public CarPowerManagementService(Context context, Resources resources, PowerHalService powerHal,
Eric Jeong58762682020-11-30 21:51:32 -0800270 SystemInterface systemInterface, UserManager userManager, CarUserService carUserService,
271 ICarPowerPolicySystemNotification powerPolicyDaemon,
Eric Jeong36f61d42021-02-19 22:10:45 -0800272 PowerComponentHandler powerComponentHandler, @Nullable String silentModeHwStatePath,
273 @Nullable String silentModeKernelStatePath, @Nullable String bootReason) {
Steve Paik388d7772018-02-12 10:54:51 -0800274 mContext = context;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800275 mHal = powerHal;
276 mSystemInterface = systemInterface;
Felipe Lemef45ee502019-12-19 10:00:14 -0800277 mUserManager = userManager;
Jim Kaye253dfff2020-01-29 09:45:22 -0800278 mShutdownPrepareTimeMs = resources.getInteger(
Keun young Park4b4ddda2019-03-26 18:47:37 -0700279 R.integer.maxGarageModeRunningDurationInSecs) * 1000;
Keun young Park62de5522020-03-10 10:47:09 -0700280 mSwitchGuestUserBeforeSleep = resources.getBoolean(
281 R.bool.config_switchGuestUserBeforeGoingSleep);
Jim Kaye253dfff2020-01-29 09:45:22 -0800282 if (mShutdownPrepareTimeMs < MIN_MAX_GARAGE_MODE_DURATION_MS) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700283 Slogf.w(TAG,
284 "maxGarageModeRunningDurationInSecs smaller than minimum required, "
285 + "resource:%d(ms) while should exceed:%d(ms), Ignore resource.",
286 mShutdownPrepareTimeMs, MIN_MAX_GARAGE_MODE_DURATION_MS);
Jim Kaye253dfff2020-01-29 09:45:22 -0800287 mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS;
Keun young Park4b4ddda2019-03-26 18:47:37 -0700288 }
Felipe Lemee3cab982020-03-12 11:39:29 -0700289 mUserService = carUserService;
Eric Jeong58762682020-11-30 21:51:32 -0800290 mCarPowerPolicyDaemon = powerPolicyDaemon;
Eric Jeong79930092021-04-26 23:55:59 -0700291 if (powerPolicyDaemon != null) {
292 // For testing purpose
293 mHasControlOverDaemon = true;
294 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700295 mWifiManager = context.getSystemService(WifiManager.class);
296 mWifiStateFile = new AtomicFile(
297 new File(mSystemInterface.getSystemCarDir(), WIFI_STATE_FILENAME));
Eric Jeong58762682020-11-30 21:51:32 -0800298 mPowerComponentHandler = powerComponentHandler;
Eric Jeong36f61d42021-02-19 22:10:45 -0800299 mSilentModeHandler = new SilentModeHandler(this, silentModeHwStatePath,
300 silentModeKernelStatePath, bootReason);
Eric Jeongdecc4252020-11-19 22:05:41 -0800301 mMaxSuspendWaitDurationMs = Math.max(MIN_SUSPEND_WAIT_DURATION_MS,
302 Math.min(getMaxSuspendWaitDurationConfig(), MAX_SUSPEND_WAIT_DURATION_MS));
Yao Chendacd7242016-01-26 14:42:42 -0800303 }
304
Eric Jeongbc351e22020-07-31 13:54:17 -0700305 /**
306 * Overrides timers to keep testing time short.
307 *
308 * <p>Passing in {@code 0} resets the value to the default.
309 */
Steve Paik07db5ed2018-09-24 16:48:52 -0700310 @VisibleForTesting
Jim Kaye18624bf2020-05-01 16:14:12 -0700311 public void setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs) {
Jim Kaye253dfff2020-01-29 09:45:22 -0800312 synchronized (mLock) {
313 mShutdownPollingIntervalMs =
314 (pollingIntervalMs == 0) ? SHUTDOWN_POLLING_INTERVAL_MS : pollingIntervalMs;
315 mShutdownPrepareTimeMs =
316 (shutdownTimeoutMs == 0) ? SHUTDOWN_EXTEND_MAX_MS : shutdownTimeoutMs;
Steve Paik07db5ed2018-09-24 16:48:52 -0700317 }
318 }
319
Keun young Park57fd08e2019-12-13 09:24:59 -0800320 @VisibleForTesting
321 protected HandlerThread getHandlerThread() {
Keun young Parkb241d022020-04-20 20:31:34 -0700322 return mHandlerThread;
Keun young Park57fd08e2019-12-13 09:24:59 -0800323 }
324
keunyoung4b0212c2015-10-29 17:11:57 -0700325 @Override
326 public void init() {
Eric Jeong91969f22020-10-05 17:47:41 -0700327 mPolicyReader.init();
Eric Jeong36f61d42021-02-19 22:10:45 -0800328 mPowerComponentHandler.init();
keunyoung4b0212c2015-10-29 17:11:57 -0700329 mHal.setListener(this);
330 if (mHal.isPowerStateSupported()) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700331 // Initialize CPMS in WAIT_FOR_VHAL state
332 onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, CarPowerStateListener.WAIT_FOR_VHAL);
keunyoung4b0212c2015-10-29 17:11:57 -0700333 } else {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700334 Slogf.w(TAG, "Vehicle hal does not support power state yet.");
Steve Paik07db5ed2018-09-24 16:48:52 -0700335 onApPowerStateChange(CpmsState.ON, CarPowerStateListener.ON);
keunyoung4b0212c2015-10-29 17:11:57 -0700336 }
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800337 mSystemInterface.startDisplayStateMonitoring(this);
Eric Jeong20a13b52020-10-02 23:50:40 -0700338 connectToPowerPolicyDaemon();
keunyoung4b0212c2015-10-29 17:11:57 -0700339 }
340
341 @Override
342 public void release() {
Eric Jeong20a13b52020-10-02 23:50:40 -0700343 if (mBinderHandler != null) {
344 mBinderHandler.unlinkToDeath();
345 }
Jim Kayed22f1d62019-12-03 16:08:00 -0800346 synchronized (mLock) {
keunyoung4b0212c2015-10-29 17:11:57 -0700347 releaseTimerLocked();
348 mCurrentState = null;
Eric Jeong20a13b52020-10-02 23:50:40 -0700349 mCarPowerPolicyDaemon = null;
Pavel Maltsevddbff982017-03-22 14:49:02 -0700350 mHandler.cancelAll();
Jim Kayed22f1d62019-12-03 16:08:00 -0800351 mListenersWeAreWaitingFor.clear();
Pavel Maltsevddbff982017-03-22 14:49:02 -0700352 }
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800353 mSystemInterface.stopDisplayStateMonitoring();
Steve Paik03124082018-02-16 11:19:26 -0800354 mPowerManagerListeners.kill();
Eric Jeongd48f7072021-02-25 18:21:06 -0800355 mPowerPolicyListeners.kill();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800356 mSystemInterface.releaseAllWakeLocks();
keunyoung4b0212c2015-10-29 17:11:57 -0700357 }
358
keunyoung4b0212c2015-10-29 17:11:57 -0700359 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -0800360 public void dump(IndentingPrintWriter writer) {
Jim Kaye253dfff2020-01-29 09:45:22 -0800361 synchronized (mLock) {
362 writer.println("*PowerManagementService*");
Eric Jeong4b69cf72021-01-07 21:23:16 -0800363 writer.printf("mCurrentState: %s\n", mCurrentState);
364 writer.printf("mProcessingStartTime: %d\n", mProcessingStartTime);
365 writer.printf("mLastSleepEntryTime: %d\n", mLastSleepEntryTime);
366 writer.printf("mNextWakeupSec: %d\n", mNextWakeupSec);
367 writer.printf("mShutdownOnNextSuspend: %b\n", mShutdownOnNextSuspend);
368 writer.printf("mShutdownOnFinish: %b\n", mShutdownOnFinish);
369 writer.printf("mShutdownPollingIntervalMs: %d\n", mShutdownPollingIntervalMs);
370 writer.printf("mShutdownPrepareTimeMs: %d\n", mShutdownPrepareTimeMs);
371 writer.printf("mRebootAfterGarageMode: %b\n", mRebootAfterGarageMode);
372 writer.printf("mSwitchGuestUserBeforeSleep: %b\n", mSwitchGuestUserBeforeSleep);
Eric Jeong36f61d42021-02-19 22:10:45 -0800373 writer.printf("mCurrentPowerPolicyId: %s\n", mCurrentPowerPolicyId);
374 writer.printf("mPendingPowerPolicyId: %s\n", mPendingPowerPolicyId);
375 writer.printf("mCurrentPowerPolicyGroupId: %s\n", mCurrentPowerPolicyGroupId);
Eric Jeong4b69cf72021-01-07 21:23:16 -0800376 writer.printf("mIsPowerPolicyLocked: %b\n", mIsPowerPolicyLocked);
377 writer.printf("mMaxSuspendWaitDurationMs: %d\n", mMaxSuspendWaitDurationMs);
378 writer.printf("config_maxSuspendWaitDuration: %d\n", getMaxSuspendWaitDurationConfig());
379 writer.printf("# of power policy change listener: %d\n",
Eric Jeongd48f7072021-02-25 18:21:06 -0800380 mPowerPolicyListeners.getRegisteredCallbackCount());
Eric Jeong4b69cf72021-01-07 21:23:16 -0800381 writer.printf("mFactoryResetCallback: %s\n", mFactoryResetCallback);
Jim Kaye253dfff2020-01-29 09:45:22 -0800382 }
Eric Jeong91969f22020-10-05 17:47:41 -0700383 mPolicyReader.dump(writer);
Eric Jeong8f0d3c42021-03-16 20:12:24 -0700384 mPowerComponentHandler.dump(writer);
Eric Jeong4b69cf72021-01-07 21:23:16 -0800385 mSilentModeHandler.dump(writer);
Steve Paik110f95f2017-11-22 14:44:05 -0800386 }
387
388 @Override
keunyoung4b0212c2015-10-29 17:11:57 -0700389 public void onApPowerStateChange(PowerState state) {
Jim Kayed22f1d62019-12-03 16:08:00 -0800390 synchronized (mLock) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700391 mPendingPowerStates.addFirst(new CpmsState(state));
Jim Kayea94bb8b2020-07-28 09:42:35 -0700392 mLock.notify();
Steve Paik07db5ed2018-09-24 16:48:52 -0700393 }
Keun young Parkb241d022020-04-20 20:31:34 -0700394 mHandler.handlePowerStateChange();
Steve Paik07db5ed2018-09-24 16:48:52 -0700395 }
396
Keun young Park9b3f2662019-03-19 10:30:25 -0700397 @VisibleForTesting
Eric Jeong36f61d42021-02-19 22:10:45 -0800398 void setStateForWakeUp() {
399 mSilentModeHandler.init();
Jim Kayed22f1d62019-12-03 16:08:00 -0800400 synchronized (mLock) {
Eric Jeong36f61d42021-02-19 22:10:45 -0800401 mIsBooting = false;
Jim Kayed22f1d62019-12-03 16:08:00 -0800402 }
Eric Jeong36f61d42021-02-19 22:10:45 -0800403 handleWaitForVhal(new CpmsState(CpmsState.WAIT_FOR_VHAL,
404 CarPowerStateListener.WAIT_FOR_VHAL));
Eric Jeongd37b78b2021-04-29 00:22:36 -0700405 Slogf.d(TAG, "setStateForTesting(): mIsBooting is set to false and power state is switched "
Eric Jeong36f61d42021-02-19 22:10:45 -0800406 + "to Wait For Vhal");
Keun young Park9b3f2662019-03-19 10:30:25 -0700407 }
408
Steve Paik07db5ed2018-09-24 16:48:52 -0700409 /**
410 * Initiate state change from CPMS directly.
411 */
412 private void onApPowerStateChange(int apState, int carPowerStateListenerState) {
413 CpmsState newState = new CpmsState(apState, carPowerStateListenerState);
Jim Kayed22f1d62019-12-03 16:08:00 -0800414 synchronized (mLock) {
Jim Kaye9e802be2020-10-07 12:50:41 -0700415 if (newState.mState == CpmsState.WAIT_FOR_FINISH) {
416 // We are ready to shut down. Suppress this transition if
417 // there is a request to cancel the shutdown (WAIT_FOR_VHAL).
418 for (int idx = 0; idx < mPendingPowerStates.size(); idx++) {
419 if (mPendingPowerStates.get(idx).mState == CpmsState.WAIT_FOR_VHAL) {
420 // Completely ignore this WAIT_FOR_FINISH
421 return;
422 }
423 }
424 }
Steve Paik07db5ed2018-09-24 16:48:52 -0700425 mPendingPowerStates.addFirst(newState);
Jim Kayea94bb8b2020-07-28 09:42:35 -0700426 mLock.notify();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800427 }
Keun young Parkb241d022020-04-20 20:31:34 -0700428 mHandler.handlePowerStateChange();
keunyoung4b0212c2015-10-29 17:11:57 -0700429 }
430
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800431 private void doHandlePowerStateChange() {
Steve Paik07db5ed2018-09-24 16:48:52 -0700432 CpmsState state;
Jim Kayed22f1d62019-12-03 16:08:00 -0800433 synchronized (mLock) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800434 state = mPendingPowerStates.peekFirst();
435 mPendingPowerStates.clear();
436 if (state == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700437 Slogf.e(TAG, "Null power state was requested");
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800438 return;
439 }
Eric Jeongd37b78b2021-04-29 00:22:36 -0700440 Slogf.i(TAG, "doHandlePowerStateChange: newState=%s", state.name());
Steve Paik07db5ed2018-09-24 16:48:52 -0700441 if (!needPowerStateChangeLocked(state)) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800442 return;
443 }
444 // now real power change happens. Whatever was queued before should be all cancelled.
445 releaseTimerLocked();
Jim Kaye765e79e2020-06-04 13:48:54 -0700446 mCurrentState = state;
keunyoung4b0212c2015-10-29 17:11:57 -0700447 }
Keun young Parkb241d022020-04-20 20:31:34 -0700448 mHandler.cancelProcessingComplete();
Eric Jeongd37b78b2021-04-29 00:22:36 -0700449 Slogf.i(TAG, "setCurrentState %s", state);
Muhammad Qureshi94524cd2020-01-25 23:47:38 -0800450 CarStatsLogHelper.logPowerState(state.mState);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700451 switch (state.mState) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700452 case CpmsState.WAIT_FOR_VHAL:
453 handleWaitForVhal(state);
keunyoung4b0212c2015-10-29 17:11:57 -0700454 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700455 case CpmsState.ON:
456 handleOn();
keunyoung4b0212c2015-10-29 17:11:57 -0700457 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700458 case CpmsState.SHUTDOWN_PREPARE:
keunyoung4b0212c2015-10-29 17:11:57 -0700459 handleShutdownPrepare(state);
460 break;
Jim Kayed76c2742019-04-02 11:33:27 -0700461 case CpmsState.SIMULATE_SLEEP:
462 simulateShutdownPrepare();
463 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700464 case CpmsState.WAIT_FOR_FINISH:
465 handleWaitForFinish(state);
466 break;
467 case CpmsState.SUSPEND:
468 // Received FINISH from VHAL
469 handleFinish();
470 break;
471 default:
472 // Illegal state
473 // TODO: Throw exception?
474 break;
keunyoung4b0212c2015-10-29 17:11:57 -0700475 }
476 }
477
Steve Paik07db5ed2018-09-24 16:48:52 -0700478 private void handleWaitForVhal(CpmsState state) {
479 int carPowerStateListenerState = state.mCarPowerStateListenerState;
Eric Jeong4b69cf72021-01-07 21:23:16 -0800480 // TODO(b/177478420): Restore Wifi, Audio, Location, and Bluetooth, if they are artificially
481 // modified for S2R.
Eric Jeongc1f53b22021-02-18 00:40:36 -0800482 mSilentModeHandler.querySilentModeHwState();
Serik Beketayev004ce582019-01-27 17:56:26 -0800483 sendPowerManagerEvent(carPowerStateListenerState);
Steve Paik07db5ed2018-09-24 16:48:52 -0700484 // Inspect CarPowerStateListenerState to decide which message to send via VHAL
485 switch (carPowerStateListenerState) {
486 case CarPowerStateListener.WAIT_FOR_VHAL:
487 mHal.sendWaitForVhal();
488 break;
489 case CarPowerStateListener.SHUTDOWN_CANCELLED:
Jim Kayedab62d82019-12-18 14:52:19 -0800490 mShutdownOnNextSuspend = false; // This cancels the "NextSuspend"
Steve Paik07db5ed2018-09-24 16:48:52 -0700491 mHal.sendShutdownCancel();
492 break;
493 case CarPowerStateListener.SUSPEND_EXIT:
494 mHal.sendSleepExit();
495 break;
496 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700497 restoreWifi();
keunyoung4b0212c2015-10-29 17:11:57 -0700498 }
499
Mayank Gargfc24d572020-02-14 11:32:34 -0800500 private void updateCarUserNoticeServiceIfNecessary() {
501 try {
502 int currentUserId = ActivityManager.getCurrentUser();
503 UserInfo currentUserInfo = mUserManager.getUserInfo(currentUserId);
504 CarUserNoticeService carUserNoticeService =
505 CarLocalServices.getService(CarUserNoticeService.class);
506 if (currentUserInfo != null && currentUserInfo.isGuest()
507 && carUserNoticeService != null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700508 Slogf.i(TAG, "Car user notice service will ignore all messages before user "
509 + "switch.");
Mayank Gargfc24d572020-02-14 11:32:34 -0800510 Intent intent = new Intent();
511 intent.setComponent(new ComponentName(mContext.getPackageName(),
512 ContinuousBlankActivity.class.getName()));
513 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
514 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
515 carUserNoticeService.ignoreUserNotice(currentUserId);
516 }
517 } catch (Exception e) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700518 Slogf.w(TAG, e, "Cannot ignore user notice for current user");
Mayank Gargfc24d572020-02-14 11:32:34 -0800519 }
520 }
521
Felipe Leme6162a092021-01-07 16:41:33 -0800522 @VisibleForTesting
523 void handleOn() {
524 if (factoryResetIfNeeded()) return;
525
Mayank Gargfc24d572020-02-14 11:32:34 -0800526 // If current user is a Guest User, we want to inform CarUserNoticeService not to show
527 // notice for current user, and show user notice only for the target user.
Keun young Park62de5522020-03-10 10:47:09 -0700528 if (!mSwitchGuestUserBeforeSleep) {
529 updateCarUserNoticeServiceIfNecessary();
530 }
Mayank Gargfc24d572020-02-14 11:32:34 -0800531
Eric Jeong36f61d42021-02-19 22:10:45 -0800532 boolean isPreemptive;
533 synchronized (mLock) {
534 isPreemptive = mPolicyReader.isPreemptivePowerPolicy(mCurrentPowerPolicyId);
535 }
536 if (!mSilentModeHandler.isSilentMode() && isPreemptive) {
537 cancelPreemptivePowerPolicy();
538 } else {
539 applyDefaultPowerPolicyForState(VehicleApPowerStateReport.ON,
540 PolicyReader.POWER_POLICY_ID_ALL_ON);
541 }
542
Serik Beketayev004ce582019-01-27 17:56:26 -0800543 sendPowerManagerEvent(CarPowerStateListener.ON);
felipeal524e2652020-05-27 19:26:46 -0700544
Steve Paik07db5ed2018-09-24 16:48:52 -0700545 mHal.sendOn();
Felipe Lemef45ee502019-12-19 10:00:14 -0800546
Mayank Garg0baf88a2020-08-30 21:57:36 -0700547 synchronized (mLock) {
548 if (mIsBooting) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700549 Slogf.d(TAG, "handleOn(): called on boot");
Mayank Garg0baf88a2020-08-30 21:57:36 -0700550 mIsBooting = false;
551 return;
552 }
553 }
554
Felipe Lemef45ee502019-12-19 10:00:14 -0800555 try {
Mayank Garg0baf88a2020-08-30 21:57:36 -0700556 mUserService.onResume();
Felipe Lemef45ee502019-12-19 10:00:14 -0800557 } catch (Exception e) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700558 Slogf.e(TAG, e, "Could not switch user on resume");
Felipe Lemef45ee502019-12-19 10:00:14 -0800559 }
560 }
561
Felipe Leme6162a092021-01-07 16:41:33 -0800562 private boolean factoryResetIfNeeded() {
563 IResultReceiver callback;
564 synchronized (mLock) {
565 if (mFactoryResetCallback == null) return false;
566 callback = mFactoryResetCallback;
567 }
568
569 try {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700570 Slogf.i(TAG, "Factory resetting as it was delayed by user");
Felipe Leme6162a092021-01-07 16:41:33 -0800571 callback.send(/* resultCode= */ 0, /* resultData= */ null);
572 return true;
573 } catch (Exception e) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700574 Slogf.wtf(TAG, e, "Should have factory reset, but failed");
Felipe Leme6162a092021-01-07 16:41:33 -0800575 return false;
576 }
577 }
578
Eric Jeong36f61d42021-02-19 22:10:45 -0800579 private void applyDefaultPowerPolicyForState(int state, @Nullable String fallbackPolicyId) {
580 CarPowerPolicy policy;
581 synchronized (mLock) {
582 policy = mPolicyReader
583 .getDefaultPowerPolicyForState(mCurrentPowerPolicyGroupId, state);
584 }
585 if (policy == null && fallbackPolicyId == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700586 Slogf.w(TAG, "No default power policy for %s is found",
587 PolicyReader.powerStateToString(state));
Eric Jeong36f61d42021-02-19 22:10:45 -0800588 return;
589 }
590 String policyId = policy == null ? fallbackPolicyId : policy.getPolicyId();
591 applyPowerPolicy(policyId, /* upToDaemon= */ true);
592 }
593
Felipe Leme6162a092021-01-07 16:41:33 -0800594 /**
595 * Sets the callback used to factory reset the device on resume when the user delayed it.
596 */
597 public void setFactoryResetCallback(IResultReceiver callback) {
598 synchronized (mLock) {
599 mFactoryResetCallback = callback;
600 }
601 }
602
Felipe Lemee3cab982020-03-12 11:39:29 -0700603 /**
Jim Kaye9889f282020-05-28 09:17:17 -0700604 * Tells Garage Mode if it should run normally, or just
605 * exit immediately without indicating 'idle'
606 * @return True if no idle jobs should be run
607 * @hide
608 */
609 public boolean garageModeShouldExitImmediately() {
610 synchronized (mLock) {
611 return mGarageModeShouldExitImmediately;
612 }
613 }
614
Steve Paik07db5ed2018-09-24 16:48:52 -0700615 private void handleShutdownPrepare(CpmsState newState) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700616 // Shutdown on finish if the system doesn't support deep sleep or doesn't allow it.
Jim Kayed22f1d62019-12-03 16:08:00 -0800617 synchronized (mLock) {
Jim Kayedab62d82019-12-18 14:52:19 -0800618 mShutdownOnFinish = mShutdownOnNextSuspend
619 || !mHal.isDeepSleepAllowed()
Jim Kayed22f1d62019-12-03 16:08:00 -0800620 || !mSystemInterface.isSystemSupportingDeepSleep()
621 || !newState.mCanSleep;
Jim Kaye9889f282020-05-28 09:17:17 -0700622 mGarageModeShouldExitImmediately = !newState.mCanPostpone;
Jim Kayed22f1d62019-12-03 16:08:00 -0800623 }
Eric Jeongd37b78b2021-04-29 00:22:36 -0700624 Slogf.i(TAG,
Jim Kaye9889f282020-05-28 09:17:17 -0700625 (newState.mCanPostpone
626 ? "starting shutdown prepare with Garage Mode"
627 : "starting shutdown prepare without Garage Mode"));
Eric Jeong4b69cf72021-01-07 21:23:16 -0800628 makeSureNoUserInteraction();
Jim Kaye9889f282020-05-28 09:17:17 -0700629 sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE);
630 mHal.sendShutdownPrepare();
631 doHandlePreprocessing();
keunyoung4b0212c2015-10-29 17:11:57 -0700632 }
633
Jim Kayed76c2742019-04-02 11:33:27 -0700634 // Simulate system shutdown to Deep Sleep
635 private void simulateShutdownPrepare() {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700636 Slogf.i(TAG, "starting shutdown prepare");
Eric Jeong83225c72021-05-13 13:22:45 -0700637 makeSureNoUserInteraction();
Jim Kayed76c2742019-04-02 11:33:27 -0700638 sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE);
639 mHal.sendShutdownPrepare();
640 doHandlePreprocessing();
641 }
642
Steve Paik07db5ed2018-09-24 16:48:52 -0700643 private void handleWaitForFinish(CpmsState state) {
Serik Beketayev004ce582019-01-27 17:56:26 -0800644 sendPowerManagerEvent(state.mCarPowerStateListenerState);
Jim Kayed22f1d62019-12-03 16:08:00 -0800645 int wakeupSec;
646 synchronized (mLock) {
Jim Kaye9889f282020-05-28 09:17:17 -0700647 // If we're shutting down immediately, don't schedule
648 // a wakeup time.
649 wakeupSec = mGarageModeShouldExitImmediately ? 0 : mNextWakeupSec;
Jim Kayed22f1d62019-12-03 16:08:00 -0800650 }
Steve Paik07db5ed2018-09-24 16:48:52 -0700651 switch (state.mCarPowerStateListenerState) {
652 case CarPowerStateListener.SUSPEND_ENTER:
Jim Kayed22f1d62019-12-03 16:08:00 -0800653 mHal.sendSleepEntry(wakeupSec);
Steve Paik07db5ed2018-09-24 16:48:52 -0700654 break;
655 case CarPowerStateListener.SHUTDOWN_ENTER:
Jim Kayed22f1d62019-12-03 16:08:00 -0800656 mHal.sendShutdownStart(wakeupSec);
Steve Paik07db5ed2018-09-24 16:48:52 -0700657 break;
658 }
659 }
660
661 private void handleFinish() {
Jim Kaye4ae10b42019-04-02 11:42:50 -0700662 boolean simulatedMode;
Jim Kayed22f1d62019-12-03 16:08:00 -0800663 synchronized (mSimulationWaitObject) {
Jim Kaye4ae10b42019-04-02 11:42:50 -0700664 simulatedMode = mInSimulatedDeepSleepMode;
Jim Kayed22f1d62019-12-03 16:08:00 -0800665 }
666 boolean mustShutDown;
Jim Kaye9a834ea2020-02-07 15:50:53 -0800667 boolean forceReboot;
Jim Kayed22f1d62019-12-03 16:08:00 -0800668 synchronized (mLock) {
Jim Kaye4ae10b42019-04-02 11:42:50 -0700669 mustShutDown = mShutdownOnFinish && !simulatedMode;
Jim Kaye9a834ea2020-02-07 15:50:53 -0800670 forceReboot = mRebootAfterGarageMode;
671 mRebootAfterGarageMode = false;
672 }
673 if (forceReboot) {
674 PowerManager powerManager = mContext.getSystemService(PowerManager.class);
675 if (powerManager == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700676 Slogf.wtf(TAG, "No PowerManager. Cannot reboot.");
Jim Kaye9a834ea2020-02-07 15:50:53 -0800677 } else {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700678 Slogf.i(TAG, "GarageMode has completed. Forcing reboot.");
Jim Kaye9a834ea2020-02-07 15:50:53 -0800679 powerManager.reboot("GarageModeReboot");
680 throw new AssertionError("Should not return from PowerManager.reboot()");
681 }
Jim Kaye4ae10b42019-04-02 11:42:50 -0700682 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700683 // To make Kernel implementation simpler when going into sleep.
684 disableWifi();
685
Jim Kaye4ae10b42019-04-02 11:42:50 -0700686 if (mustShutDown) {
Serik Beketayevdfedda22018-12-11 16:56:01 -0800687 // shutdown HU
688 mSystemInterface.shutdown();
Steve Paik07db5ed2018-09-24 16:48:52 -0700689 } else {
Jim Kaye4ae10b42019-04-02 11:42:50 -0700690 doHandleDeepSleep(simulatedMode);
Steve Paik07db5ed2018-09-24 16:48:52 -0700691 }
Jim Kayedab62d82019-12-18 14:52:19 -0800692 mShutdownOnNextSuspend = false;
Steve Paik07db5ed2018-09-24 16:48:52 -0700693 }
694
Eric Jeong26f47c72020-07-22 15:45:24 -0700695 private void restoreWifi() {
696 boolean needToRestore = readWifiModifiedState();
697 if (needToRestore) {
698 if (!mWifiManager.isWifiEnabled()) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700699 Slogf.i(TAG, "Wifi has been enabled to restore the last setting");
Eric Jeong26f47c72020-07-22 15:45:24 -0700700 mWifiManager.setWifiEnabled(true);
701 }
702 // Update the persistent data as wifi is not modified by car framework.
703 saveWifiModifiedState(false);
704 }
705 }
706
707 private void disableWifi() {
708 boolean wifiEnabled = mWifiManager.isWifiEnabled();
709 boolean wifiModifiedState = readWifiModifiedState();
710 if (wifiEnabled != wifiModifiedState) {
711 saveWifiModifiedState(wifiEnabled);
712 }
713 if (!wifiEnabled) return;
714
715 mWifiManager.setWifiEnabled(false);
Eric Jeongd37b78b2021-04-29 00:22:36 -0700716 Slogf.i(TAG, "Wifi has been disabled and the last setting was saved");
Eric Jeong26f47c72020-07-22 15:45:24 -0700717 }
718
719 private void saveWifiModifiedState(boolean forciblyDisabled) {
720 FileOutputStream fos;
721 try {
722 fos = mWifiStateFile.startWrite();
723 } catch (IOException e) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700724 Slogf.e(TAG, e, "Cannot create %s", WIFI_STATE_FILENAME);
Eric Jeong26f47c72020-07-22 15:45:24 -0700725 return;
726 }
727
728 try (BufferedWriter writer = new BufferedWriter(
729 new OutputStreamWriter(fos, StandardCharsets.UTF_8))) {
730 writer.write(forciblyDisabled ? WIFI_STATE_MODIFIED : WIFI_STATE_ORIGINAL);
731 writer.newLine();
732 writer.flush();
733 mWifiStateFile.finishWrite(fos);
734 } catch (IOException e) {
735 mWifiStateFile.failWrite(fos);
Eric Jeongd37b78b2021-04-29 00:22:36 -0700736 Slogf.e(TAG, e, "Writing %s failed", WIFI_STATE_FILENAME);
Eric Jeong26f47c72020-07-22 15:45:24 -0700737 }
738 }
739
740 private boolean readWifiModifiedState() {
741 boolean needToRestore = false;
742 boolean invalidState = false;
743
744 try (BufferedReader reader = new BufferedReader(
745 new InputStreamReader(mWifiStateFile.openRead(), StandardCharsets.UTF_8))) {
746 String line = reader.readLine();
747 if (line == null) {
748 needToRestore = false;
749 invalidState = true;
750 } else {
751 line = line.trim();
752 needToRestore = WIFI_STATE_MODIFIED.equals(line);
753 invalidState = !(needToRestore || WIFI_STATE_ORIGINAL.equals(line));
754 }
755 } catch (IOException e) {
756 // If a file named wifi_state doesn't exist, we will not modify Wifi at system start.
Eric Jeongd37b78b2021-04-29 00:22:36 -0700757 Slogf.w(TAG, "Failed to read %s: %s", WIFI_STATE_FILENAME, e);
Eric Jeong26f47c72020-07-22 15:45:24 -0700758 return false;
759 }
760 if (invalidState) {
761 mWifiStateFile.delete();
762 }
763
764 return needToRestore;
765 }
766
Jim Kayed22f1d62019-12-03 16:08:00 -0800767 @GuardedBy("mLock")
keunyoung4b0212c2015-10-29 17:11:57 -0700768 private void releaseTimerLocked() {
Jim Kayed22f1d62019-12-03 16:08:00 -0800769 if (mTimer != null) {
770 mTimer.cancel();
keunyoung4b0212c2015-10-29 17:11:57 -0700771 }
Jim Kayed22f1d62019-12-03 16:08:00 -0800772 mTimer = null;
773 mTimerActive = false;
keunyoung4b0212c2015-10-29 17:11:57 -0700774 }
775
Steve Paik07db5ed2018-09-24 16:48:52 -0700776 private void doHandlePreprocessing() {
Jim Kaye253dfff2020-01-29 09:45:22 -0800777 int intervalMs;
778 int pollingCount;
779 synchronized (mLock) {
780 intervalMs = mShutdownPollingIntervalMs;
781 pollingCount = (mShutdownPrepareTimeMs / mShutdownPollingIntervalMs) + 1;
782 }
Keun young Park8c152cb2019-05-09 18:04:31 -0700783 if (Build.IS_USERDEBUG || Build.IS_ENG) {
784 int shutdownPrepareTimeOverrideInSecs =
785 SystemProperties.getInt(PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE, -1);
786 if (shutdownPrepareTimeOverrideInSecs >= 0) {
787 pollingCount =
Jim Kaye253dfff2020-01-29 09:45:22 -0800788 (shutdownPrepareTimeOverrideInSecs * 1000 / intervalMs)
Keun young Park8c152cb2019-05-09 18:04:31 -0700789 + 1;
Eric Jeongd37b78b2021-04-29 00:22:36 -0700790 Slogf.i(TAG, "Garage mode duration overridden secs: %d",
791 shutdownPrepareTimeOverrideInSecs);
Keun young Park8c152cb2019-05-09 18:04:31 -0700792 }
793 }
Eric Jeongd37b78b2021-04-29 00:22:36 -0700794 Slogf.i(TAG, "processing before shutdown expected for: %dms, adding polling:%d",
795 mShutdownPrepareTimeMs, pollingCount);
Mikhail Petrov8d970a42021-04-26 20:08:12 -0700796 boolean allAreComplete;
Jim Kayed22f1d62019-12-03 16:08:00 -0800797 synchronized (mLock) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700798 mProcessingStartTime = SystemClock.elapsedRealtime();
799 releaseTimerLocked();
Mikhail Petrov8d970a42021-04-26 20:08:12 -0700800 allAreComplete = mListenersWeAreWaitingFor.isEmpty();
801 if (allAreComplete) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700802 Slogf.i(TAG, "Listener queue is empty, don't start polling");
Mikhail Petrov8d970a42021-04-26 20:08:12 -0700803 } else {
804 mTimer = new Timer();
805 mTimerActive = true;
806 mTimer.scheduleAtFixedRate(
807 new ShutdownProcessingTimerTask(pollingCount),
Eric Jeongd37b78b2021-04-29 00:22:36 -0700808 /* delay= */ 0,
Mikhail Petrov8d970a42021-04-26 20:08:12 -0700809 intervalMs);
810 }
811 }
812 if (allAreComplete) {
813 signalComplete();
keunyoung4b0212c2015-10-29 17:11:57 -0700814 }
Mayank Garg7e1450b2020-08-07 18:15:15 -0700815 // allowUserSwitch value doesn't matter for onSuspend = true
Mayank Garg0baf88a2020-08-30 21:57:36 -0700816 mUserService.onSuspend();
keunyoung4b0212c2015-10-29 17:11:57 -0700817 }
818
Serik Beketayev004ce582019-01-27 17:56:26 -0800819 private void sendPowerManagerEvent(int newState) {
Jim Kayee5133162019-04-22 12:50:27 -0700820 // Broadcast to the listeners that do not signal completion
821 notifyListeners(mPowerManagerListeners, newState);
Serik Beketayev004ce582019-01-27 17:56:26 -0800822
Jim Kayee5133162019-04-22 12:50:27 -0700823 // SHUTDOWN_PREPARE is the only state where we need
824 // to maintain callbacks from listener components.
825 boolean allowCompletion = (newState == CarPowerStateListener.SHUTDOWN_PREPARE);
Serik Beketayev004ce582019-01-27 17:56:26 -0800826
Jim Kayee5133162019-04-22 12:50:27 -0700827 // Fully populate mListenersWeAreWaitingFor before calling any onStateChanged()
828 // for the listeners that signal completion.
829 // Otherwise, if the first listener calls finish() synchronously, we will
830 // see the list go empty and we will think that we are done.
831 boolean haveSomeCompleters = false;
Eric Jeong58762682020-11-30 21:51:32 -0800832 PowerManagerCallbackList<ICarPowerStateListener> completingListeners =
833 new PowerManagerCallbackList(l -> { });
Jim Kayed22f1d62019-12-03 16:08:00 -0800834 synchronized (mLock) {
Jim Kayee5133162019-04-22 12:50:27 -0700835 mListenersWeAreWaitingFor.clear();
836 int idx = mPowerManagerListenersWithCompletion.beginBroadcast();
837 while (idx-- > 0) {
838 ICarPowerStateListener listener =
839 mPowerManagerListenersWithCompletion.getBroadcastItem(idx);
840 completingListeners.register(listener);
841 if (allowCompletion) {
842 mListenersWeAreWaitingFor.add(listener.asBinder());
843 haveSomeCompleters = true;
Serik Beketayev004ce582019-01-27 17:56:26 -0800844 }
845 }
Jim Kayee5133162019-04-22 12:50:27 -0700846 mPowerManagerListenersWithCompletion.finishBroadcast();
847 }
848 // Broadcast to the listeners that DO signal completion
849 notifyListeners(completingListeners, newState);
850
851 if (allowCompletion && !haveSomeCompleters) {
852 // No jobs need to signal completion. So we are now complete.
853 signalComplete();
Serik Beketayev004ce582019-01-27 17:56:26 -0800854 }
855 }
856
Eric Jeong58762682020-11-30 21:51:32 -0800857 private void notifyListeners(PowerManagerCallbackList<ICarPowerStateListener> listenerList,
858 int newState) {
Jim Kayee5133162019-04-22 12:50:27 -0700859 int idx = listenerList.beginBroadcast();
860 while (idx-- > 0) {
861 ICarPowerStateListener listener = listenerList.getBroadcastItem(idx);
862 try {
863 listener.onStateChanged(newState);
864 } catch (RemoteException e) {
865 // It's likely the connection snapped. Let binder death handle the situation.
Eric Jeongd37b78b2021-04-29 00:22:36 -0700866 Slogf.e(TAG, e, "onStateChanged() call failed");
Steve Paik03124082018-02-16 11:19:26 -0800867 }
Steve Paik03124082018-02-16 11:19:26 -0800868 }
Jim Kayee5133162019-04-22 12:50:27 -0700869 listenerList.finishBroadcast();
Steve Paik03124082018-02-16 11:19:26 -0800870 }
871
Jim Kaye4ae10b42019-04-02 11:42:50 -0700872 private void doHandleDeepSleep(boolean simulatedMode) {
Eric Jeong83225c72021-05-13 13:22:45 -0700873 int status = applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_SUSPEND_TO_RAM);
874 if (status != PolicyOperationStatus.OK) {
875 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
876 }
Keun-young Park9d4cf622016-08-04 13:24:28 -0700877 // keep holding partial wakelock to prevent entering sleep before enterDeepSleep call
878 // enterDeepSleep should force sleep entry even if wake lock is kept.
879 mSystemInterface.switchToPartialWakeLock();
Keun young Parkb241d022020-04-20 20:31:34 -0700880 mHandler.cancelProcessingComplete();
Jim Kayed22f1d62019-12-03 16:08:00 -0800881 synchronized (mLock) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800882 mLastSleepEntryTime = SystemClock.elapsedRealtime();
883 }
Jim Kaye0ffbf522019-07-01 16:10:40 -0700884 int nextListenerState;
Jim Kaye4ae10b42019-04-02 11:42:50 -0700885 if (simulatedMode) {
Jim Kayed22f1d62019-12-03 16:08:00 -0800886 simulateSleepByWaiting();
Jim Kaye0ffbf522019-07-01 16:10:40 -0700887 nextListenerState = CarPowerStateListener.SHUTDOWN_CANCELLED;
Jim Kayed76c2742019-04-02 11:33:27 -0700888 } else {
Jim Kayeee122fc2020-05-29 09:37:05 -0700889 boolean sleepSucceeded = suspendWithRetries();
Jim Kayed76c2742019-04-02 11:33:27 -0700890 if (!sleepSucceeded) {
Jim Kayeee122fc2020-05-29 09:37:05 -0700891 // Suspend failed and we shut down instead.
892 // We either won't get here at all or we will power off very soon.
Jim Kaye32ea4ce2019-12-03 15:00:51 -0800893 return;
Jim Kayed76c2742019-04-02 11:33:27 -0700894 }
Jim Kayeee122fc2020-05-29 09:37:05 -0700895 // We suspended and have now resumed
Jim Kaye0ffbf522019-07-01 16:10:40 -0700896 nextListenerState = CarPowerStateListener.SUSPEND_EXIT;
Steve Paik0f9fc002018-02-09 17:42:00 -0800897 }
Jim Kayed22f1d62019-12-03 16:08:00 -0800898 synchronized (mLock) {
Jim Kayeee122fc2020-05-29 09:37:05 -0700899 // Any wakeup time from before is no longer valid.
Jim Kayed22f1d62019-12-03 16:08:00 -0800900 mNextWakeupSec = 0;
901 }
Eric Jeongd37b78b2021-04-29 00:22:36 -0700902 Slogf.i(TAG, "Resuming after suspending");
Serik Beketayev74debf22018-10-04 12:18:09 -0700903 mSystemInterface.refreshDisplayBrightness();
Jim Kaye0ffbf522019-07-01 16:10:40 -0700904 onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, nextListenerState);
keunyoung4b0212c2015-10-29 17:11:57 -0700905 }
906
Jim Kaye24ddc862020-04-30 14:05:17 -0700907 private boolean needPowerStateChangeLocked(@NonNull CpmsState newState) {
908 if (mCurrentState == null) {
keunyoung4b0212c2015-10-29 17:11:57 -0700909 return true;
Steve Paik07db5ed2018-09-24 16:48:52 -0700910 } else if (mCurrentState.equals(newState)) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700911 Slogf.d(TAG, "Requested state is already in effect: %s", newState.name());
Steve Paik07db5ed2018-09-24 16:48:52 -0700912 return false;
913 }
914
915 // The following switch/case enforces the allowed state transitions.
Jim Kaye24ddc862020-04-30 14:05:17 -0700916 boolean transitionAllowed = false;
Steve Paik07db5ed2018-09-24 16:48:52 -0700917 switch (mCurrentState.mState) {
918 case CpmsState.WAIT_FOR_VHAL:
Jim Kaye24ddc862020-04-30 14:05:17 -0700919 transitionAllowed = (newState.mState == CpmsState.ON)
Steve Paik07db5ed2018-09-24 16:48:52 -0700920 || (newState.mState == CpmsState.SHUTDOWN_PREPARE);
Jim Kaye24ddc862020-04-30 14:05:17 -0700921 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700922 case CpmsState.SUSPEND:
Jim Kaye24ddc862020-04-30 14:05:17 -0700923 transitionAllowed = newState.mState == CpmsState.WAIT_FOR_VHAL;
924 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700925 case CpmsState.ON:
Jim Kaye24ddc862020-04-30 14:05:17 -0700926 transitionAllowed = (newState.mState == CpmsState.SHUTDOWN_PREPARE)
Jim Kayed76c2742019-04-02 11:33:27 -0700927 || (newState.mState == CpmsState.SIMULATE_SLEEP);
Jim Kaye24ddc862020-04-30 14:05:17 -0700928 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700929 case CpmsState.SHUTDOWN_PREPARE:
Jim Kaye49fbfd02019-10-09 09:45:18 -0700930 // If VHAL sends SHUTDOWN_IMMEDIATELY or SLEEP_IMMEDIATELY while in
931 // SHUTDOWN_PREPARE state, do it.
Jim Kaye24ddc862020-04-30 14:05:17 -0700932 transitionAllowed =
933 ((newState.mState == CpmsState.SHUTDOWN_PREPARE) && !newState.mCanPostpone)
934 || (newState.mState == CpmsState.WAIT_FOR_FINISH)
935 || (newState.mState == CpmsState.WAIT_FOR_VHAL);
936 break;
Jim Kayed76c2742019-04-02 11:33:27 -0700937 case CpmsState.SIMULATE_SLEEP:
Jim Kaye24ddc862020-04-30 14:05:17 -0700938 transitionAllowed = true;
939 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700940 case CpmsState.WAIT_FOR_FINISH:
Jim Kaye24ddc862020-04-30 14:05:17 -0700941 transitionAllowed = (newState.mState == CpmsState.SUSPEND
Jim Kaye78a1bce2020-04-16 15:33:45 -0700942 || newState.mState == CpmsState.WAIT_FOR_VHAL);
Jim Kaye24ddc862020-04-30 14:05:17 -0700943 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700944 default:
Eric Jeongd37b78b2021-04-29 00:22:36 -0700945 Slogf.e(TAG, "Unexpected current state: currentState=%s, newState=%s",
946 mCurrentState.name(), newState.name());
Jim Kaye24ddc862020-04-30 14:05:17 -0700947 transitionAllowed = true;
keunyoung4b0212c2015-10-29 17:11:57 -0700948 }
Jim Kaye24ddc862020-04-30 14:05:17 -0700949 if (!transitionAllowed) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700950 Slogf.e(TAG, "Requested power transition is not allowed: %s --> %s",
951 mCurrentState.name(), newState.name());
Jim Kaye24ddc862020-04-30 14:05:17 -0700952 }
953 return transitionAllowed;
keunyoung4b0212c2015-10-29 17:11:57 -0700954 }
955
Steve Paik07db5ed2018-09-24 16:48:52 -0700956 private void doHandleProcessingComplete() {
Jim Kayed22f1d62019-12-03 16:08:00 -0800957 int listenerState;
958 synchronized (mLock) {
keunyoung4b0212c2015-10-29 17:11:57 -0700959 releaseTimerLocked();
Steve Paik07db5ed2018-09-24 16:48:52 -0700960 if (!mShutdownOnFinish && mLastSleepEntryTime > mProcessingStartTime) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800961 // entered sleep after processing start. So this could be duplicate request.
Eric Jeongd37b78b2021-04-29 00:22:36 -0700962 Slogf.w(TAG, "Duplicate sleep entry request, ignore");
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800963 return;
964 }
Jim Kayed22f1d62019-12-03 16:08:00 -0800965 listenerState = mShutdownOnFinish
966 ? CarPowerStateListener.SHUTDOWN_ENTER : CarPowerStateListener.SUSPEND_ENTER;
keunyoung4b0212c2015-10-29 17:11:57 -0700967 }
keunyoung4b0212c2015-10-29 17:11:57 -0700968
Jim Kayed22f1d62019-12-03 16:08:00 -0800969 onApPowerStateChange(CpmsState.WAIT_FOR_FINISH, listenerState);
keunyoung4b0212c2015-10-29 17:11:57 -0700970 }
971
972 @Override
973 public void onDisplayBrightnessChange(int brightness) {
Keun young Parkb241d022020-04-20 20:31:34 -0700974 mHandler.handleDisplayBrightnessChange(brightness);
keunyoung4b0212c2015-10-29 17:11:57 -0700975 }
976
977 private void doHandleDisplayBrightnessChange(int brightness) {
Steve Paik87b36fd2018-03-13 19:25:47 -0700978 mSystemInterface.setDisplayBrightness(brightness);
keunyoung4b0212c2015-10-29 17:11:57 -0700979 }
980
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800981 private void doHandleMainDisplayStateChange(boolean on) {
Eric Jeongd37b78b2021-04-29 00:22:36 -0700982 Slogf.w(TAG, "Unimplemented: doHandleMainDisplayStateChange() - on = %b", on);
keunyoung4b0212c2015-10-29 17:11:57 -0700983 }
984
Eric Jeongbc351e22020-07-31 13:54:17 -0700985 /**
986 * Handles when a main display changes.
987 */
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800988 public void handleMainDisplayChanged(boolean on) {
Keun young Parkb241d022020-04-20 20:31:34 -0700989 mHandler.handleMainDisplayStateChange(on);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800990 }
991
Steve Paik47cdf7b2018-03-16 17:27:43 -0700992 /**
993 * Send display brightness to VHAL.
994 * @param brightness value 0-100%
995 */
996 public void sendDisplayBrightness(int brightness) {
997 mHal.sendDisplayBrightness(brightness);
998 }
999
Jim Kayed22f1d62019-12-03 16:08:00 -08001000 /**
1001 * Get the PowerHandler that we use to change power states
1002 */
1003 public Handler getHandler() {
Keun young Parkb241d022020-04-20 20:31:34 -07001004 return mHandler;
1005
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001006 }
1007
Jim Kayee5133162019-04-22 12:50:27 -07001008 // Binder interface for general use.
1009 // The listener is not required (or allowed) to call finished().
Steve Paik388d7772018-02-12 10:54:51 -08001010 @Override
1011 public void registerListener(ICarPowerStateListener listener) {
1012 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Steve Paik03124082018-02-16 11:19:26 -08001013 mPowerManagerListeners.register(listener);
Jim Kayee5133162019-04-22 12:50:27 -07001014 }
1015
1016 // Binder interface for Car services only.
1017 // After the listener completes its processing, it must call finished().
1018 @Override
1019 public void registerListenerWithCompletion(ICarPowerStateListener listener) {
1020 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Keun young Parkaabecd92019-05-03 17:31:27 -07001021 ICarImpl.assertCallingFromSystemProcessOrSelf();
Jim Kayee5133162019-04-22 12:50:27 -07001022
1023 mPowerManagerListenersWithCompletion.register(listener);
1024 // TODO: Need to send current state to newly registered listener? If so, need to handle
1025 // completion for SHUTDOWN_PREPARE state
Steve Paik388d7772018-02-12 10:54:51 -08001026 }
1027
1028 @Override
1029 public void unregisterListener(ICarPowerStateListener listener) {
1030 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Steve Paik03124082018-02-16 11:19:26 -08001031 doUnregisterListener(listener);
1032 }
1033
Steve Paik388d7772018-02-12 10:54:51 -08001034 @Override
1035 public void requestShutdownOnNextSuspend() {
1036 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Jim Kayed22f1d62019-12-03 16:08:00 -08001037 synchronized (mLock) {
Jim Kayedab62d82019-12-18 14:52:19 -08001038 mShutdownOnNextSuspend = true;
Jim Kayed22f1d62019-12-03 16:08:00 -08001039 }
Steve Paik388d7772018-02-12 10:54:51 -08001040 }
1041
1042 @Override
Jim Kayee5133162019-04-22 12:50:27 -07001043 public void finished(ICarPowerStateListener listener) {
Steve Paik388d7772018-02-12 10:54:51 -08001044 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Keun young Parkaabecd92019-05-03 17:31:27 -07001045 ICarImpl.assertCallingFromSystemProcessOrSelf();
Jim Kayee5133162019-04-22 12:50:27 -07001046 finishedImpl(listener.asBinder());
Steve Paik03124082018-02-16 11:19:26 -08001047 }
1048
Serik Beketayev6e4c7822018-08-27 08:20:09 -07001049 @Override
Jim Kayed22f1d62019-12-03 16:08:00 -08001050 public void scheduleNextWakeupTime(int seconds) {
Jim Kaye1842e822020-05-04 13:08:45 -07001051 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Serik Beketayev6e4c7822018-08-27 08:20:09 -07001052 if (seconds < 0) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001053 Slogf.w(TAG, "Next wake up time is negative. Ignoring!");
Serik Beketayev6e4c7822018-08-27 08:20:09 -07001054 return;
1055 }
Jim Kayed22f1d62019-12-03 16:08:00 -08001056 boolean timedWakeupAllowed = mHal.isTimedWakeupAllowed();
1057 synchronized (mLock) {
1058 if (!timedWakeupAllowed) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001059 Slogf.w(TAG, "Setting timed wakeups are disabled in HAL. Skipping");
Jim Kayed22f1d62019-12-03 16:08:00 -08001060 mNextWakeupSec = 0;
1061 return;
1062 }
1063 if (mNextWakeupSec == 0 || mNextWakeupSec > seconds) {
1064 // The new value is sooner than the old value. Take the new value.
1065 mNextWakeupSec = seconds;
1066 } else {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001067 Slogf.d(TAG, "Tried to schedule next wake up, but already had shorter "
Jim Kayed22f1d62019-12-03 16:08:00 -08001068 + "scheduled time");
1069 }
Serik Beketayev6e4c7822018-08-27 08:20:09 -07001070 }
1071 }
1072
Jim Kaye1842e822020-05-04 13:08:45 -07001073 @Override
1074 public int getPowerState() {
1075 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1076 synchronized (mLock) {
1077 return (mCurrentState == null) ? CarPowerStateListener.INVALID
1078 : mCurrentState.mCarPowerStateListenerState;
1079 }
1080 }
1081
Eric Jeong58762682020-11-30 21:51:32 -08001082 /**
1083 * @see android.car.hardware.power.CarPowerManager#getCurrentPowerPolicy
1084 */
1085 @Override
Eric Jeongb7003812020-12-08 11:37:55 -08001086 public CarPowerPolicy getCurrentPowerPolicy() {
1087 ICarImpl.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
Eric Jeong8f0d3c42021-03-16 20:12:24 -07001088 return mPowerComponentHandler.getAccumulatedPolicy();
Eric Jeong58762682020-11-30 21:51:32 -08001089 }
1090
1091 /**
1092 * @see android.car.hardware.power.CarPowerManager#applyPowerPolicy
1093 */
1094 @Override
1095 public void applyPowerPolicy(String policyId) {
Eric Jeongb7003812020-12-08 11:37:55 -08001096 ICarImpl.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_POWER_POLICY);
Eric Jeong4b69cf72021-01-07 21:23:16 -08001097 Preconditions.checkArgument(policyId != null, "policyId cannot be null");
Eric Jeong078ada02021-01-20 18:11:17 -08001098 Preconditions.checkArgument(!policyId.startsWith(PolicyReader.SYSTEM_POWER_POLICY_PREFIX),
1099 "System power policy cannot be applied by apps");
Eric Jeong83225c72021-05-13 13:22:45 -07001100 int status = applyPowerPolicy(policyId, true);
1101 if (status != PolicyOperationStatus.OK) {
1102 throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status));
Eric Jeong58762682020-11-30 21:51:32 -08001103 }
1104 }
1105
1106 /**
Eric Jeongd48f7072021-02-25 18:21:06 -08001107 * @see android.car.hardware.power.CarPowerManager#setPowerPolicyGroup
Eric Jeong58762682020-11-30 21:51:32 -08001108 */
1109 @Override
Eric Jeongd48f7072021-02-25 18:21:06 -08001110 public void setPowerPolicyGroup(String policyGroupId) {
1111 ICarImpl.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_POWER_POLICY);
1112 Preconditions.checkArgument(policyGroupId != null, "policyGroupId cannot be null");
Eric Jeong83225c72021-05-13 13:22:45 -07001113 int status = setCurrentPowerPolicyGroup(policyGroupId);
1114 if (status != PolicyOperationStatus.OK) {
1115 throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status));
Eric Jeongd48f7072021-02-25 18:21:06 -08001116 }
Eric Jeong58762682020-11-30 21:51:32 -08001117 }
1118
1119 /**
Eric Jeongd48f7072021-02-25 18:21:06 -08001120 * @see android.car.hardware.power.CarPowerManager#addPowerPolicyListener
Eric Jeong58762682020-11-30 21:51:32 -08001121 */
1122 @Override
Eric Jeongd48f7072021-02-25 18:21:06 -08001123 public void addPowerPolicyListener(CarPowerPolicyFilter filter,
1124 ICarPowerPolicyListener listener) {
Eric Jeongb7003812020-12-08 11:37:55 -08001125 ICarImpl.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
Eric Jeongd48f7072021-02-25 18:21:06 -08001126 mPowerPolicyListeners.register(listener, filter);
1127 }
1128
1129 /**
1130 * @see android.car.hardware.power.CarPowerManager#removePowerPolicyListener
1131 */
1132 @Override
1133 public void removePowerPolicyListener(ICarPowerPolicyListener listener) {
1134 ICarImpl.assertPermission(mContext, Car.PERMISSION_READ_CAR_POWER_POLICY);
1135 mPowerPolicyListeners.unregister(listener);
Eric Jeong58762682020-11-30 21:51:32 -08001136 }
1137
Eric Jeong4b69cf72021-01-07 21:23:16 -08001138 void notifySilentModeChange(boolean silent) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001139 Slogf.i(TAG, "Silent mode is set to %b", silent);
Eric Jeong4b69cf72021-01-07 21:23:16 -08001140 mSilentModeHandler.updateKernelSilentMode(silent);
Eric Jeong36f61d42021-02-19 22:10:45 -08001141 if (silent) {
1142 applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION);
1143 } else {
1144 cancelPreemptivePowerPolicy();
Eric Jeong4b69cf72021-01-07 21:23:16 -08001145 }
1146 }
1147
Eric Jeong58762682020-11-30 21:51:32 -08001148 private void doUnregisterListener(ICarPowerStateListener listener) {
1149 mPowerManagerListeners.unregister(listener);
1150 boolean found = mPowerManagerListenersWithCompletion.unregister(listener);
1151 if (found) {
1152 // Remove this from the completion list (if it's there)
1153 finishedImpl(listener.asBinder());
1154 }
1155 }
1156
Jim Kayee5133162019-04-22 12:50:27 -07001157 private void finishedImpl(IBinder binder) {
Jim Kaye9889f282020-05-28 09:17:17 -07001158 boolean allAreComplete;
Jim Kayed22f1d62019-12-03 16:08:00 -08001159 synchronized (mLock) {
Jim Kaye9889f282020-05-28 09:17:17 -07001160 mListenersWeAreWaitingFor.remove(binder);
1161 allAreComplete = mListenersWeAreWaitingFor.isEmpty();
Jim Kayee5133162019-04-22 12:50:27 -07001162 }
1163 if (allAreComplete) {
1164 signalComplete();
1165 }
1166 }
1167
1168 private void signalComplete() {
1169 if (mCurrentState.mState == CpmsState.SHUTDOWN_PREPARE
1170 || mCurrentState.mState == CpmsState.SIMULATE_SLEEP) {
1171 PowerHandler powerHandler;
1172 // All apps are ready to shutdown/suspend.
Jim Kayed22f1d62019-12-03 16:08:00 -08001173 synchronized (mLock) {
Jim Kayee5133162019-04-22 12:50:27 -07001174 if (!mShutdownOnFinish) {
1175 if (mLastSleepEntryTime > mProcessingStartTime
1176 && mLastSleepEntryTime < SystemClock.elapsedRealtime()) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001177 Slogf.i(TAG, "signalComplete: Already slept!");
Jim Kayee5133162019-04-22 12:50:27 -07001178 return;
Steve Paik07db5ed2018-09-24 16:48:52 -07001179 }
Steve Paik07db5ed2018-09-24 16:48:52 -07001180 }
Jim Kayee5133162019-04-22 12:50:27 -07001181 powerHandler = mHandler;
Steve Paik03124082018-02-16 11:19:26 -08001182 }
Eric Jeongd37b78b2021-04-29 00:22:36 -07001183 Slogf.i(TAG, "Apps are finished, call handleProcessingComplete()");
Jim Kayee5133162019-04-22 12:50:27 -07001184 powerHandler.handleProcessingComplete();
Steve Paik03124082018-02-16 11:19:26 -08001185 }
Steve Paik388d7772018-02-12 10:54:51 -08001186 }
1187
Eric Jeong20a13b52020-10-02 23:50:40 -07001188 private void initializePowerPolicy() {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001189 Slogf.i(TAG, "CPMS is taking control from carpowerpolicyd");
Eric Jeong03e0cc32020-10-28 18:21:20 -07001190 ICarPowerPolicySystemNotification daemon;
1191 synchronized (mLock) {
1192 daemon = mCarPowerPolicyDaemon;
1193 }
Eric Jeong79930092021-04-26 23:55:59 -07001194 PolicyState state;
Eric Jeong1ed55602021-02-24 11:21:14 -08001195 if (daemon != null) {
Eric Jeong1ed55602021-02-24 11:21:14 -08001196 try {
1197 state = daemon.notifyCarServiceReady();
Eric Jeong1ed55602021-02-24 11:21:14 -08001198 } catch (RemoteException e) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001199 Slogf.e(TAG, e, "Failed to tell car power policy daemon that CarService is ready");
Eric Jeong1ed55602021-02-24 11:21:14 -08001200 return;
1201 }
Eric Jeong1ed55602021-02-24 11:21:14 -08001202 } else {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001203 Slogf.w(TAG, "Failed to notify car service is ready. car power policy daemon is not "
Eric Jeong1ed55602021-02-24 11:21:14 -08001204 + "available");
Eric Jeong79930092021-04-26 23:55:59 -07001205 return;
1206 }
1207
1208 String currentPowerPolicyId;
1209 String currentPolicyGroupId;
1210 synchronized (mLock) {
1211 mHasControlOverDaemon = true;
1212 currentPowerPolicyId = mCurrentPowerPolicyId;
1213 currentPolicyGroupId = mCurrentPowerPolicyGroupId;
1214 }
Eric Jeong79930092021-04-26 23:55:59 -07001215 // If the current power policy or the policy group has been modified by CPMS, we ignore
Eric Jeong7edd8b22021-05-05 16:35:33 -07001216 // the power policy or the policy group passed from car power policy daemon, and notifies
1217 // the current power policy to the daemon.
Eric Jeong79930092021-04-26 23:55:59 -07001218 if (currentPowerPolicyId == null || currentPowerPolicyId.isEmpty()) {
Eric Jeong83225c72021-05-13 13:22:45 -07001219 int status = applyPowerPolicy(state.policyId, false);
1220 if (status != PolicyOperationStatus.OK) {
1221 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
Eric Jeong79930092021-04-26 23:55:59 -07001222 }
Eric Jeong7edd8b22021-05-05 16:35:33 -07001223 } else {
1224 notifyPowerPolicyChangeToDaemon(currentPowerPolicyId);
Eric Jeong79930092021-04-26 23:55:59 -07001225 }
1226 if (currentPolicyGroupId == null || currentPolicyGroupId.isEmpty()) {
Eric Jeong83225c72021-05-13 13:22:45 -07001227 int status = setCurrentPowerPolicyGroup(state.policyGroupId);
1228 if (status != PolicyOperationStatus.OK) {
1229 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
Eric Jeong79930092021-04-26 23:55:59 -07001230 }
Eric Jeonga2934632020-11-08 23:14:30 -08001231 }
Eric Jeong4b69cf72021-01-07 21:23:16 -08001232 mSilentModeHandler.init();
Eric Jeong03e0cc32020-10-28 18:21:20 -07001233 }
1234
Eric Jeong83225c72021-05-13 13:22:45 -07001235 @PolicyOperationStatus.ErrorCode
1236 private int setCurrentPowerPolicyGroup(String policyGroupId) {
Eric Jeong03e0cc32020-10-28 18:21:20 -07001237 if (!mPolicyReader.isPowerPolicyGroupAvailable(policyGroupId)) {
Eric Jeong83225c72021-05-13 13:22:45 -07001238 int error = PolicyOperationStatus.ERROR_SET_POWER_POLICY_GROUP;
1239 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error,
1240 policyGroupId + " is not registered"));
1241 return error;
Eric Jeong03e0cc32020-10-28 18:21:20 -07001242 }
1243 synchronized (mLock) {
Eric Jeong36f61d42021-02-19 22:10:45 -08001244 mCurrentPowerPolicyGroupId = policyGroupId;
Eric Jeong03e0cc32020-10-28 18:21:20 -07001245 }
Eric Jeong83225c72021-05-13 13:22:45 -07001246 return PolicyOperationStatus.OK;
Eric Jeong03e0cc32020-10-28 18:21:20 -07001247 }
1248
Eric Jeong83225c72021-05-13 13:22:45 -07001249 @PolicyOperationStatus.ErrorCode
1250 private int applyPowerPolicy(@Nullable String policyId, boolean upToDaemon) {
Eric Jeong36f61d42021-02-19 22:10:45 -08001251 CarPowerPolicy policy = mPolicyReader.getPowerPolicy(policyId);
Eric Jeong03e0cc32020-10-28 18:21:20 -07001252 if (policy == null) {
Eric Jeong83225c72021-05-13 13:22:45 -07001253 int error = PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
1254 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId));
1255 return error;
Eric Jeong03e0cc32020-10-28 18:21:20 -07001256 }
Eric Jeong4b69cf72021-01-07 21:23:16 -08001257 synchronized (mLock) {
1258 if (mIsPowerPolicyLocked) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001259 Slogf.i(TAG, "Power policy is locked. The request policy(%s) will be applied when "
1260 + "power policy becomes unlocked", policyId);
Eric Jeong36f61d42021-02-19 22:10:45 -08001261 mPendingPowerPolicyId = policyId;
Eric Jeong83225c72021-05-13 13:22:45 -07001262 return PolicyOperationStatus.OK;
Eric Jeong4b69cf72021-01-07 21:23:16 -08001263 }
Eric Jeong36f61d42021-02-19 22:10:45 -08001264 mCurrentPowerPolicyId = policyId;
Eric Jeong4b69cf72021-01-07 21:23:16 -08001265 }
Eric Jeong03e0cc32020-10-28 18:21:20 -07001266 mPowerComponentHandler.applyPowerPolicy(policy);
Eric Jeong4d8b4872020-11-09 13:12:30 -08001267 notifyPowerPolicyChange(policyId, upToDaemon);
Eric Jeongd37b78b2021-04-29 00:22:36 -07001268 Slogf.i(TAG, "The current power policy is %s", policyId);
Eric Jeong83225c72021-05-13 13:22:45 -07001269 return PolicyOperationStatus.OK;
Eric Jeong20a13b52020-10-02 23:50:40 -07001270 }
1271
Eric Jeong83225c72021-05-13 13:22:45 -07001272 @PolicyOperationStatus.ErrorCode
1273 private int applyPreemptivePowerPolicy(String policyId) {
Eric Jeong36f61d42021-02-19 22:10:45 -08001274 CarPowerPolicy policy = mPolicyReader.getPreemptivePowerPolicy(policyId);
1275 if (policy == null) {
Eric Jeong83225c72021-05-13 13:22:45 -07001276 int error = PolicyOperationStatus.ERROR_NOT_REGISTERED_POWER_POLICY_ID;
1277 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error, policyId));
1278 return error;
Eric Jeong36f61d42021-02-19 22:10:45 -08001279 }
1280 synchronized (mLock) {
1281 mIsPowerPolicyLocked = true;
1282 if (!mPolicyReader.isPreemptivePowerPolicy(mCurrentPowerPolicyId)) {
1283 mPendingPowerPolicyId = mCurrentPowerPolicyId;
1284 }
1285 mCurrentPowerPolicyId = policyId;
1286 }
1287 mPowerComponentHandler.applyPowerPolicy(policy);
1288 notifyPowerPolicyChange(policyId, true);
Eric Jeongd37b78b2021-04-29 00:22:36 -07001289 Slogf.i(TAG, "The current power policy is %s", policyId);
Eric Jeong83225c72021-05-13 13:22:45 -07001290 return PolicyOperationStatus.OK;
Eric Jeong36f61d42021-02-19 22:10:45 -08001291 }
1292
1293 private void cancelPreemptivePowerPolicy() {
1294 String policyId;
1295 synchronized (mLock) {
1296 if (!mIsPowerPolicyLocked) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001297 Slogf.w(TAG, "Failed to cancel system power policy: the current policy is not the "
Eric Jeong36f61d42021-02-19 22:10:45 -08001298 + "system power policy");
1299 return;
1300 }
1301 mIsPowerPolicyLocked = false;
1302 policyId = mPendingPowerPolicyId;
Eric Jeong83225c72021-05-13 13:22:45 -07001303 mPendingPowerPolicyId = null;
Eric Jeong36f61d42021-02-19 22:10:45 -08001304 }
Eric Jeong83225c72021-05-13 13:22:45 -07001305 int status = applyPowerPolicy(policyId, true);
1306 if (status != PolicyOperationStatus.OK) {
1307 Slogf.w(TAG, "Failed to cancel system power policy: %s",
1308 PolicyOperationStatus.errorCodeToString(status));
Eric Jeong36f61d42021-02-19 22:10:45 -08001309 }
1310 }
1311
1312 private void notifyPowerPolicyChangeToDaemon(String policyId) {
1313 ICarPowerPolicySystemNotification daemon;
Eric Jeong79930092021-04-26 23:55:59 -07001314 boolean hadPendingPolicyNotification;
Eric Jeong36f61d42021-02-19 22:10:45 -08001315 synchronized (mLock) {
1316 daemon = mCarPowerPolicyDaemon;
Eric Jeong79930092021-04-26 23:55:59 -07001317 if (daemon == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001318 Slogf.e(TAG, "Failed to notify car power policy daemon: the daemon is not ready");
Eric Jeong79930092021-04-26 23:55:59 -07001319 return;
1320 }
1321 if (!mHasControlOverDaemon) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001322 Slogf.w(TAG, "Notifying policy change is deferred: CPMS has not yet taken control");
Eric Jeong79930092021-04-26 23:55:59 -07001323 return;
1324 }
Eric Jeong36f61d42021-02-19 22:10:45 -08001325 }
1326 try {
1327 daemon.notifyPowerPolicyChange(policyId);
Eric Jeong79930092021-04-26 23:55:59 -07001328 } catch (RemoteException | IllegalStateException e) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001329 Slogf.e(TAG, e, "Failed to notify car power policy daemon of a new power policy(%s)",
1330 policyId);
Eric Jeong36f61d42021-02-19 22:10:45 -08001331 }
1332 }
1333
Eric Jeong4d8b4872020-11-09 13:12:30 -08001334 private void notifyPowerPolicyChange(String policyId, boolean upToDaemon) {
Eric Jeong58762682020-11-30 21:51:32 -08001335 // Notify system clients
Eric Jeong4d8b4872020-11-09 13:12:30 -08001336 if (upToDaemon) {
Eric Jeong36f61d42021-02-19 22:10:45 -08001337 notifyPowerPolicyChangeToDaemon(policyId);
Eric Jeong4d8b4872020-11-09 13:12:30 -08001338 }
Eric Jeong58762682020-11-30 21:51:32 -08001339
1340 // Notify Java clients
Eric Jeong8f0d3c42021-03-16 20:12:24 -07001341 CarPowerPolicy accumulatedPolicy = mPowerComponentHandler.getAccumulatedPolicy();
1342 CarPowerPolicy appliedPolicy = mPolicyReader.isPreemptivePowerPolicy(policyId)
Eric Jeong36f61d42021-02-19 22:10:45 -08001343 ? mPolicyReader.getPreemptivePowerPolicy(policyId)
1344 : mPolicyReader.getPowerPolicy(policyId);
Eric Jeong8f0d3c42021-03-16 20:12:24 -07001345 if (appliedPolicy == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001346 Slogf.wtf(TAG, "The new power policy(%s) should exist", policyId);
Eric Jeong58762682020-11-30 21:51:32 -08001347 }
Eric Jeongd48f7072021-02-25 18:21:06 -08001348 int idx = mPowerPolicyListeners.beginBroadcast();
Eric Jeong58762682020-11-30 21:51:32 -08001349 while (idx-- > 0) {
Eric Jeongd48f7072021-02-25 18:21:06 -08001350 ICarPowerPolicyListener listener = mPowerPolicyListeners.getBroadcastItem(idx);
Eric Jeong58762682020-11-30 21:51:32 -08001351 CarPowerPolicyFilter filter =
Eric Jeongd48f7072021-02-25 18:21:06 -08001352 (CarPowerPolicyFilter) mPowerPolicyListeners.getBroadcastCookie(idx);
Eric Jeong1e5aeb42021-04-05 00:14:19 -07001353 if (!mPowerComponentHandler.isComponentChanged(filter)) {
Eric Jeong58762682020-11-30 21:51:32 -08001354 continue;
1355 }
1356 try {
Eric Jeong8f0d3c42021-03-16 20:12:24 -07001357 listener.onPolicyChanged(appliedPolicy, accumulatedPolicy);
Eric Jeong58762682020-11-30 21:51:32 -08001358 } catch (RemoteException e) {
1359 // It's likely the connection snapped. Let binder death handle the situation.
Eric Jeongd37b78b2021-04-29 00:22:36 -07001360 Slogf.e(TAG, e, "onPolicyChanged() call failed: policyId = %s", policyId);
Eric Jeong58762682020-11-30 21:51:32 -08001361 }
1362 }
Eric Jeongd48f7072021-02-25 18:21:06 -08001363 mPowerPolicyListeners.finishBroadcast();
Eric Jeong58762682020-11-30 21:51:32 -08001364 }
1365
Eric Jeong4b69cf72021-01-07 21:23:16 -08001366 private void makeSureNoUserInteraction() {
Eric Jeong4b69cf72021-01-07 21:23:16 -08001367 mSilentModeHandler.updateKernelSilentMode(true);
Eric Jeong83225c72021-05-13 13:22:45 -07001368 int status = applyPreemptivePowerPolicy(PolicyReader.POWER_POLICY_ID_NO_USER_INTERACTION);
1369 if (status != PolicyOperationStatus.OK) {
1370 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
Eric Jeong36f61d42021-02-19 22:10:45 -08001371 }
Eric Jeong4b69cf72021-01-07 21:23:16 -08001372 }
1373
Eric Jeong20a13b52020-10-02 23:50:40 -07001374 private void connectToPowerPolicyDaemon() {
1375 synchronized (mLock) {
1376 if (mCarPowerPolicyDaemon != null || mConnectionInProgress) {
1377 return;
1378 }
1379 mConnectionInProgress = true;
1380 }
1381 connectToDaemonHelper(CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY);
1382 }
1383
1384 private void connectToDaemonHelper(int retryCount) {
1385 if (retryCount <= 0) {
1386 synchronized (mLock) {
1387 mConnectionInProgress = false;
1388 }
Eric Jeongd37b78b2021-04-29 00:22:36 -07001389 Slogf.e(TAG, "Cannot reconnect to car power policyd daemon after retrying %d times",
1390 CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY);
Eric Jeong20a13b52020-10-02 23:50:40 -07001391 return;
1392 }
1393 if (makeBinderConnection()) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001394 Slogf.i(TAG, "Connected to car power policy daemon");
Eric Jeong20a13b52020-10-02 23:50:40 -07001395 initializePowerPolicy();
1396 return;
1397 }
1398 mHandler.sendMessageDelayed(PooledLambda.obtainMessage(
1399 CarPowerManagementService::connectToDaemonHelper,
1400 CarPowerManagementService.this, retryCount - 1),
1401 CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS);
1402 }
1403
1404 private boolean makeBinderConnection() {
1405 long currentTimeMs = SystemClock.uptimeMillis();
1406 IBinder binder = ServiceManager.getService(CAR_POWER_POLICY_DAEMON_INTERFACE);
1407 if (binder == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001408 Slogf.w(TAG, "Finding car power policy daemon failed. Power policy management is not "
Eric Jeong20a13b52020-10-02 23:50:40 -07001409 + "supported");
1410 return false;
1411 }
1412 long elapsedTimeMs = SystemClock.uptimeMillis() - currentTimeMs;
1413 if (elapsedTimeMs > CAR_POWER_POLICY_DAEMON_FIND_MARGINAL_TIME_MS) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001414 Slogf.wtf(TAG, "Finding car power policy daemon took too long(%dms)", elapsedTimeMs);
Eric Jeong20a13b52020-10-02 23:50:40 -07001415 }
1416
1417 ICarPowerPolicySystemNotification daemon =
1418 ICarPowerPolicySystemNotification.Stub.asInterface(binder);
1419 if (daemon == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001420 Slogf.w(TAG, "Getting car power policy daemon interface failed. Power policy management"
1421 + " is not supported");
Eric Jeong20a13b52020-10-02 23:50:40 -07001422 return false;
1423 }
1424 synchronized (mLock) {
1425 mCarPowerPolicyDaemon = daemon;
1426 mConnectionInProgress = false;
1427 }
1428 mBinderHandler = new BinderHandler(daemon);
1429 mBinderHandler.linkToDeath();
1430 return true;
1431 }
1432
1433 private final class BinderHandler implements IBinder.DeathRecipient {
1434 private ICarPowerPolicySystemNotification mDaemon;
1435
1436 private BinderHandler(ICarPowerPolicySystemNotification daemon) {
1437 mDaemon = daemon;
1438 }
1439
1440 @Override
1441 public void binderDied() {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001442 Slogf.w(TAG, "Car power policy daemon died: reconnecting");
Eric Jeong20a13b52020-10-02 23:50:40 -07001443 unlinkToDeath();
1444 mDaemon = null;
1445 synchronized (mLock) {
1446 mCarPowerPolicyDaemon = null;
Eric Jeong79930092021-04-26 23:55:59 -07001447 mHasControlOverDaemon = false;
Eric Jeong20a13b52020-10-02 23:50:40 -07001448 }
1449 mHandler.sendMessageDelayed(PooledLambda.obtainMessage(
1450 CarPowerManagementService::connectToDaemonHelper,
1451 CarPowerManagementService.this, CAR_POWER_POLICY_DAEMON_BIND_MAX_RETRY),
1452 CAR_POWER_POLICY_DAEMON_BIND_RETRY_INTERVAL_MS);
1453 }
1454
1455 private void linkToDeath() {
1456 if (mDaemon == null) {
1457 return;
1458 }
1459 IBinder binder = mDaemon.asBinder();
1460 if (binder == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001461 Slogf.w(TAG, "Linking to binder death recipient skipped");
Eric Jeong20a13b52020-10-02 23:50:40 -07001462 return;
1463 }
1464 try {
1465 binder.linkToDeath(this, 0);
1466 } catch (RemoteException e) {
1467 mDaemon = null;
Eric Jeongd37b78b2021-04-29 00:22:36 -07001468 Slogf.w(TAG, e, "Linking to binder death recipient failed: %s");
Eric Jeong20a13b52020-10-02 23:50:40 -07001469 }
1470 }
1471
1472 private void unlinkToDeath() {
1473 if (mDaemon == null) {
1474 return;
1475 }
1476 IBinder binder = mDaemon.asBinder();
1477 if (binder == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001478 Slogf.w(TAG, "Unlinking from binder death recipient skipped");
Eric Jeong20a13b52020-10-02 23:50:40 -07001479 return;
1480 }
1481 binder.unlinkToDeath(this, 0);
1482 }
1483 }
1484
Keun young Parkb241d022020-04-20 20:31:34 -07001485 private static final class PowerHandler extends Handler {
1486 private static final String TAG = PowerHandler.class.getSimpleName();
Eric Jeongbc351e22020-07-31 13:54:17 -07001487 private static final int MSG_POWER_STATE_CHANGE = 0;
1488 private static final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1;
1489 private static final int MSG_MAIN_DISPLAY_STATE_CHANGE = 2;
1490 private static final int MSG_PROCESSING_COMPLETE = 3;
keunyoung4b0212c2015-10-29 17:11:57 -07001491
1492 // Do not handle this immediately but with some delay as there can be a race between
1493 // display off due to rear view camera and delivery to here.
Eric Jeongbc351e22020-07-31 13:54:17 -07001494 private static final long MAIN_DISPLAY_EVENT_DELAY_MS = 500;
keunyoung4b0212c2015-10-29 17:11:57 -07001495
Keun young Parkb241d022020-04-20 20:31:34 -07001496 private final WeakReference<CarPowerManagementService> mService;
1497
1498 private PowerHandler(Looper looper, CarPowerManagementService service) {
keunyoung4b0212c2015-10-29 17:11:57 -07001499 super(looper);
Keun young Parkb241d022020-04-20 20:31:34 -07001500 mService = new WeakReference<CarPowerManagementService>(service);
keunyoung4b0212c2015-10-29 17:11:57 -07001501 }
1502
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001503 private void handlePowerStateChange() {
1504 Message msg = obtainMessage(MSG_POWER_STATE_CHANGE);
keunyoung4b0212c2015-10-29 17:11:57 -07001505 sendMessage(msg);
1506 }
1507
1508 private void handleDisplayBrightnessChange(int brightness) {
1509 Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, brightness, 0);
1510 sendMessage(msg);
1511 }
1512
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001513 private void handleMainDisplayStateChange(boolean on) {
keunyoung4b0212c2015-10-29 17:11:57 -07001514 removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001515 Message msg = obtainMessage(MSG_MAIN_DISPLAY_STATE_CHANGE, Boolean.valueOf(on));
keunyoung4b0212c2015-10-29 17:11:57 -07001516 sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS);
1517 }
1518
Steve Paik07db5ed2018-09-24 16:48:52 -07001519 private void handleProcessingComplete() {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001520 removeMessages(MSG_PROCESSING_COMPLETE);
Steve Paik07db5ed2018-09-24 16:48:52 -07001521 Message msg = obtainMessage(MSG_PROCESSING_COMPLETE);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001522 sendMessage(msg);
1523 }
1524
1525 private void cancelProcessingComplete() {
1526 removeMessages(MSG_PROCESSING_COMPLETE);
1527 }
1528
keunyoung4b0212c2015-10-29 17:11:57 -07001529 private void cancelAll() {
1530 removeMessages(MSG_POWER_STATE_CHANGE);
1531 removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE);
1532 removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
1533 removeMessages(MSG_PROCESSING_COMPLETE);
1534 }
1535
1536 @Override
1537 public void handleMessage(Message msg) {
Keun young Parkb241d022020-04-20 20:31:34 -07001538 CarPowerManagementService service = mService.get();
1539 if (service == null) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001540 Slogf.i(TAG, "handleMessage null service");
Keun young Parkb241d022020-04-20 20:31:34 -07001541 return;
1542 }
keunyoung4b0212c2015-10-29 17:11:57 -07001543 switch (msg.what) {
1544 case MSG_POWER_STATE_CHANGE:
Keun young Parkb241d022020-04-20 20:31:34 -07001545 service.doHandlePowerStateChange();
keunyoung4b0212c2015-10-29 17:11:57 -07001546 break;
1547 case MSG_DISPLAY_BRIGHTNESS_CHANGE:
Keun young Parkb241d022020-04-20 20:31:34 -07001548 service.doHandleDisplayBrightnessChange(msg.arg1);
keunyoung4b0212c2015-10-29 17:11:57 -07001549 break;
1550 case MSG_MAIN_DISPLAY_STATE_CHANGE:
Keun young Parkb241d022020-04-20 20:31:34 -07001551 service.doHandleMainDisplayStateChange((Boolean) msg.obj);
Keun-young Park1f4d6a72016-02-11 09:49:47 -08001552 break;
keunyoung4b0212c2015-10-29 17:11:57 -07001553 case MSG_PROCESSING_COMPLETE:
Keun young Parkb241d022020-04-20 20:31:34 -07001554 service.doHandleProcessingComplete();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001555 break;
keunyoung4b0212c2015-10-29 17:11:57 -07001556 }
1557 }
1558 }
1559
keunyoung4b0212c2015-10-29 17:11:57 -07001560 private class ShutdownProcessingTimerTask extends TimerTask {
keunyoung4b0212c2015-10-29 17:11:57 -07001561 private final int mExpirationCount;
1562 private int mCurrentCount;
1563
Steve Paik07db5ed2018-09-24 16:48:52 -07001564 private ShutdownProcessingTimerTask(int expirationCount) {
keunyoung4b0212c2015-10-29 17:11:57 -07001565 mExpirationCount = expirationCount;
1566 mCurrentCount = 0;
1567 }
1568
1569 @Override
1570 public void run() {
Jim Kayed22f1d62019-12-03 16:08:00 -08001571 synchronized (mLock) {
Serik Beketayevf8287a02019-02-08 12:31:10 -08001572 if (!mTimerActive) {
1573 // Ignore timer expiration since we got cancelled
1574 return;
1575 }
1576 mCurrentCount++;
1577 if (mCurrentCount > mExpirationCount) {
1578 PowerHandler handler;
keunyoung4b0212c2015-10-29 17:11:57 -07001579 releaseTimerLocked();
Pavel Maltsevddbff982017-03-22 14:49:02 -07001580 handler = mHandler;
Serik Beketayevf8287a02019-02-08 12:31:10 -08001581 handler.handleProcessingComplete();
1582 } else {
1583 mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS);
keunyoung4b0212c2015-10-29 17:11:57 -07001584 }
keunyoung4b0212c2015-10-29 17:11:57 -07001585 }
1586 }
1587 }
Steve Paik07db5ed2018-09-24 16:48:52 -07001588
Jim Kayeee122fc2020-05-29 09:37:05 -07001589 // Send the command to enter Suspend to RAM.
Jim Kayebe23e542020-08-11 12:07:11 -07001590 // If the command is not successful, try again with an exponential back-off.
Jim Kayeee122fc2020-05-29 09:37:05 -07001591 // If it fails repeatedly, send the command to shut down.
Jim Kayebe23e542020-08-11 12:07:11 -07001592 // If we decide to go to a different power state, abort this retry mechanism.
Jim Kayeee122fc2020-05-29 09:37:05 -07001593 // Returns true if we successfully suspended.
1594 private boolean suspendWithRetries() {
Jim Kayebe23e542020-08-11 12:07:11 -07001595 long retryIntervalMs = INITIAL_SUSPEND_RETRY_INTERVAL_MS;
Eric Jeongdecc4252020-11-19 22:05:41 -08001596 long totalWaitDurationMs = 0;
Jim Kayeee122fc2020-05-29 09:37:05 -07001597
1598 while (true) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001599 Slogf.i(TAG, "Entering Suspend to RAM");
Jim Kayeee122fc2020-05-29 09:37:05 -07001600 boolean suspendSucceeded = mSystemInterface.enterDeepSleep();
1601 if (suspendSucceeded) {
1602 return true;
1603 }
Eric Jeongdecc4252020-11-19 22:05:41 -08001604 if (totalWaitDurationMs >= mMaxSuspendWaitDurationMs) {
Jim Kayeee122fc2020-05-29 09:37:05 -07001605 break;
1606 }
1607 // We failed to suspend. Block the thread briefly and try again.
Jim Kayea94bb8b2020-07-28 09:42:35 -07001608 synchronized (mLock) {
1609 if (mPendingPowerStates.isEmpty()) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001610 Slogf.w(TAG, "Failed to Suspend; will retry after %dms", retryIntervalMs);
Jim Kayea94bb8b2020-07-28 09:42:35 -07001611 try {
1612 mLock.wait(retryIntervalMs);
Jim Kayebe23e542020-08-11 12:07:11 -07001613 } catch (InterruptedException ignored) {
1614 Thread.currentThread().interrupt();
1615 }
Eric Jeongdecc4252020-11-19 22:05:41 -08001616 totalWaitDurationMs += retryIntervalMs;
1617 retryIntervalMs = Math.min(retryIntervalMs * 2, MAX_RETRY_INTERVAL_MS);
Jim Kayea94bb8b2020-07-28 09:42:35 -07001618 }
1619 // Check for a new power state now, before going around the loop again
1620 if (!mPendingPowerStates.isEmpty()) {
Eric Jeongd37b78b2021-04-29 00:22:36 -07001621 Slogf.i(TAG, "Terminating the attempt to Suspend to RAM");
Jim Kayea94bb8b2020-07-28 09:42:35 -07001622 return false;
1623 }
1624 }
Jim Kayeee122fc2020-05-29 09:37:05 -07001625 }
1626 // Too many failures trying to suspend. Shut down.
Eric Jeongd37b78b2021-04-29 00:22:36 -07001627 Slogf.w(TAG, "Could not Suspend to RAM after %dms long trial. Shutting down.",
1628 totalWaitDurationMs);
Jim Kayeee122fc2020-05-29 09:37:05 -07001629 mSystemInterface.shutdown();
1630 return false;
1631 }
1632
Steve Paik07db5ed2018-09-24 16:48:52 -07001633 private static class CpmsState {
Yuncheol Heoe6e03472019-05-08 18:24:45 -07001634 // NOTE: When modifying states below, make sure to update CarPowerStateChanged.State in
Jeffrey Huangb8ecf012020-12-04 12:02:30 -08001635 // frameworks/proto_logging/stats/atoms.proto also.
Steve Paik07db5ed2018-09-24 16:48:52 -07001636 public static final int WAIT_FOR_VHAL = 0;
1637 public static final int ON = 1;
1638 public static final int SHUTDOWN_PREPARE = 2;
1639 public static final int WAIT_FOR_FINISH = 3;
1640 public static final int SUSPEND = 4;
Jim Kayed76c2742019-04-02 11:33:27 -07001641 public static final int SIMULATE_SLEEP = 5;
Steve Paik07db5ed2018-09-24 16:48:52 -07001642
1643 /* Config values from AP_POWER_STATE_REQ */
1644 public final boolean mCanPostpone;
1645 public final boolean mCanSleep;
1646 /* Message sent to CarPowerStateListener in response to this state */
1647 public final int mCarPowerStateListenerState;
1648 /* One of the above state variables */
1649 public final int mState;
1650
1651 /**
1652 * This constructor takes a PowerHalService.PowerState object and creates the corresponding
1653 * CPMS state from it.
1654 */
1655 CpmsState(PowerState halPowerState) {
1656 switch (halPowerState.mState) {
1657 case VehicleApPowerStateReq.ON:
1658 this.mCanPostpone = false;
1659 this.mCanSleep = false;
1660 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(ON);
1661 this.mState = ON;
1662 break;
1663 case VehicleApPowerStateReq.SHUTDOWN_PREPARE:
1664 this.mCanPostpone = halPowerState.canPostponeShutdown();
1665 this.mCanSleep = halPowerState.canEnterDeepSleep();
1666 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(
1667 SHUTDOWN_PREPARE);
1668 this.mState = SHUTDOWN_PREPARE;
1669 break;
1670 case VehicleApPowerStateReq.CANCEL_SHUTDOWN:
1671 this.mCanPostpone = false;
1672 this.mCanSleep = false;
1673 this.mCarPowerStateListenerState = CarPowerStateListener.SHUTDOWN_CANCELLED;
1674 this.mState = WAIT_FOR_VHAL;
1675 break;
1676 case VehicleApPowerStateReq.FINISHED:
1677 this.mCanPostpone = false;
1678 this.mCanSleep = false;
1679 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(SUSPEND);
1680 this.mState = SUSPEND;
1681 break;
1682 default:
1683 // Illegal state from PowerState. Throw an exception?
1684 this.mCanPostpone = false;
1685 this.mCanSleep = false;
1686 this.mCarPowerStateListenerState = 0;
1687 this.mState = 0;
1688 break;
1689 }
1690 }
1691
Steve Paik07db5ed2018-09-24 16:48:52 -07001692 CpmsState(int state, int carPowerStateListenerState) {
Jim Kayed76c2742019-04-02 11:33:27 -07001693 this.mCanPostpone = (state == SIMULATE_SLEEP);
1694 this.mCanSleep = (state == SIMULATE_SLEEP);
Steve Paik07db5ed2018-09-24 16:48:52 -07001695 this.mCarPowerStateListenerState = carPowerStateListenerState;
1696 this.mState = state;
1697 }
1698
Jim Kayed76c2742019-04-02 11:33:27 -07001699 public String name() {
1700 String baseName;
1701 switch(mState) {
1702 case WAIT_FOR_VHAL: baseName = "WAIT_FOR_VHAL"; break;
1703 case ON: baseName = "ON"; break;
1704 case SHUTDOWN_PREPARE: baseName = "SHUTDOWN_PREPARE"; break;
1705 case WAIT_FOR_FINISH: baseName = "WAIT_FOR_FINISH"; break;
1706 case SUSPEND: baseName = "SUSPEND"; break;
1707 case SIMULATE_SLEEP: baseName = "SIMULATE_SLEEP"; break;
1708 default: baseName = "<unknown>"; break;
1709 }
1710 return baseName + "(" + mState + ")";
1711 }
1712
Steve Paik07db5ed2018-09-24 16:48:52 -07001713 private static int cpmsStateToPowerStateListenerState(int state) {
1714 int powerStateListenerState = 0;
1715
1716 // Set the CarPowerStateListenerState based on current state
1717 switch (state) {
1718 case ON:
1719 powerStateListenerState = CarPowerStateListener.ON;
1720 break;
1721 case SHUTDOWN_PREPARE:
1722 powerStateListenerState = CarPowerStateListener.SHUTDOWN_PREPARE;
1723 break;
1724 case SUSPEND:
1725 powerStateListenerState = CarPowerStateListener.SUSPEND_ENTER;
1726 break;
1727 case WAIT_FOR_VHAL:
1728 case WAIT_FOR_FINISH:
1729 default:
1730 // Illegal state for this constructor. Throw an exception?
1731 break;
1732 }
1733 return powerStateListenerState;
1734 }
1735
1736 @Override
1737 public boolean equals(Object o) {
1738 if (this == o) {
1739 return true;
1740 }
1741 if (!(o instanceof CpmsState)) {
1742 return false;
1743 }
1744 CpmsState that = (CpmsState) o;
1745 return this.mState == that.mState
1746 && this.mCanSleep == that.mCanSleep
1747 && this.mCanPostpone == that.mCanPostpone
1748 && this.mCarPowerStateListenerState == that.mCarPowerStateListenerState;
1749 }
1750
1751 @Override
1752 public String toString() {
1753 return "CpmsState canSleep:" + mCanSleep + ", canPostpone=" + mCanPostpone
1754 + ", carPowerStateListenerState=" + mCarPowerStateListenerState
Jim Kayed76c2742019-04-02 11:33:27 -07001755 + ", CpmsState=" + this.name();
Steve Paik07db5ed2018-09-24 16:48:52 -07001756 }
1757 }
1758
Jim Kayed76c2742019-04-02 11:33:27 -07001759 /**
1760 * Resume after a manually-invoked suspend.
1761 * Invoked using "adb shell dumpsys activity service com.android.car resume".
1762 */
1763 public void forceSimulatedResume() {
Jim Kaye0ffbf522019-07-01 16:10:40 -07001764 PowerHandler handler;
Jim Kayed22f1d62019-12-03 16:08:00 -08001765 synchronized (mLock) {
Jim Kaye0ffbf522019-07-01 16:10:40 -07001766 // Cancel Garage Mode in case it's running
1767 mPendingPowerStates.addFirst(new CpmsState(CpmsState.WAIT_FOR_VHAL,
1768 CarPowerStateListener.SHUTDOWN_CANCELLED));
Jim Kayea94bb8b2020-07-28 09:42:35 -07001769 mLock.notify();
Jim Kaye0ffbf522019-07-01 16:10:40 -07001770 handler = mHandler;
1771 }
1772 handler.handlePowerStateChange();
1773
Jim Kayed22f1d62019-12-03 16:08:00 -08001774 synchronized (mSimulationWaitObject) {
Jim Kaye4ae10b42019-04-02 11:42:50 -07001775 mWakeFromSimulatedSleep = true;
Jim Kayed22f1d62019-12-03 16:08:00 -08001776 mSimulationWaitObject.notify();
Jim Kayed76c2742019-04-02 11:33:27 -07001777 }
1778 }
1779
1780 /**
Jim Kaye9a834ea2020-02-07 15:50:53 -08001781 * Manually enter simulated suspend (Deep Sleep) mode, trigging Garage mode.
1782 * If the parameter is 'true', reboot the system when Garage Mode completes.
1783 *
1784 * Invoked using "adb shell dumpsys activity service com.android.car suspend" or
1785 * "adb shell dumpsys activity service com.android.car garage-mode reboot".
Jim Kayed76c2742019-04-02 11:33:27 -07001786 * This is similar to 'onApPowerStateChange()' except that it needs to create a CpmsState
1787 * that is not directly derived from a VehicleApPowerStateReq.
1788 */
Eric Jeongbc351e22020-07-31 13:54:17 -07001789 public void forceSuspendAndMaybeReboot(boolean shouldReboot) {
Jim Kayed22f1d62019-12-03 16:08:00 -08001790 synchronized (mSimulationWaitObject) {
Jim Kaye4ae10b42019-04-02 11:42:50 -07001791 mInSimulatedDeepSleepMode = true;
1792 mWakeFromSimulatedSleep = false;
Jim Kaye9889f282020-05-28 09:17:17 -07001793 mGarageModeShouldExitImmediately = false;
Jim Kayed76c2742019-04-02 11:33:27 -07001794 }
1795 PowerHandler handler;
Jim Kayed22f1d62019-12-03 16:08:00 -08001796 synchronized (mLock) {
Jim Kaye9a834ea2020-02-07 15:50:53 -08001797 mRebootAfterGarageMode = shouldReboot;
Jim Kayed76c2742019-04-02 11:33:27 -07001798 mPendingPowerStates.addFirst(new CpmsState(CpmsState.SIMULATE_SLEEP,
1799 CarPowerStateListener.SHUTDOWN_PREPARE));
1800 handler = mHandler;
1801 }
1802 handler.handlePowerStateChange();
1803 }
1804
Eric Jeonga2934632020-11-08 23:14:30 -08001805 /**
1806 * Manually defines a power policy.
1807 *
1808 * <p>If the given ID already exists or specified power components are invalid, it fails.
1809 *
Eric Jeong83225c72021-05-13 13:22:45 -07001810 * @return {@code true}, if successful. Otherwise, {@code false}.
Eric Jeonga2934632020-11-08 23:14:30 -08001811 */
Eric Jeong83225c72021-05-13 13:22:45 -07001812 public boolean definePowerPolicyFromCommand(String[] args, IndentingPrintWriter writer) {
Eric Jeonga2934632020-11-08 23:14:30 -08001813 if (args.length < 2) {
Eric Jeong83225c72021-05-13 13:22:45 -07001814 writer.println("Too few arguments");
1815 return false;
Eric Jeonga2934632020-11-08 23:14:30 -08001816 }
1817 String powerPolicyId = args[1];
1818 int index = 2;
1819 String[] enabledComponents = new String[0];
1820 String[] disabledComponents = new String[0];
1821 while (index < args.length) {
1822 switch (args[index]) {
1823 case "--enable":
1824 if (index == args.length - 1) {
Eric Jeong83225c72021-05-13 13:22:45 -07001825 writer.println("No components for --enable");
1826 return false;
Eric Jeonga2934632020-11-08 23:14:30 -08001827 }
1828 enabledComponents = args[index + 1].split(",");
1829 break;
1830 case "--disable":
1831 if (index == args.length - 1) {
Eric Jeong83225c72021-05-13 13:22:45 -07001832 writer.println("No components for --disabled");
1833 return false;
Eric Jeonga2934632020-11-08 23:14:30 -08001834 }
1835 disabledComponents = args[index + 1].split(",");
1836 break;
1837 default:
Eric Jeong83225c72021-05-13 13:22:45 -07001838 writer.printf("Unrecognized argument: %s\n", args[index]);
1839 return false;
Eric Jeonga2934632020-11-08 23:14:30 -08001840 }
1841 index += 2;
1842 }
Eric Jeong83225c72021-05-13 13:22:45 -07001843 int status = definePowerPolicy(powerPolicyId, enabledComponents, disabledComponents);
1844 if (status != PolicyOperationStatus.OK) {
1845 writer.println(PolicyOperationStatus.errorCodeToString(status));
1846 return false;
Eric Jeongb7003812020-12-08 11:37:55 -08001847 }
Eric Jeong83225c72021-05-13 13:22:45 -07001848 writer.printf("Power policy(%s) is successfully defined.\n", powerPolicyId);
1849 return true;
Eric Jeongb7003812020-12-08 11:37:55 -08001850 }
1851
1852 /**
1853 * Defines a power policy with the given id and components.
1854 *
1855 * <p> A policy defined with this method is valid until the system is rebooted/restarted.
1856 */
1857 @VisibleForTesting
Eric Jeong83225c72021-05-13 13:22:45 -07001858 @PolicyOperationStatus.ErrorCode
1859 public int definePowerPolicy(String powerPolicyId, String[] enabledComponents,
Eric Jeongb7003812020-12-08 11:37:55 -08001860 String[] disabledComponents) {
Eric Jeong83225c72021-05-13 13:22:45 -07001861 int status = mPolicyReader.definePowerPolicy(powerPolicyId,
1862 enabledComponents, disabledComponents);
1863 if (status != PolicyOperationStatus.OK) {
1864 int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY;
1865 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error));
1866 return error;
Eric Jeonga2934632020-11-08 23:14:30 -08001867 }
1868 ICarPowerPolicySystemNotification daemon;
1869 synchronized (mLock) {
1870 daemon = mCarPowerPolicyDaemon;
1871 }
1872 try {
1873 daemon.notifyPowerPolicyDefinition(powerPolicyId, enabledComponents,
1874 disabledComponents);
1875 } catch (RemoteException e) {
Eric Jeong83225c72021-05-13 13:22:45 -07001876 int error = PolicyOperationStatus.ERROR_DEFINE_POWER_POLICY;
1877 Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(error));
1878 return error;
Eric Jeonga2934632020-11-08 23:14:30 -08001879 }
Eric Jeong83225c72021-05-13 13:22:45 -07001880 return PolicyOperationStatus.OK;
Eric Jeonga2934632020-11-08 23:14:30 -08001881 }
1882
1883 /**
1884 * Manually applies a power policy.
1885 *
1886 * <p>If the given ID is not defined, it fails.
1887 *
Eric Jeong83225c72021-05-13 13:22:45 -07001888 * @return {@code true}, if successful. Otherwise, {@code false}.
Eric Jeonga2934632020-11-08 23:14:30 -08001889 */
Eric Jeong83225c72021-05-13 13:22:45 -07001890 public boolean applyPowerPolicyFromCommand(String[] args, IndentingPrintWriter writer) {
Eric Jeonga2934632020-11-08 23:14:30 -08001891 if (args.length != 2) {
Eric Jeong83225c72021-05-13 13:22:45 -07001892 writer.println("Power policy ID should be given");
1893 return false;
Eric Jeonga2934632020-11-08 23:14:30 -08001894 }
1895 String powerPolicyId = args[1];
Eric Jeong4b69cf72021-01-07 21:23:16 -08001896 if (powerPolicyId == null) {
Eric Jeong83225c72021-05-13 13:22:45 -07001897 writer.println("Policy ID cannot be null");
1898 return false;
Eric Jeong4b69cf72021-01-07 21:23:16 -08001899 }
Eric Jeong36f61d42021-02-19 22:10:45 -08001900 boolean isPreemptive = mPolicyReader.isPreemptivePowerPolicy(powerPolicyId);
Eric Jeong83225c72021-05-13 13:22:45 -07001901 int status = isPreemptive ? applyPreemptivePowerPolicy(powerPolicyId)
Eric Jeong36f61d42021-02-19 22:10:45 -08001902 : applyPowerPolicy(powerPolicyId, true);
Eric Jeong83225c72021-05-13 13:22:45 -07001903 if (status != PolicyOperationStatus.OK) {
1904 writer.println(PolicyOperationStatus.errorCodeToString(status));
1905 return false;
Eric Jeonga2934632020-11-08 23:14:30 -08001906 }
1907 writer.printf("Power policy(%s) is successfully applied.\n", powerPolicyId);
Eric Jeong83225c72021-05-13 13:22:45 -07001908 return true;
Eric Jeonga2934632020-11-08 23:14:30 -08001909 }
1910
Eric Jeonge701e0d2020-12-16 17:54:00 -08001911 /**
Eric Jeong110c9632021-04-09 10:59:50 -07001912 * Manually defines a power policy group.
1913 *
1914 * <p>If the given ID already exists, a wrong power state is given, or specified power policy ID
1915 * doesn't exist, it fails.
1916 *
Eric Jeong83225c72021-05-13 13:22:45 -07001917 * @return {@code true}, if successful. Otherwise, {@code false}.
Eric Jeong110c9632021-04-09 10:59:50 -07001918 */
Eric Jeong83225c72021-05-13 13:22:45 -07001919 public boolean definePowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer) {
Eric Jeong110c9632021-04-09 10:59:50 -07001920 if (args.length < 3 || args.length > 4) {
Eric Jeong83225c72021-05-13 13:22:45 -07001921 writer.println("Invalid syntax");
1922 return false;
Eric Jeong110c9632021-04-09 10:59:50 -07001923 }
1924 String policyGroupId = args[1];
1925 int index = 2;
1926 SparseArray<String> defaultPolicyPerState = new SparseArray<>();
1927 while (index < args.length) {
1928 String[] tokens = args[index].split(":");
1929 if (tokens.length != 2) {
Eric Jeong83225c72021-05-13 13:22:45 -07001930 writer.println("Invalid syntax");
1931 return false;
Eric Jeong110c9632021-04-09 10:59:50 -07001932 }
1933 int state = PolicyReader.toPowerState(tokens[0]);
1934 if (state == PolicyReader.INVALID_POWER_STATE) {
Eric Jeong83225c72021-05-13 13:22:45 -07001935 writer.printf("Invalid power state: %s\n", tokens[0]);
1936 return false;
Eric Jeong110c9632021-04-09 10:59:50 -07001937 }
1938 defaultPolicyPerState.put(state, tokens[1]);
1939 index++;
1940 }
Eric Jeong83225c72021-05-13 13:22:45 -07001941 int status = mPolicyReader.definePowerPolicyGroup(policyGroupId,
Eric Jeong110c9632021-04-09 10:59:50 -07001942 defaultPolicyPerState);
Eric Jeong83225c72021-05-13 13:22:45 -07001943 if (status != PolicyOperationStatus.OK) {
1944 writer.println(PolicyOperationStatus.errorCodeToString(status));
1945 return false;
Eric Jeong110c9632021-04-09 10:59:50 -07001946 }
Eric Jeong83225c72021-05-13 13:22:45 -07001947 writer.printf("Power policy group(%s) is successfully defined.\n", policyGroupId);
1948 return true;
Eric Jeong110c9632021-04-09 10:59:50 -07001949 }
1950
1951 /**
1952 * Manually sets a power policy group.
1953 *
1954 * <p>If the given ID is not defined, it fails.
1955 *
Eric Jeong83225c72021-05-13 13:22:45 -07001956 * @return {@code true}, if successful. Otherwise, {@code false}.
Eric Jeong110c9632021-04-09 10:59:50 -07001957 */
Eric Jeong83225c72021-05-13 13:22:45 -07001958 public boolean setPowerPolicyGroupFromCommand(String[] args, IndentingPrintWriter writer) {
Eric Jeong110c9632021-04-09 10:59:50 -07001959 if (args.length != 2) {
Eric Jeong83225c72021-05-13 13:22:45 -07001960 writer.println("Power policy group ID should be given");
1961 return false;
Eric Jeong110c9632021-04-09 10:59:50 -07001962 }
1963 String policyGroupId = args[1];
Eric Jeong83225c72021-05-13 13:22:45 -07001964 int status = setCurrentPowerPolicyGroup(policyGroupId);
1965 if (status != PolicyOperationStatus.OK) {
1966 writer.println(PolicyOperationStatus.errorCodeToString(status));
1967 return false;
Eric Jeong110c9632021-04-09 10:59:50 -07001968 }
Eric Jeong83225c72021-05-13 13:22:45 -07001969 writer.printf("Setting power policy group(%s) is successful.\n", policyGroupId);
1970 return true;
Eric Jeong110c9632021-04-09 10:59:50 -07001971 }
1972
1973 /**
Eric Jeonge701e0d2020-12-16 17:54:00 -08001974 * Powers off the device, considering the given options.
1975 *
1976 * <p>The final state can be "suspend-to-RAM" or "shutdown". Attempting to go to suspend-to-RAM
1977 * on devices which do not support it may lead to an unexpected system state.
1978 */
1979 public void powerOffFromCommand(boolean skipGarageMode, boolean shutdown) {
1980 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1981 int param = 0;
1982 if (shutdown) {
1983 param = skipGarageMode ? VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY
1984 : VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY;
1985 } else {
1986 param = skipGarageMode ? VehicleApPowerStateShutdownParam.SLEEP_IMMEDIATELY
1987 : VehicleApPowerStateShutdownParam.CAN_SLEEP;
1988 }
1989 PowerState state = new PowerState(VehicleApPowerStateReq.SHUTDOWN_PREPARE, param);
1990 synchronized (mLock) {
1991 mRebootAfterGarageMode = false;
1992 mPendingPowerStates.addFirst(new CpmsState(state));
1993 mLock.notify();
1994 }
1995 mHandler.handlePowerStateChange();
1996 }
1997
Eric Jeongc1f53b22021-02-18 00:40:36 -08001998 /**
1999 * Changes Silent Mode to the given mode.
2000 */
2001 public void setSilentMode(String silentMode) {
2002 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
2003 mSilentModeHandler.setSilentMode(silentMode);
2004 }
2005
2006 /**
2007 * Dumps the current Silent Mode.
2008 */
2009 public void dumpSilentMode(IndentingPrintWriter writer) {
2010 mSilentModeHandler.dump(writer);
2011 }
2012
Jim Kayed76c2742019-04-02 11:33:27 -07002013 // In a real Deep Sleep, the hardware removes power from the CPU (but retains power
2014 // on the RAM). This puts the processor to sleep. Upon some external signal, power
2015 // is re-applied to the CPU, and processing resumes right where it left off.
Jim Kayed22f1d62019-12-03 16:08:00 -08002016 // We simulate this behavior by calling wait().
2017 // We continue from wait() when forceSimulatedResume() is called.
2018 private void simulateSleepByWaiting() {
Eric Jeongd37b78b2021-04-29 00:22:36 -07002019 Slogf.i(TAG, "Starting to simulate Deep Sleep by waiting");
Jim Kayed22f1d62019-12-03 16:08:00 -08002020 synchronized (mSimulationWaitObject) {
Jim Kaye4ae10b42019-04-02 11:42:50 -07002021 while (!mWakeFromSimulatedSleep) {
Jim Kayed76c2742019-04-02 11:33:27 -07002022 try {
Jim Kayed22f1d62019-12-03 16:08:00 -08002023 mSimulationWaitObject.wait();
Jim Kayed76c2742019-04-02 11:33:27 -07002024 } catch (InterruptedException ignored) {
Jim Kayed22f1d62019-12-03 16:08:00 -08002025 Thread.currentThread().interrupt(); // Restore interrupted status
Jim Kayed76c2742019-04-02 11:33:27 -07002026 }
2027 }
Jim Kaye4ae10b42019-04-02 11:42:50 -07002028 mInSimulatedDeepSleepMode = false;
Jim Kayed76c2742019-04-02 11:33:27 -07002029 }
Eric Jeongd37b78b2021-04-29 00:22:36 -07002030 Slogf.i(TAG, "Exit Deep Sleep simulation");
Jim Kayed76c2742019-04-02 11:33:27 -07002031 }
Eric Jeongdecc4252020-11-19 22:05:41 -08002032
2033 private int getMaxSuspendWaitDurationConfig() {
2034 return mContext.getResources().getInteger(R.integer.config_maxSuspendWaitDuration);
2035 }
keunyoung4b0212c2015-10-29 17:11:57 -07002036}