blob: 13492b22178d5731fe093f6fb4e07ea42fd12265 [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 Jeongbc351e22020-07-31 13:54:17 -070016package com.android.car.power;
keunyoung4b0212c2015-10-29 17:11:57 -070017
Jim Kaye24ddc862020-04-30 14:05:17 -070018import android.annotation.NonNull;
felipeal53e5ee82020-05-15 17:47:24 -070019import android.annotation.UserIdInt;
Anthony Hughfbb67762019-10-15 12:54:54 -070020import android.app.ActivityManager;
Steve Paik87b36fd2018-03-13 19:25:47 -070021import android.car.Car;
22import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
23import android.car.hardware.power.ICarPower;
24import android.car.hardware.power.ICarPowerStateListener;
felipeal19e3d732020-03-18 12:07:32 -070025import android.car.userlib.HalCallback;
felipeal283b58f2020-04-01 12:49:05 -070026import android.car.userlib.InitialUserSetter;
felipeal53e5ee82020-05-15 17:47:24 -070027import android.car.userlib.InitialUserSetter.InitialUserInfoType;
felipeal283b58f2020-04-01 12:49:05 -070028import android.car.userlib.UserHalHelper;
29import android.car.userlib.UserHelper;
Mayank Gargfc24d572020-02-14 11:32:34 -080030import android.content.ComponentName;
Steve Paik87b36fd2018-03-13 19:25:47 -070031import android.content.Context;
Mayank Gargfc24d572020-02-14 11:32:34 -080032import android.content.Intent;
Felipe Lemef45ee502019-12-19 10:00:14 -080033import android.content.pm.UserInfo;
Felipe Leme848eb652019-12-18 09:53:18 -080034import android.content.res.Resources;
Felipe Lemee3cab982020-03-12 11:39:29 -070035import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
felipeale40abfe2020-03-16 17:11:52 -070036import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
Steve Paik07db5ed2018-09-24 16:48:52 -070037import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
Eric Jeong26f47c72020-07-22 15:45:24 -070038import android.net.wifi.WifiManager;
Keun young Park8c152cb2019-05-09 18:04:31 -070039import android.os.Build;
Steve Paik87b36fd2018-03-13 19:25:47 -070040import android.os.Handler;
41import android.os.HandlerThread;
42import android.os.IBinder;
43import android.os.Looper;
44import android.os.Message;
Jim Kaye9a834ea2020-02-07 15:50:53 -080045import android.os.PowerManager;
Steve Paik87b36fd2018-03-13 19:25:47 -070046import android.os.RemoteCallbackList;
47import android.os.RemoteException;
48import android.os.SystemClock;
Keun young Park8c152cb2019-05-09 18:04:31 -070049import android.os.SystemProperties;
Keun young Park9b3f2662019-03-19 10:30:25 -070050import android.os.UserHandle;
Felipe Lemef45ee502019-12-19 10:00:14 -080051import android.os.UserManager;
felipeal23004822020-03-19 09:57:56 -070052import android.sysprop.CarProperties;
Eric Jeong26f47c72020-07-22 15:45:24 -070053import android.util.AtomicFile;
54import android.util.Slog;
keunyoung4b0212c2015-10-29 17:11:57 -070055
Eric Jeongbc351e22020-07-31 13:54:17 -070056import com.android.car.CarLocalServices;
57import com.android.car.CarLog;
58import com.android.car.CarServiceBase;
59import com.android.car.CarServiceUtils;
60import com.android.car.CarStatsLogHelper;
61import com.android.car.ICarImpl;
62import com.android.car.R;
Mayank Gargfc24d572020-02-14 11:32:34 -080063import com.android.car.am.ContinuousBlankActivity;
keunyoung4b0212c2015-10-29 17:11:57 -070064import com.android.car.hal.PowerHalService;
65import com.android.car.hal.PowerHalService.PowerState;
Enrico Granatab19bc322017-10-12 12:25:06 -070066import com.android.car.systeminterface.SystemInterface;
Mayank Gargfc24d572020-02-14 11:32:34 -080067import com.android.car.user.CarUserNoticeService;
Felipe Lemee3cab982020-03-12 11:39:29 -070068import com.android.car.user.CarUserService;
keunyoung4b0212c2015-10-29 17:11:57 -070069import com.android.internal.annotations.GuardedBy;
Yao Chendacd7242016-01-26 14:42:42 -080070import com.android.internal.annotations.VisibleForTesting;
keunyoung4b0212c2015-10-29 17:11:57 -070071
Eric Jeong26f47c72020-07-22 15:45:24 -070072import java.io.BufferedReader;
73import java.io.BufferedWriter;
74import java.io.File;
75import java.io.FileOutputStream;
76import java.io.IOException;
77import java.io.InputStreamReader;
78import java.io.OutputStreamWriter;
Steve Paik87b36fd2018-03-13 19:25:47 -070079import java.io.PrintWriter;
Keun young Parkb241d022020-04-20 20:31:34 -070080import java.lang.ref.WeakReference;
Eric Jeong26f47c72020-07-22 15:45:24 -070081import java.nio.charset.StandardCharsets;
Jim Kayee5133162019-04-22 12:50:27 -070082import java.util.HashSet;
Steve Paik87b36fd2018-03-13 19:25:47 -070083import java.util.LinkedList;
Jim Kayee5133162019-04-22 12:50:27 -070084import java.util.Set;
Steve Paik87b36fd2018-03-13 19:25:47 -070085import java.util.Timer;
86import java.util.TimerTask;
keunyoung4b0212c2015-10-29 17:11:57 -070087
Serik Beketayev1d9e0d82018-09-11 08:19:33 -070088/**
89 * Power Management service class for cars. Controls the power states and interacts with other
90 * parts of the system to ensure its own state.
91 */
92public class CarPowerManagementService extends ICarPower.Stub implements
93 CarServiceBase, PowerHalService.PowerEventListener {
Jim Kayed22f1d62019-12-03 16:08:00 -080094
Felipe Lemee3cab982020-03-12 11:39:29 -070095 // TODO: replace all usage
96 private static final String TAG = CarLog.TAG_POWER;
Eric Jeong26f47c72020-07-22 15:45:24 -070097 private static final String WIFI_STATE_FILENAME = "wifi_state";
98 private static final String WIFI_STATE_MODIFIED = "forcibly_disabled";
99 private static final String WIFI_STATE_ORIGINAL = "original";
Felipe Lemee3cab982020-03-12 11:39:29 -0700100
Jim Kayed22f1d62019-12-03 16:08:00 -0800101 private final Object mLock = new Object();
102 private final Object mSimulationWaitObject = new Object();
103
Steve Paik388d7772018-02-12 10:54:51 -0800104 private final Context mContext;
keunyoung4b0212c2015-10-29 17:11:57 -0700105 private final PowerHalService mHal;
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700106 private final SystemInterface mSystemInterface;
Jim Kayee5133162019-04-22 12:50:27 -0700107 // The listeners that complete simply by returning from onStateChanged()
Steve Paik03124082018-02-16 11:19:26 -0800108 private final PowerManagerCallbackList mPowerManagerListeners = new PowerManagerCallbackList();
Jim Kayee5133162019-04-22 12:50:27 -0700109 // The listeners that must indicate asynchronous completion by calling finished().
110 private final PowerManagerCallbackList mPowerManagerListenersWithCompletion =
111 new PowerManagerCallbackList();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800112
Jim Kayed22f1d62019-12-03 16:08:00 -0800113 @GuardedBy("mSimulationWaitObject")
114 private boolean mWakeFromSimulatedSleep;
115 @GuardedBy("mSimulationWaitObject")
116 private boolean mInSimulatedDeepSleepMode;
117
118 @GuardedBy("mLock")
119 private final Set<IBinder> mListenersWeAreWaitingFor = new HashSet<>();
120 @GuardedBy("mLock")
Steve Paik07db5ed2018-09-24 16:48:52 -0700121 private CpmsState mCurrentState;
Jim Kayed22f1d62019-12-03 16:08:00 -0800122 @GuardedBy("mLock")
keunyoung4b0212c2015-10-29 17:11:57 -0700123 private Timer mTimer;
Jim Kayed22f1d62019-12-03 16:08:00 -0800124 @GuardedBy("mLock")
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800125 private long mProcessingStartTime;
Jim Kayed22f1d62019-12-03 16:08:00 -0800126 @GuardedBy("mLock")
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800127 private long mLastSleepEntryTime;
Jim Kayed22f1d62019-12-03 16:08:00 -0800128 @GuardedBy("mLock")
Steve Paik07db5ed2018-09-24 16:48:52 -0700129 private final LinkedList<CpmsState> mPendingPowerStates = new LinkedList<>();
Keun young Parkb241d022020-04-20 20:31:34 -0700130 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
131 getClass().getSimpleName());
132 private final PowerHandler mHandler = new PowerHandler(mHandlerThread.getLooper(), this);
133
Jim Kayed22f1d62019-12-03 16:08:00 -0800134 @GuardedBy("mLock")
Serik Beketayevf8287a02019-02-08 12:31:10 -0800135 private boolean mTimerActive;
Jim Kayed22f1d62019-12-03 16:08:00 -0800136 @GuardedBy("mLock")
137 private int mNextWakeupSec;
138 @GuardedBy("mLock")
139 private boolean mShutdownOnFinish;
140 @GuardedBy("mLock")
Jim Kayedab62d82019-12-18 14:52:19 -0800141 private boolean mShutdownOnNextSuspend;
142 @GuardedBy("mLock")
Keun young Park9b3f2662019-03-19 10:30:25 -0700143 private boolean mIsBooting = true;
Jim Kayed22f1d62019-12-03 16:08:00 -0800144 @GuardedBy("mLock")
Jim Kaye32ea4ce2019-12-03 15:00:51 -0800145 private boolean mIsResuming;
Jim Kaye9a834ea2020-02-07 15:50:53 -0800146 @GuardedBy("mLock")
Jim Kaye253dfff2020-01-29 09:45:22 -0800147 private int mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS;
148 @GuardedBy("mLock")
149 private int mShutdownPollingIntervalMs = SHUTDOWN_POLLING_INTERVAL_MS;
150 @GuardedBy("mLock")
Jim Kaye9a834ea2020-02-07 15:50:53 -0800151 private boolean mRebootAfterGarageMode;
Jim Kaye9889f282020-05-28 09:17:17 -0700152 @GuardedBy("mLock")
153 private boolean mGarageModeShouldExitImmediately;
Felipe Leme848eb652019-12-18 09:53:18 -0800154 private final boolean mDisableUserSwitchDuringResume;
Felipe Lemee3cab982020-03-12 11:39:29 -0700155
felipeal283b58f2020-04-01 12:49:05 -0700156 private final UserManager mUserManager;
Felipe Lemee3cab982020-03-12 11:39:29 -0700157 private final CarUserService mUserService;
felipeal283b58f2020-04-01 12:49:05 -0700158 private final InitialUserSetter mInitialUserSetter;
keunyoung4b0212c2015-10-29 17:11:57 -0700159
Eric Jeong26f47c72020-07-22 15:45:24 -0700160 private final WifiManager mWifiManager;
161 private final AtomicFile mWifiStateFile;
162
Steve Paik03124082018-02-16 11:19:26 -0800163 // TODO: Make this OEM configurable.
Steve Paik07db5ed2018-09-24 16:48:52 -0700164 private static final int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
165 private static final int SHUTDOWN_EXTEND_MAX_MS = 5000;
166
Keun young Park4b4ddda2019-03-26 18:47:37 -0700167 // maxGarageModeRunningDurationInSecs should be equal or greater than this. 15 min for now.
168 private static final int MIN_MAX_GARAGE_MODE_DURATION_MS = 15 * 60 * 1000;
169
Keun young Park8c152cb2019-05-09 18:04:31 -0700170 // in secs
171 private static final String PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE =
172 "android.car.garagemodeduration";
173
Keun young Park62de5522020-03-10 10:47:09 -0700174 // This is a temp work-around to reduce user switching delay after wake-up.
175 private final boolean mSwitchGuestUserBeforeSleep;
176
Steve Paik03124082018-02-16 11:19:26 -0800177 private class PowerManagerCallbackList extends RemoteCallbackList<ICarPowerStateListener> {
178 /**
179 * Old version of {@link #onCallbackDied(E, Object)} that
180 * does not provide a cookie.
181 */
182 @Override
183 public void onCallbackDied(ICarPowerStateListener listener) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700184 Slog.i(TAG, "binderDied " + listener.asBinder());
Steve Paik03124082018-02-16 11:19:26 -0800185 CarPowerManagementService.this.doUnregisterListener(listener);
186 }
187 }
188
Felipe Leme848eb652019-12-18 09:53:18 -0800189 public CarPowerManagementService(Context context, PowerHalService powerHal,
felipeal283b58f2020-04-01 12:49:05 -0700190 SystemInterface systemInterface, CarUserService carUserService) {
191 this(context, context.getResources(), powerHal, systemInterface, UserManager.get(context),
192 carUserService, new InitialUserSetter(context,
felipeal61ce3732020-04-03 11:01:00 -0700193 (u) -> carUserService.setInitialUser(u),
Jim Kaye765e79e2020-06-04 13:48:54 -0700194 context.getString(R.string.default_guest_name)));
Felipe Leme848eb652019-12-18 09:53:18 -0800195 }
196
197 @VisibleForTesting
Jim Kaye18624bf2020-05-01 16:14:12 -0700198 public CarPowerManagementService(Context context, Resources resources, PowerHalService powerHal,
felipeal53e5ee82020-05-15 17:47:24 -0700199 SystemInterface systemInterface, UserManager userManager, CarUserService carUserService,
Jim Kaye765e79e2020-06-04 13:48:54 -0700200 InitialUserSetter initialUserSetter) {
Steve Paik388d7772018-02-12 10:54:51 -0800201 mContext = context;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800202 mHal = powerHal;
203 mSystemInterface = systemInterface;
Felipe Lemef45ee502019-12-19 10:00:14 -0800204 mUserManager = userManager;
Felipe Leme848eb652019-12-18 09:53:18 -0800205 mDisableUserSwitchDuringResume = resources
206 .getBoolean(R.bool.config_disableUserSwitchDuringResume);
Jim Kaye253dfff2020-01-29 09:45:22 -0800207 mShutdownPrepareTimeMs = resources.getInteger(
Keun young Park4b4ddda2019-03-26 18:47:37 -0700208 R.integer.maxGarageModeRunningDurationInSecs) * 1000;
Keun young Park62de5522020-03-10 10:47:09 -0700209 mSwitchGuestUserBeforeSleep = resources.getBoolean(
210 R.bool.config_switchGuestUserBeforeGoingSleep);
Jim Kaye253dfff2020-01-29 09:45:22 -0800211 if (mShutdownPrepareTimeMs < MIN_MAX_GARAGE_MODE_DURATION_MS) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700212 Slog.w(TAG,
Keun young Park4b4ddda2019-03-26 18:47:37 -0700213 "maxGarageModeRunningDurationInSecs smaller than minimum required, resource:"
Jim Kaye253dfff2020-01-29 09:45:22 -0800214 + mShutdownPrepareTimeMs + "(ms) while should exceed:"
Keun young Park4b4ddda2019-03-26 18:47:37 -0700215 + MIN_MAX_GARAGE_MODE_DURATION_MS + "(ms), Ignore resource.");
Jim Kaye253dfff2020-01-29 09:45:22 -0800216 mShutdownPrepareTimeMs = MIN_MAX_GARAGE_MODE_DURATION_MS;
Keun young Park4b4ddda2019-03-26 18:47:37 -0700217 }
Felipe Lemee3cab982020-03-12 11:39:29 -0700218 mUserService = carUserService;
felipeal283b58f2020-04-01 12:49:05 -0700219 mInitialUserSetter = initialUserSetter;
Eric Jeong26f47c72020-07-22 15:45:24 -0700220 mWifiManager = context.getSystemService(WifiManager.class);
221 mWifiStateFile = new AtomicFile(
222 new File(mSystemInterface.getSystemCarDir(), WIFI_STATE_FILENAME));
Yao Chendacd7242016-01-26 14:42:42 -0800223 }
224
Eric Jeongbc351e22020-07-31 13:54:17 -0700225 /**
226 * Overrides timers to keep testing time short.
227 *
228 * <p>Passing in {@code 0} resets the value to the default.
229 */
Steve Paik07db5ed2018-09-24 16:48:52 -0700230 @VisibleForTesting
Jim Kaye18624bf2020-05-01 16:14:12 -0700231 public void setShutdownTimersForTest(int pollingIntervalMs, int shutdownTimeoutMs) {
Jim Kaye253dfff2020-01-29 09:45:22 -0800232 synchronized (mLock) {
233 mShutdownPollingIntervalMs =
234 (pollingIntervalMs == 0) ? SHUTDOWN_POLLING_INTERVAL_MS : pollingIntervalMs;
235 mShutdownPrepareTimeMs =
236 (shutdownTimeoutMs == 0) ? SHUTDOWN_EXTEND_MAX_MS : shutdownTimeoutMs;
Steve Paik07db5ed2018-09-24 16:48:52 -0700237 }
238 }
239
Keun young Park57fd08e2019-12-13 09:24:59 -0800240 @VisibleForTesting
241 protected HandlerThread getHandlerThread() {
Keun young Parkb241d022020-04-20 20:31:34 -0700242 return mHandlerThread;
Keun young Park57fd08e2019-12-13 09:24:59 -0800243 }
244
keunyoung4b0212c2015-10-29 17:11:57 -0700245 @Override
246 public void init() {
247 mHal.setListener(this);
248 if (mHal.isPowerStateSupported()) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700249 // Initialize CPMS in WAIT_FOR_VHAL state
250 onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, CarPowerStateListener.WAIT_FOR_VHAL);
keunyoung4b0212c2015-10-29 17:11:57 -0700251 } else {
Eric Jeong26f47c72020-07-22 15:45:24 -0700252 Slog.w(TAG, "Vehicle hal does not support power state yet.");
Steve Paik07db5ed2018-09-24 16:48:52 -0700253 onApPowerStateChange(CpmsState.ON, CarPowerStateListener.ON);
keunyoung4b0212c2015-10-29 17:11:57 -0700254 }
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800255 mSystemInterface.startDisplayStateMonitoring(this);
keunyoung4b0212c2015-10-29 17:11:57 -0700256 }
257
258 @Override
259 public void release() {
Jim Kayed22f1d62019-12-03 16:08:00 -0800260 synchronized (mLock) {
keunyoung4b0212c2015-10-29 17:11:57 -0700261 releaseTimerLocked();
262 mCurrentState = null;
Pavel Maltsevddbff982017-03-22 14:49:02 -0700263 mHandler.cancelAll();
Jim Kayed22f1d62019-12-03 16:08:00 -0800264 mListenersWeAreWaitingFor.clear();
Pavel Maltsevddbff982017-03-22 14:49:02 -0700265 }
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800266 mSystemInterface.stopDisplayStateMonitoring();
Steve Paik03124082018-02-16 11:19:26 -0800267 mPowerManagerListeners.kill();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800268 mSystemInterface.releaseAllWakeLocks();
keunyoung4b0212c2015-10-29 17:11:57 -0700269 }
270
keunyoung4b0212c2015-10-29 17:11:57 -0700271 @Override
272 public void dump(PrintWriter writer) {
Jim Kaye253dfff2020-01-29 09:45:22 -0800273 synchronized (mLock) {
274 writer.println("*PowerManagementService*");
Felipe Leme315a53b2020-03-12 10:51:04 -0700275 // TODO: split it in multiple lines
Keun young Park62de5522020-03-10 10:47:09 -0700276 // TODO: lock only what's needed
Jim Kaye253dfff2020-01-29 09:45:22 -0800277 writer.print("mCurrentState:" + mCurrentState);
278 writer.print(",mProcessingStartTime:" + mProcessingStartTime);
279 writer.print(",mLastSleepEntryTime:" + mLastSleepEntryTime);
280 writer.print(",mNextWakeupSec:" + mNextWakeupSec);
281 writer.print(",mShutdownOnNextSuspend:" + mShutdownOnNextSuspend);
282 writer.print(",mShutdownOnFinish:" + mShutdownOnFinish);
283 writer.print(",mShutdownPollingIntervalMs:" + mShutdownPollingIntervalMs);
284 writer.print(",mShutdownPrepareTimeMs:" + mShutdownPrepareTimeMs);
285 writer.print(",mDisableUserSwitchDuringResume:" + mDisableUserSwitchDuringResume);
286 writer.println(",mRebootAfterGarageMode:" + mRebootAfterGarageMode);
Keun young Park62de5522020-03-10 10:47:09 -0700287 writer.println("mSwitchGuestUserBeforeSleep:" + mSwitchGuestUserBeforeSleep);
Jim Kaye253dfff2020-01-29 09:45:22 -0800288 }
felipeal283b58f2020-04-01 12:49:05 -0700289 mInitialUserSetter.dump(writer);
Steve Paik110f95f2017-11-22 14:44:05 -0800290 }
291
292 @Override
keunyoung4b0212c2015-10-29 17:11:57 -0700293 public void onApPowerStateChange(PowerState state) {
Jim Kayed22f1d62019-12-03 16:08:00 -0800294 synchronized (mLock) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700295 mPendingPowerStates.addFirst(new CpmsState(state));
Jim Kayea94bb8b2020-07-28 09:42:35 -0700296 mLock.notify();
Steve Paik07db5ed2018-09-24 16:48:52 -0700297 }
Keun young Parkb241d022020-04-20 20:31:34 -0700298 mHandler.handlePowerStateChange();
Steve Paik07db5ed2018-09-24 16:48:52 -0700299 }
300
Keun young Park9b3f2662019-03-19 10:30:25 -0700301 @VisibleForTesting
Felipe Leme848eb652019-12-18 09:53:18 -0800302 void setStateForTesting(boolean isBooting, boolean isResuming) {
Jim Kayed22f1d62019-12-03 16:08:00 -0800303 synchronized (mLock) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700304 Slog.d(TAG, "setStateForTesting():"
Felipe Leme848eb652019-12-18 09:53:18 -0800305 + " booting(" + mIsBooting + ">" + isBooting + ")"
306 + " resuming(" + mIsResuming + ">" + isResuming + ")");
307 mIsBooting = isBooting;
308 mIsResuming = isResuming;
Jim Kayed22f1d62019-12-03 16:08:00 -0800309 }
Keun young Park9b3f2662019-03-19 10:30:25 -0700310 }
311
Steve Paik07db5ed2018-09-24 16:48:52 -0700312 /**
313 * Initiate state change from CPMS directly.
314 */
315 private void onApPowerStateChange(int apState, int carPowerStateListenerState) {
316 CpmsState newState = new CpmsState(apState, carPowerStateListenerState);
Jim Kayed22f1d62019-12-03 16:08:00 -0800317 synchronized (mLock) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700318 mPendingPowerStates.addFirst(newState);
Jim Kayea94bb8b2020-07-28 09:42:35 -0700319 mLock.notify();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800320 }
Keun young Parkb241d022020-04-20 20:31:34 -0700321 mHandler.handlePowerStateChange();
keunyoung4b0212c2015-10-29 17:11:57 -0700322 }
323
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800324 private void doHandlePowerStateChange() {
Steve Paik07db5ed2018-09-24 16:48:52 -0700325 CpmsState state;
Jim Kayed22f1d62019-12-03 16:08:00 -0800326 synchronized (mLock) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800327 state = mPendingPowerStates.peekFirst();
328 mPendingPowerStates.clear();
329 if (state == null) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700330 Slog.e(TAG, "Null power state was requested");
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800331 return;
332 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700333 Slog.i(TAG, "doHandlePowerStateChange: newState=" + state.name());
Steve Paik07db5ed2018-09-24 16:48:52 -0700334 if (!needPowerStateChangeLocked(state)) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800335 return;
336 }
337 // now real power change happens. Whatever was queued before should be all cancelled.
338 releaseTimerLocked();
Jim Kaye765e79e2020-06-04 13:48:54 -0700339 mCurrentState = state;
keunyoung4b0212c2015-10-29 17:11:57 -0700340 }
Keun young Parkb241d022020-04-20 20:31:34 -0700341 mHandler.cancelProcessingComplete();
Eric Jeong26f47c72020-07-22 15:45:24 -0700342 Slog.i(TAG, "setCurrentState " + state.toString());
Muhammad Qureshi94524cd2020-01-25 23:47:38 -0800343 CarStatsLogHelper.logPowerState(state.mState);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700344 switch (state.mState) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700345 case CpmsState.WAIT_FOR_VHAL:
346 handleWaitForVhal(state);
keunyoung4b0212c2015-10-29 17:11:57 -0700347 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700348 case CpmsState.ON:
349 handleOn();
keunyoung4b0212c2015-10-29 17:11:57 -0700350 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700351 case CpmsState.SHUTDOWN_PREPARE:
keunyoung4b0212c2015-10-29 17:11:57 -0700352 handleShutdownPrepare(state);
353 break;
Jim Kayed76c2742019-04-02 11:33:27 -0700354 case CpmsState.SIMULATE_SLEEP:
355 simulateShutdownPrepare();
356 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700357 case CpmsState.WAIT_FOR_FINISH:
358 handleWaitForFinish(state);
359 break;
360 case CpmsState.SUSPEND:
361 // Received FINISH from VHAL
362 handleFinish();
363 break;
364 default:
365 // Illegal state
366 // TODO: Throw exception?
367 break;
keunyoung4b0212c2015-10-29 17:11:57 -0700368 }
369 }
370
Steve Paik07db5ed2018-09-24 16:48:52 -0700371 private void handleWaitForVhal(CpmsState state) {
372 int carPowerStateListenerState = state.mCarPowerStateListenerState;
Serik Beketayev004ce582019-01-27 17:56:26 -0800373 sendPowerManagerEvent(carPowerStateListenerState);
Steve Paik07db5ed2018-09-24 16:48:52 -0700374 // Inspect CarPowerStateListenerState to decide which message to send via VHAL
375 switch (carPowerStateListenerState) {
376 case CarPowerStateListener.WAIT_FOR_VHAL:
377 mHal.sendWaitForVhal();
378 break;
379 case CarPowerStateListener.SHUTDOWN_CANCELLED:
Jim Kayedab62d82019-12-18 14:52:19 -0800380 mShutdownOnNextSuspend = false; // This cancels the "NextSuspend"
Steve Paik07db5ed2018-09-24 16:48:52 -0700381 mHal.sendShutdownCancel();
382 break;
383 case CarPowerStateListener.SUSPEND_EXIT:
384 mHal.sendSleepExit();
385 break;
386 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700387 restoreWifi();
keunyoung4b0212c2015-10-29 17:11:57 -0700388 }
389
Mayank Gargfc24d572020-02-14 11:32:34 -0800390 private void updateCarUserNoticeServiceIfNecessary() {
391 try {
392 int currentUserId = ActivityManager.getCurrentUser();
393 UserInfo currentUserInfo = mUserManager.getUserInfo(currentUserId);
394 CarUserNoticeService carUserNoticeService =
395 CarLocalServices.getService(CarUserNoticeService.class);
396 if (currentUserInfo != null && currentUserInfo.isGuest()
397 && carUserNoticeService != null) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700398 Slog.i(TAG, "Car user notice service will ignore all messages before user switch.");
Mayank Gargfc24d572020-02-14 11:32:34 -0800399 Intent intent = new Intent();
400 intent.setComponent(new ComponentName(mContext.getPackageName(),
401 ContinuousBlankActivity.class.getName()));
402 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
403 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
404 carUserNoticeService.ignoreUserNotice(currentUserId);
405 }
406 } catch (Exception e) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700407 Slog.w(TAG, "Cannot ignore user notice for current user", e);
Mayank Gargfc24d572020-02-14 11:32:34 -0800408 }
409 }
410
Steve Paik07db5ed2018-09-24 16:48:52 -0700411 private void handleOn() {
Mayank Gargfc24d572020-02-14 11:32:34 -0800412 // If current user is a Guest User, we want to inform CarUserNoticeService not to show
413 // notice for current user, and show user notice only for the target user.
Keun young Park62de5522020-03-10 10:47:09 -0700414 if (!mSwitchGuestUserBeforeSleep) {
415 updateCarUserNoticeServiceIfNecessary();
416 }
Mayank Gargfc24d572020-02-14 11:32:34 -0800417
Jim Kaye32ea4ce2019-12-03 15:00:51 -0800418 // Some OEMs have their own user-switching logic, which may not be coordinated with this
419 // code. To avoid contention, we don't switch users when we coming alive. The OEM's code
420 // should do the switch.
421 boolean allowUserSwitch = true;
Jim Kayed22f1d62019-12-03 16:08:00 -0800422 synchronized (mLock) {
423 if (mIsBooting) {
424 // The system is booting, so don't switch users
425 allowUserSwitch = false;
426 mIsBooting = false;
427 mIsResuming = false;
Eric Jeong26f47c72020-07-22 15:45:24 -0700428 Slog.i(TAG, "User switch disallowed while booting");
Keun young Park29a1e792020-01-15 10:34:29 -0800429 } else {
Jim Kayed22f1d62019-12-03 16:08:00 -0800430 // The system is resuming after a suspension. Optionally disable user switching.
Felipe Leme848eb652019-12-18 09:53:18 -0800431 allowUserSwitch = !mDisableUserSwitchDuringResume;
Jim Kayed22f1d62019-12-03 16:08:00 -0800432 mIsBooting = false;
433 mIsResuming = false;
Jim Kaye8dba6692019-12-03 16:21:03 -0800434 if (!allowUserSwitch) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700435 Slog.i(TAG, "User switch disallowed while resuming");
Jim Kaye8dba6692019-12-03 16:21:03 -0800436 }
Jim Kayed22f1d62019-12-03 16:08:00 -0800437 }
Jim Kaye32ea4ce2019-12-03 15:00:51 -0800438 }
Serik Beketayev004ce582019-01-27 17:56:26 -0800439 sendPowerManagerEvent(CarPowerStateListener.ON);
felipeal524e2652020-05-27 19:26:46 -0700440
Steve Paik07db5ed2018-09-24 16:48:52 -0700441 mHal.sendOn();
Felipe Lemef45ee502019-12-19 10:00:14 -0800442
443 try {
444 switchUserOnResumeIfNecessary(allowUserSwitch);
445 } catch (Exception e) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700446 Slog.e(TAG, "Could not switch user on resume", e);
Felipe Lemef45ee502019-12-19 10:00:14 -0800447 }
448 }
449
Felipe Lemeb382c5c2020-03-11 15:35:03 -0700450 @VisibleForTesting // Ideally it should not be exposed, but it speeds up the unit tests
451 void switchUserOnResumeIfNecessary(boolean allowSwitching) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700452 Slog.d(TAG, "switchUserOnResumeIfNecessary(): allowSwitching=" + allowSwitching
Keun young Park62de5522020-03-10 10:47:09 -0700453 + ", mSwitchGuestUserBeforeSleep=" + mSwitchGuestUserBeforeSleep);
felipeal049b4bf2020-03-31 14:47:06 -0700454 if (!allowSwitching) {
Keun young Park62de5522020-03-10 10:47:09 -0700455 if (mSwitchGuestUserBeforeSleep) { // already handled
456 return;
457 }
458 switchToNewGuestIfNecessary();
felipeal049b4bf2020-03-31 14:47:06 -0700459 return;
460 }
461
felipeal283b58f2020-04-01 12:49:05 -0700462 if (CarProperties.user_hal_enabled().orElse(false) && mUserService.isUserHalSupported()) {
463 switchUserOnResumeIfNecessaryUsingHal();
Felipe Lemef45ee502019-12-19 10:00:14 -0800464 return;
465 }
felipeal049b4bf2020-03-31 14:47:06 -0700466
felipeal53e5ee82020-05-15 17:47:24 -0700467 executeDefaultInitialUserBehavior(!mSwitchGuestUserBeforeSleep);
468 }
469
470 private void executeDefaultInitialUserBehavior(boolean replaceGuest) {
471 mInitialUserSetter.set(newInitialUserInfoBuilder(InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
472 .setReplaceGuest(replaceGuest)
473 .build());
felipeal049b4bf2020-03-31 14:47:06 -0700474 }
475
476 /**
felipeal283b58f2020-04-01 12:49:05 -0700477 * Replaces the current user if it's a guest.
felipeal049b4bf2020-03-31 14:47:06 -0700478 */
Keun young Park62de5522020-03-10 10:47:09 -0700479 private void switchToNewGuestIfNecessary() {
480 int currentUserId = ActivityManager.getCurrentUser();
481 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
482
483 UserInfo newUser = mInitialUserSetter.replaceGuestIfNeeded(currentUser);
484 if (newUser == currentUser) return; // Not a guest
felipeal049b4bf2020-03-31 14:47:06 -0700485
felipeal948f6b62020-04-15 16:06:40 -0700486 boolean replaceGuest = !mSwitchGuestUserBeforeSleep;
felipeal61ce3732020-04-03 11:01:00 -0700487 if (newUser == null) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700488 Slog.w(TAG, "Failed to replace guest; falling back to default behavior");
felipeal53e5ee82020-05-15 17:47:24 -0700489 executeDefaultInitialUserBehavior(replaceGuest);
felipeal283b58f2020-04-01 12:49:05 -0700490 return;
Felipe Lemef45ee502019-12-19 10:00:14 -0800491 }
felipeal53e5ee82020-05-15 17:47:24 -0700492 switchUser(newUser.id, replaceGuest);
493 }
494
495 private void switchUser(@UserIdInt int userId, boolean replaceGuest) {
496 mInitialUserSetter.set(newInitialUserInfoBuilder(InitialUserSetter.TYPE_SWITCH)
497 .setSwitchUserId(userId).setReplaceGuest(replaceGuest).build());
498 }
499
500 private InitialUserSetter.Builder newInitialUserInfoBuilder(@InitialUserInfoType int type) {
501 return new InitialUserSetter.Builder(type)
502 .setSupportsOverrideUserIdProperty(!mUserService.isUserHalSupported());
Felipe Lemef45ee502019-12-19 10:00:14 -0800503 }
504
Felipe Lemee3cab982020-03-12 11:39:29 -0700505 /**
Jim Kaye9889f282020-05-28 09:17:17 -0700506 * Tells Garage Mode if it should run normally, or just
507 * exit immediately without indicating 'idle'
508 * @return True if no idle jobs should be run
509 * @hide
510 */
511 public boolean garageModeShouldExitImmediately() {
512 synchronized (mLock) {
513 return mGarageModeShouldExitImmediately;
514 }
515 }
516
517 /**
Felipe Lemee3cab982020-03-12 11:39:29 -0700518 * Switches the initial user by calling the User HAL to define the behavior.
519 */
felipeal283b58f2020-04-01 12:49:05 -0700520 private void switchUserOnResumeIfNecessaryUsingHal() {
Eric Jeong26f47c72020-07-22 15:45:24 -0700521 Slog.i(TAG, "Using User HAL to define initial user behavior");
felipeale40abfe2020-03-16 17:11:52 -0700522 mUserService.getInitialUserInfo(InitialUserInfoRequestType.RESUME, (status, response) -> {
523 switch (status) {
524 case HalCallback.STATUS_HAL_RESPONSE_TIMEOUT:
525 case HalCallback.STATUS_HAL_SET_TIMEOUT:
felipeal283b58f2020-04-01 12:49:05 -0700526 switchUserOnResumeUserHalFallback("timeout");
felipeale40abfe2020-03-16 17:11:52 -0700527 return;
528 case HalCallback.STATUS_CONCURRENT_OPERATION:
felipeal283b58f2020-04-01 12:49:05 -0700529 switchUserOnResumeUserHalFallback("concurrent call");
felipeale40abfe2020-03-16 17:11:52 -0700530 return;
531 case HalCallback.STATUS_WRONG_HAL_RESPONSE:
felipeal283b58f2020-04-01 12:49:05 -0700532 switchUserOnResumeUserHalFallback("wrong response");
felipeale40abfe2020-03-16 17:11:52 -0700533 return;
Mayank Garg9ed099e2020-06-04 16:05:20 -0700534 case HalCallback.STATUS_HAL_NOT_SUPPORTED:
535 switchUserOnResumeUserHalFallback("Hal not supported");
536 return;
felipeale40abfe2020-03-16 17:11:52 -0700537 case HalCallback.STATUS_OK:
538 if (response == null) {
felipeal283b58f2020-04-01 12:49:05 -0700539 switchUserOnResumeUserHalFallback("no response");
felipeale40abfe2020-03-16 17:11:52 -0700540 return;
Felipe Lemee3cab982020-03-12 11:39:29 -0700541 }
felipeal948f6b62020-04-15 16:06:40 -0700542 boolean replaceGuest = !mSwitchGuestUserBeforeSleep;
felipeale40abfe2020-03-16 17:11:52 -0700543 switch (response.action) {
544 case InitialUserInfoResponseAction.DEFAULT:
Eric Jeong26f47c72020-07-22 15:45:24 -0700545 Slog.i(TAG, "HAL requested default initial user behavior");
felipeal53e5ee82020-05-15 17:47:24 -0700546 executeDefaultInitialUserBehavior(replaceGuest);
felipeale40abfe2020-03-16 17:11:52 -0700547 return;
felipeal283b58f2020-04-01 12:49:05 -0700548 case InitialUserInfoResponseAction.SWITCH:
549 int userId = response.userToSwitchOrCreate.userId;
Eric Jeong26f47c72020-07-22 15:45:24 -0700550 Slog.i(TAG, "HAL requested switch to user " + userId);
felipeal09807c22020-04-09 15:16:52 -0700551 // If guest was replaced on shutdown, it doesn't need to be replaced
552 // again
felipeal53e5ee82020-05-15 17:47:24 -0700553 switchUser(userId, replaceGuest);
felipeal283b58f2020-04-01 12:49:05 -0700554 return;
555 case InitialUserInfoResponseAction.CREATE:
556 int halFlags = response.userToSwitchOrCreate.flags;
557 String name = response.userNameToCreate;
Eric Jeong26f47c72020-07-22 15:45:24 -0700558 Slog.i(TAG, "HAL requested new user (name="
felipeal283b58f2020-04-01 12:49:05 -0700559 + UserHelper.safeName(name) + ", flags="
560 + UserHalHelper.userFlagsToString(halFlags) + ")");
felipeal53e5ee82020-05-15 17:47:24 -0700561 mInitialUserSetter
562 .set(newInitialUserInfoBuilder(InitialUserSetter.TYPE_CREATE)
563 .setNewUserName(name)
564 .setNewUserFlags(halFlags)
565 .build());
felipeal283b58f2020-04-01 12:49:05 -0700566 return;
felipeale40abfe2020-03-16 17:11:52 -0700567 default:
568 switchUserOnResumeUserHalFallback(
felipeal283b58f2020-04-01 12:49:05 -0700569 "invalid response action: " + response.action);
felipeale40abfe2020-03-16 17:11:52 -0700570 return;
571 }
572 default:
felipeal283b58f2020-04-01 12:49:05 -0700573 switchUserOnResumeUserHalFallback("invalid status: " + status);
felipeale40abfe2020-03-16 17:11:52 -0700574 }
575 });
Felipe Lemee3cab982020-03-12 11:39:29 -0700576 }
577
578 /**
579 * Switches the initial user directly when the User HAL call failed.
580 */
felipeal283b58f2020-04-01 12:49:05 -0700581 private void switchUserOnResumeUserHalFallback(String reason) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700582 Slog.w(TAG, "Failed to set initial user based on User Hal (" + reason
Felipe Lemee3cab982020-03-12 11:39:29 -0700583 + "); falling back to default behavior");
felipeal53e5ee82020-05-15 17:47:24 -0700584 executeDefaultInitialUserBehavior(!mSwitchGuestUserBeforeSleep);
keunyoung4b0212c2015-10-29 17:11:57 -0700585 }
586
Steve Paik07db5ed2018-09-24 16:48:52 -0700587 private void handleShutdownPrepare(CpmsState newState) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700588 // Shutdown on finish if the system doesn't support deep sleep or doesn't allow it.
Jim Kayed22f1d62019-12-03 16:08:00 -0800589 synchronized (mLock) {
Jim Kayedab62d82019-12-18 14:52:19 -0800590 mShutdownOnFinish = mShutdownOnNextSuspend
591 || !mHal.isDeepSleepAllowed()
Jim Kayed22f1d62019-12-03 16:08:00 -0800592 || !mSystemInterface.isSystemSupportingDeepSleep()
593 || !newState.mCanSleep;
Jim Kaye9889f282020-05-28 09:17:17 -0700594 mGarageModeShouldExitImmediately = !newState.mCanPostpone;
Jim Kayed22f1d62019-12-03 16:08:00 -0800595 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700596 Slog.i(TAG,
Jim Kaye9889f282020-05-28 09:17:17 -0700597 (newState.mCanPostpone
598 ? "starting shutdown prepare with Garage Mode"
599 : "starting shutdown prepare without Garage Mode"));
600 sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE);
601 mHal.sendShutdownPrepare();
602 doHandlePreprocessing();
keunyoung4b0212c2015-10-29 17:11:57 -0700603 }
604
Jim Kayed76c2742019-04-02 11:33:27 -0700605 // Simulate system shutdown to Deep Sleep
606 private void simulateShutdownPrepare() {
Eric Jeong26f47c72020-07-22 15:45:24 -0700607 Slog.i(TAG, "starting shutdown prepare");
Jim Kayed76c2742019-04-02 11:33:27 -0700608 sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE);
609 mHal.sendShutdownPrepare();
610 doHandlePreprocessing();
611 }
612
Steve Paik07db5ed2018-09-24 16:48:52 -0700613 private void handleWaitForFinish(CpmsState state) {
Serik Beketayev004ce582019-01-27 17:56:26 -0800614 sendPowerManagerEvent(state.mCarPowerStateListenerState);
Jim Kayed22f1d62019-12-03 16:08:00 -0800615 int wakeupSec;
616 synchronized (mLock) {
Jim Kaye9889f282020-05-28 09:17:17 -0700617 // If we're shutting down immediately, don't schedule
618 // a wakeup time.
619 wakeupSec = mGarageModeShouldExitImmediately ? 0 : mNextWakeupSec;
Jim Kayed22f1d62019-12-03 16:08:00 -0800620 }
Steve Paik07db5ed2018-09-24 16:48:52 -0700621 switch (state.mCarPowerStateListenerState) {
622 case CarPowerStateListener.SUSPEND_ENTER:
Jim Kayed22f1d62019-12-03 16:08:00 -0800623 mHal.sendSleepEntry(wakeupSec);
Steve Paik07db5ed2018-09-24 16:48:52 -0700624 break;
625 case CarPowerStateListener.SHUTDOWN_ENTER:
Jim Kayed22f1d62019-12-03 16:08:00 -0800626 mHal.sendShutdownStart(wakeupSec);
Steve Paik07db5ed2018-09-24 16:48:52 -0700627 break;
628 }
629 }
630
631 private void handleFinish() {
Jim Kaye4ae10b42019-04-02 11:42:50 -0700632 boolean simulatedMode;
Jim Kayed22f1d62019-12-03 16:08:00 -0800633 synchronized (mSimulationWaitObject) {
Jim Kaye4ae10b42019-04-02 11:42:50 -0700634 simulatedMode = mInSimulatedDeepSleepMode;
Jim Kayed22f1d62019-12-03 16:08:00 -0800635 }
636 boolean mustShutDown;
Jim Kaye9a834ea2020-02-07 15:50:53 -0800637 boolean forceReboot;
Jim Kayed22f1d62019-12-03 16:08:00 -0800638 synchronized (mLock) {
Jim Kaye4ae10b42019-04-02 11:42:50 -0700639 mustShutDown = mShutdownOnFinish && !simulatedMode;
Jim Kaye9a834ea2020-02-07 15:50:53 -0800640 forceReboot = mRebootAfterGarageMode;
641 mRebootAfterGarageMode = false;
642 }
643 if (forceReboot) {
644 PowerManager powerManager = mContext.getSystemService(PowerManager.class);
645 if (powerManager == null) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700646 Slog.wtf(TAG, "No PowerManager. Cannot reboot.");
Jim Kaye9a834ea2020-02-07 15:50:53 -0800647 } else {
Eric Jeong26f47c72020-07-22 15:45:24 -0700648 Slog.i(TAG, "GarageMode has completed. Forcing reboot.");
Jim Kaye9a834ea2020-02-07 15:50:53 -0800649 powerManager.reboot("GarageModeReboot");
650 throw new AssertionError("Should not return from PowerManager.reboot()");
651 }
Jim Kaye4ae10b42019-04-02 11:42:50 -0700652 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700653 // To make Kernel implementation simpler when going into sleep.
654 disableWifi();
655
Jim Kaye4ae10b42019-04-02 11:42:50 -0700656 if (mustShutDown) {
Serik Beketayevdfedda22018-12-11 16:56:01 -0800657 // shutdown HU
658 mSystemInterface.shutdown();
Steve Paik07db5ed2018-09-24 16:48:52 -0700659 } else {
Jim Kaye4ae10b42019-04-02 11:42:50 -0700660 doHandleDeepSleep(simulatedMode);
Steve Paik07db5ed2018-09-24 16:48:52 -0700661 }
Jim Kayedab62d82019-12-18 14:52:19 -0800662 mShutdownOnNextSuspend = false;
Steve Paik07db5ed2018-09-24 16:48:52 -0700663 }
664
Eric Jeong26f47c72020-07-22 15:45:24 -0700665 private void restoreWifi() {
666 boolean needToRestore = readWifiModifiedState();
667 if (needToRestore) {
668 if (!mWifiManager.isWifiEnabled()) {
669 Slog.i(TAG, "Wifi has been enabled to restore the last setting");
670 mWifiManager.setWifiEnabled(true);
671 }
672 // Update the persistent data as wifi is not modified by car framework.
673 saveWifiModifiedState(false);
674 }
675 }
676
677 private void disableWifi() {
678 boolean wifiEnabled = mWifiManager.isWifiEnabled();
679 boolean wifiModifiedState = readWifiModifiedState();
680 if (wifiEnabled != wifiModifiedState) {
681 saveWifiModifiedState(wifiEnabled);
682 }
683 if (!wifiEnabled) return;
684
685 mWifiManager.setWifiEnabled(false);
686 wifiEnabled = mWifiManager.isWifiEnabled();
687 Slog.i(TAG, "Wifi has been disabled and the last setting was saved");
688 }
689
690 private void saveWifiModifiedState(boolean forciblyDisabled) {
691 FileOutputStream fos;
692 try {
693 fos = mWifiStateFile.startWrite();
694 } catch (IOException e) {
695 Slog.e(TAG, "Cannot create " + WIFI_STATE_FILENAME, e);
696 return;
697 }
698
699 try (BufferedWriter writer = new BufferedWriter(
700 new OutputStreamWriter(fos, StandardCharsets.UTF_8))) {
701 writer.write(forciblyDisabled ? WIFI_STATE_MODIFIED : WIFI_STATE_ORIGINAL);
702 writer.newLine();
703 writer.flush();
704 mWifiStateFile.finishWrite(fos);
705 } catch (IOException e) {
706 mWifiStateFile.failWrite(fos);
707 Slog.e(TAG, "Writing " + WIFI_STATE_FILENAME + " failed", e);
708 }
709 }
710
711 private boolean readWifiModifiedState() {
712 boolean needToRestore = false;
713 boolean invalidState = false;
714
715 try (BufferedReader reader = new BufferedReader(
716 new InputStreamReader(mWifiStateFile.openRead(), StandardCharsets.UTF_8))) {
717 String line = reader.readLine();
718 if (line == null) {
719 needToRestore = false;
720 invalidState = true;
721 } else {
722 line = line.trim();
723 needToRestore = WIFI_STATE_MODIFIED.equals(line);
724 invalidState = !(needToRestore || WIFI_STATE_ORIGINAL.equals(line));
725 }
726 } catch (IOException e) {
727 // If a file named wifi_state doesn't exist, we will not modify Wifi at system start.
728 Slog.w(TAG, "Failed to read " + WIFI_STATE_FILENAME + ": " + e);
729 return false;
730 }
731 if (invalidState) {
732 mWifiStateFile.delete();
733 }
734
735 return needToRestore;
736 }
737
Jim Kayed22f1d62019-12-03 16:08:00 -0800738 @GuardedBy("mLock")
keunyoung4b0212c2015-10-29 17:11:57 -0700739 private void releaseTimerLocked() {
Jim Kayed22f1d62019-12-03 16:08:00 -0800740 if (mTimer != null) {
741 mTimer.cancel();
keunyoung4b0212c2015-10-29 17:11:57 -0700742 }
Jim Kayed22f1d62019-12-03 16:08:00 -0800743 mTimer = null;
744 mTimerActive = false;
keunyoung4b0212c2015-10-29 17:11:57 -0700745 }
746
Steve Paik07db5ed2018-09-24 16:48:52 -0700747 private void doHandlePreprocessing() {
Jim Kaye253dfff2020-01-29 09:45:22 -0800748 int intervalMs;
749 int pollingCount;
750 synchronized (mLock) {
751 intervalMs = mShutdownPollingIntervalMs;
752 pollingCount = (mShutdownPrepareTimeMs / mShutdownPollingIntervalMs) + 1;
753 }
Keun young Park8c152cb2019-05-09 18:04:31 -0700754 if (Build.IS_USERDEBUG || Build.IS_ENG) {
755 int shutdownPrepareTimeOverrideInSecs =
756 SystemProperties.getInt(PROP_MAX_GARAGE_MODE_DURATION_OVERRIDE, -1);
757 if (shutdownPrepareTimeOverrideInSecs >= 0) {
758 pollingCount =
Jim Kaye253dfff2020-01-29 09:45:22 -0800759 (shutdownPrepareTimeOverrideInSecs * 1000 / intervalMs)
Keun young Park8c152cb2019-05-09 18:04:31 -0700760 + 1;
Eric Jeong26f47c72020-07-22 15:45:24 -0700761 Slog.i(TAG, "Garage mode duration overridden secs:"
762 + shutdownPrepareTimeOverrideInSecs);
Keun young Park8c152cb2019-05-09 18:04:31 -0700763 }
764 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700765 Slog.i(TAG, "processing before shutdown expected for: "
Jim Kaye253dfff2020-01-29 09:45:22 -0800766 + mShutdownPrepareTimeMs + " ms, adding polling:" + pollingCount);
Jim Kayed22f1d62019-12-03 16:08:00 -0800767 synchronized (mLock) {
Steve Paik07db5ed2018-09-24 16:48:52 -0700768 mProcessingStartTime = SystemClock.elapsedRealtime();
769 releaseTimerLocked();
770 mTimer = new Timer();
Serik Beketayevf8287a02019-02-08 12:31:10 -0800771 mTimerActive = true;
Steve Paik07db5ed2018-09-24 16:48:52 -0700772 mTimer.scheduleAtFixedRate(
773 new ShutdownProcessingTimerTask(pollingCount),
774 0 /*delay*/,
Jim Kaye253dfff2020-01-29 09:45:22 -0800775 intervalMs);
keunyoung4b0212c2015-10-29 17:11:57 -0700776 }
Keun young Park62de5522020-03-10 10:47:09 -0700777 if (mSwitchGuestUserBeforeSleep) {
778 switchToNewGuestIfNecessary();
779 }
keunyoung4b0212c2015-10-29 17:11:57 -0700780 }
781
Serik Beketayev004ce582019-01-27 17:56:26 -0800782 private void sendPowerManagerEvent(int newState) {
Jim Kayee5133162019-04-22 12:50:27 -0700783 // Broadcast to the listeners that do not signal completion
784 notifyListeners(mPowerManagerListeners, newState);
Serik Beketayev004ce582019-01-27 17:56:26 -0800785
Jim Kayee5133162019-04-22 12:50:27 -0700786 // SHUTDOWN_PREPARE is the only state where we need
787 // to maintain callbacks from listener components.
788 boolean allowCompletion = (newState == CarPowerStateListener.SHUTDOWN_PREPARE);
Serik Beketayev004ce582019-01-27 17:56:26 -0800789
Jim Kayee5133162019-04-22 12:50:27 -0700790 // Fully populate mListenersWeAreWaitingFor before calling any onStateChanged()
791 // for the listeners that signal completion.
792 // Otherwise, if the first listener calls finish() synchronously, we will
793 // see the list go empty and we will think that we are done.
794 boolean haveSomeCompleters = false;
795 PowerManagerCallbackList completingListeners = new PowerManagerCallbackList();
Jim Kayed22f1d62019-12-03 16:08:00 -0800796 synchronized (mLock) {
Jim Kayee5133162019-04-22 12:50:27 -0700797 mListenersWeAreWaitingFor.clear();
798 int idx = mPowerManagerListenersWithCompletion.beginBroadcast();
799 while (idx-- > 0) {
800 ICarPowerStateListener listener =
801 mPowerManagerListenersWithCompletion.getBroadcastItem(idx);
802 completingListeners.register(listener);
803 if (allowCompletion) {
804 mListenersWeAreWaitingFor.add(listener.asBinder());
805 haveSomeCompleters = true;
Serik Beketayev004ce582019-01-27 17:56:26 -0800806 }
807 }
Jim Kayee5133162019-04-22 12:50:27 -0700808 mPowerManagerListenersWithCompletion.finishBroadcast();
809 }
810 // Broadcast to the listeners that DO signal completion
811 notifyListeners(completingListeners, newState);
812
813 if (allowCompletion && !haveSomeCompleters) {
814 // No jobs need to signal completion. So we are now complete.
815 signalComplete();
Serik Beketayev004ce582019-01-27 17:56:26 -0800816 }
817 }
818
Jim Kayee5133162019-04-22 12:50:27 -0700819 private void notifyListeners(PowerManagerCallbackList listenerList, int newState) {
820 int idx = listenerList.beginBroadcast();
821 while (idx-- > 0) {
822 ICarPowerStateListener listener = listenerList.getBroadcastItem(idx);
823 try {
824 listener.onStateChanged(newState);
825 } catch (RemoteException e) {
826 // It's likely the connection snapped. Let binder death handle the situation.
Eric Jeong26f47c72020-07-22 15:45:24 -0700827 Slog.e(TAG, "onStateChanged() call failed", e);
Steve Paik03124082018-02-16 11:19:26 -0800828 }
Steve Paik03124082018-02-16 11:19:26 -0800829 }
Jim Kayee5133162019-04-22 12:50:27 -0700830 listenerList.finishBroadcast();
Steve Paik03124082018-02-16 11:19:26 -0800831 }
832
Jim Kaye4ae10b42019-04-02 11:42:50 -0700833 private void doHandleDeepSleep(boolean simulatedMode) {
Keun-young Park9d4cf622016-08-04 13:24:28 -0700834 // keep holding partial wakelock to prevent entering sleep before enterDeepSleep call
835 // enterDeepSleep should force sleep entry even if wake lock is kept.
836 mSystemInterface.switchToPartialWakeLock();
Keun young Parkb241d022020-04-20 20:31:34 -0700837 mHandler.cancelProcessingComplete();
Jim Kayed22f1d62019-12-03 16:08:00 -0800838 synchronized (mLock) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800839 mLastSleepEntryTime = SystemClock.elapsedRealtime();
840 }
Jim Kaye0ffbf522019-07-01 16:10:40 -0700841 int nextListenerState;
Jim Kaye4ae10b42019-04-02 11:42:50 -0700842 if (simulatedMode) {
Jim Kayed22f1d62019-12-03 16:08:00 -0800843 simulateSleepByWaiting();
Jim Kaye0ffbf522019-07-01 16:10:40 -0700844 nextListenerState = CarPowerStateListener.SHUTDOWN_CANCELLED;
Jim Kayed76c2742019-04-02 11:33:27 -0700845 } else {
Jim Kayeee122fc2020-05-29 09:37:05 -0700846 boolean sleepSucceeded = suspendWithRetries();
Jim Kayed76c2742019-04-02 11:33:27 -0700847 if (!sleepSucceeded) {
Jim Kayeee122fc2020-05-29 09:37:05 -0700848 // Suspend failed and we shut down instead.
849 // We either won't get here at all or we will power off very soon.
Jim Kaye32ea4ce2019-12-03 15:00:51 -0800850 return;
Jim Kayed76c2742019-04-02 11:33:27 -0700851 }
Jim Kayeee122fc2020-05-29 09:37:05 -0700852 // We suspended and have now resumed
Jim Kaye0ffbf522019-07-01 16:10:40 -0700853 nextListenerState = CarPowerStateListener.SUSPEND_EXIT;
Steve Paik0f9fc002018-02-09 17:42:00 -0800854 }
Jim Kayed22f1d62019-12-03 16:08:00 -0800855 synchronized (mLock) {
856 mIsResuming = true;
Jim Kayeee122fc2020-05-29 09:37:05 -0700857 // Any wakeup time from before is no longer valid.
Jim Kayed22f1d62019-12-03 16:08:00 -0800858 mNextWakeupSec = 0;
859 }
Eric Jeong26f47c72020-07-22 15:45:24 -0700860 Slog.i(TAG, "Resuming after suspending");
Serik Beketayev74debf22018-10-04 12:18:09 -0700861 mSystemInterface.refreshDisplayBrightness();
Jim Kaye0ffbf522019-07-01 16:10:40 -0700862 onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, nextListenerState);
keunyoung4b0212c2015-10-29 17:11:57 -0700863 }
864
Jim Kaye24ddc862020-04-30 14:05:17 -0700865 private boolean needPowerStateChangeLocked(@NonNull CpmsState newState) {
866 if (mCurrentState == null) {
keunyoung4b0212c2015-10-29 17:11:57 -0700867 return true;
Steve Paik07db5ed2018-09-24 16:48:52 -0700868 } else if (mCurrentState.equals(newState)) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700869 Slog.d(TAG, "Requested state is already in effect: " + newState.name());
Steve Paik07db5ed2018-09-24 16:48:52 -0700870 return false;
871 }
872
873 // The following switch/case enforces the allowed state transitions.
Jim Kaye24ddc862020-04-30 14:05:17 -0700874 boolean transitionAllowed = false;
Steve Paik07db5ed2018-09-24 16:48:52 -0700875 switch (mCurrentState.mState) {
876 case CpmsState.WAIT_FOR_VHAL:
Jim Kaye24ddc862020-04-30 14:05:17 -0700877 transitionAllowed = (newState.mState == CpmsState.ON)
Steve Paik07db5ed2018-09-24 16:48:52 -0700878 || (newState.mState == CpmsState.SHUTDOWN_PREPARE);
Jim Kaye24ddc862020-04-30 14:05:17 -0700879 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700880 case CpmsState.SUSPEND:
Jim Kaye24ddc862020-04-30 14:05:17 -0700881 transitionAllowed = newState.mState == CpmsState.WAIT_FOR_VHAL;
882 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700883 case CpmsState.ON:
Jim Kaye24ddc862020-04-30 14:05:17 -0700884 transitionAllowed = (newState.mState == CpmsState.SHUTDOWN_PREPARE)
Jim Kayed76c2742019-04-02 11:33:27 -0700885 || (newState.mState == CpmsState.SIMULATE_SLEEP);
Jim Kaye24ddc862020-04-30 14:05:17 -0700886 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700887 case CpmsState.SHUTDOWN_PREPARE:
Jim Kaye49fbfd02019-10-09 09:45:18 -0700888 // If VHAL sends SHUTDOWN_IMMEDIATELY or SLEEP_IMMEDIATELY while in
889 // SHUTDOWN_PREPARE state, do it.
Jim Kaye24ddc862020-04-30 14:05:17 -0700890 transitionAllowed =
891 ((newState.mState == CpmsState.SHUTDOWN_PREPARE) && !newState.mCanPostpone)
892 || (newState.mState == CpmsState.WAIT_FOR_FINISH)
893 || (newState.mState == CpmsState.WAIT_FOR_VHAL);
894 break;
Jim Kayed76c2742019-04-02 11:33:27 -0700895 case CpmsState.SIMULATE_SLEEP:
Jim Kaye24ddc862020-04-30 14:05:17 -0700896 transitionAllowed = true;
897 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700898 case CpmsState.WAIT_FOR_FINISH:
Jim Kaye24ddc862020-04-30 14:05:17 -0700899 transitionAllowed = (newState.mState == CpmsState.SUSPEND
Jim Kaye78a1bce2020-04-16 15:33:45 -0700900 || newState.mState == CpmsState.WAIT_FOR_VHAL);
Jim Kaye24ddc862020-04-30 14:05:17 -0700901 break;
Steve Paik07db5ed2018-09-24 16:48:52 -0700902 default:
Eric Jeong26f47c72020-07-22 15:45:24 -0700903 Slog.e(TAG, "Unexpected current state: currentState="
Jim Kayed76c2742019-04-02 11:33:27 -0700904 + mCurrentState.name() + ", newState=" + newState.name());
Jim Kaye24ddc862020-04-30 14:05:17 -0700905 transitionAllowed = true;
keunyoung4b0212c2015-10-29 17:11:57 -0700906 }
Jim Kaye24ddc862020-04-30 14:05:17 -0700907 if (!transitionAllowed) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700908 Slog.e(TAG, "Requested power transition is not allowed: "
Jim Kaye24ddc862020-04-30 14:05:17 -0700909 + mCurrentState.name() + " --> " + newState.name());
910 }
911 return transitionAllowed;
keunyoung4b0212c2015-10-29 17:11:57 -0700912 }
913
Steve Paik07db5ed2018-09-24 16:48:52 -0700914 private void doHandleProcessingComplete() {
Jim Kayed22f1d62019-12-03 16:08:00 -0800915 int listenerState;
916 synchronized (mLock) {
keunyoung4b0212c2015-10-29 17:11:57 -0700917 releaseTimerLocked();
Steve Paik07db5ed2018-09-24 16:48:52 -0700918 if (!mShutdownOnFinish && mLastSleepEntryTime > mProcessingStartTime) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800919 // entered sleep after processing start. So this could be duplicate request.
Eric Jeong26f47c72020-07-22 15:45:24 -0700920 Slog.w(TAG, "Duplicate sleep entry request, ignore");
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800921 return;
922 }
Jim Kayed22f1d62019-12-03 16:08:00 -0800923 listenerState = mShutdownOnFinish
924 ? CarPowerStateListener.SHUTDOWN_ENTER : CarPowerStateListener.SUSPEND_ENTER;
keunyoung4b0212c2015-10-29 17:11:57 -0700925 }
keunyoung4b0212c2015-10-29 17:11:57 -0700926
Jim Kayed22f1d62019-12-03 16:08:00 -0800927 onApPowerStateChange(CpmsState.WAIT_FOR_FINISH, listenerState);
keunyoung4b0212c2015-10-29 17:11:57 -0700928 }
929
930 @Override
931 public void onDisplayBrightnessChange(int brightness) {
Keun young Parkb241d022020-04-20 20:31:34 -0700932 mHandler.handleDisplayBrightnessChange(brightness);
keunyoung4b0212c2015-10-29 17:11:57 -0700933 }
934
935 private void doHandleDisplayBrightnessChange(int brightness) {
Steve Paik87b36fd2018-03-13 19:25:47 -0700936 mSystemInterface.setDisplayBrightness(brightness);
keunyoung4b0212c2015-10-29 17:11:57 -0700937 }
938
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800939 private void doHandleMainDisplayStateChange(boolean on) {
Eric Jeong26f47c72020-07-22 15:45:24 -0700940 Slog.w(TAG, "Unimplemented: doHandleMainDisplayStateChange() - on = " + on);
keunyoung4b0212c2015-10-29 17:11:57 -0700941 }
942
Eric Jeongbc351e22020-07-31 13:54:17 -0700943 /**
944 * Handles when a main display changes.
945 */
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800946 public void handleMainDisplayChanged(boolean on) {
Keun young Parkb241d022020-04-20 20:31:34 -0700947 mHandler.handleMainDisplayStateChange(on);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800948 }
949
Steve Paik47cdf7b2018-03-16 17:27:43 -0700950 /**
951 * Send display brightness to VHAL.
952 * @param brightness value 0-100%
953 */
954 public void sendDisplayBrightness(int brightness) {
955 mHal.sendDisplayBrightness(brightness);
956 }
957
Jim Kayed22f1d62019-12-03 16:08:00 -0800958 /**
959 * Get the PowerHandler that we use to change power states
960 */
961 public Handler getHandler() {
Keun young Parkb241d022020-04-20 20:31:34 -0700962 return mHandler;
963
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800964 }
965
Jim Kayee5133162019-04-22 12:50:27 -0700966 // Binder interface for general use.
967 // The listener is not required (or allowed) to call finished().
Steve Paik388d7772018-02-12 10:54:51 -0800968 @Override
969 public void registerListener(ICarPowerStateListener listener) {
970 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Steve Paik03124082018-02-16 11:19:26 -0800971 mPowerManagerListeners.register(listener);
Jim Kayee5133162019-04-22 12:50:27 -0700972 }
973
974 // Binder interface for Car services only.
975 // After the listener completes its processing, it must call finished().
976 @Override
977 public void registerListenerWithCompletion(ICarPowerStateListener listener) {
978 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Keun young Parkaabecd92019-05-03 17:31:27 -0700979 ICarImpl.assertCallingFromSystemProcessOrSelf();
Jim Kayee5133162019-04-22 12:50:27 -0700980
981 mPowerManagerListenersWithCompletion.register(listener);
982 // TODO: Need to send current state to newly registered listener? If so, need to handle
983 // completion for SHUTDOWN_PREPARE state
Steve Paik388d7772018-02-12 10:54:51 -0800984 }
985
986 @Override
987 public void unregisterListener(ICarPowerStateListener listener) {
988 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Steve Paik03124082018-02-16 11:19:26 -0800989 doUnregisterListener(listener);
990 }
991
992 private void doUnregisterListener(ICarPowerStateListener listener) {
Jim Kayee5133162019-04-22 12:50:27 -0700993 mPowerManagerListeners.unregister(listener);
994 boolean found = mPowerManagerListenersWithCompletion.unregister(listener);
Steve Paik03124082018-02-16 11:19:26 -0800995 if (found) {
Jim Kayee5133162019-04-22 12:50:27 -0700996 // Remove this from the completion list (if it's there)
997 finishedImpl(listener.asBinder());
Steve Paik03124082018-02-16 11:19:26 -0800998 }
Steve Paik388d7772018-02-12 10:54:51 -0800999 }
1000
1001 @Override
1002 public void requestShutdownOnNextSuspend() {
1003 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Jim Kayed22f1d62019-12-03 16:08:00 -08001004 synchronized (mLock) {
Jim Kayedab62d82019-12-18 14:52:19 -08001005 mShutdownOnNextSuspend = true;
Jim Kayed22f1d62019-12-03 16:08:00 -08001006 }
Steve Paik388d7772018-02-12 10:54:51 -08001007 }
1008
1009 @Override
Jim Kayee5133162019-04-22 12:50:27 -07001010 public void finished(ICarPowerStateListener listener) {
Steve Paik388d7772018-02-12 10:54:51 -08001011 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Keun young Parkaabecd92019-05-03 17:31:27 -07001012 ICarImpl.assertCallingFromSystemProcessOrSelf();
Jim Kayee5133162019-04-22 12:50:27 -07001013 finishedImpl(listener.asBinder());
Steve Paik03124082018-02-16 11:19:26 -08001014 }
1015
Serik Beketayev6e4c7822018-08-27 08:20:09 -07001016 @Override
Jim Kayed22f1d62019-12-03 16:08:00 -08001017 public void scheduleNextWakeupTime(int seconds) {
Jim Kaye1842e822020-05-04 13:08:45 -07001018 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
Serik Beketayev6e4c7822018-08-27 08:20:09 -07001019 if (seconds < 0) {
Eric Jeong26f47c72020-07-22 15:45:24 -07001020 Slog.w(TAG, "Next wake up time is negative. Ignoring!");
Serik Beketayev6e4c7822018-08-27 08:20:09 -07001021 return;
1022 }
Jim Kayed22f1d62019-12-03 16:08:00 -08001023 boolean timedWakeupAllowed = mHal.isTimedWakeupAllowed();
1024 synchronized (mLock) {
1025 if (!timedWakeupAllowed) {
Eric Jeong26f47c72020-07-22 15:45:24 -07001026 Slog.w(TAG, "Setting timed wakeups are disabled in HAL. Skipping");
Jim Kayed22f1d62019-12-03 16:08:00 -08001027 mNextWakeupSec = 0;
1028 return;
1029 }
1030 if (mNextWakeupSec == 0 || mNextWakeupSec > seconds) {
1031 // The new value is sooner than the old value. Take the new value.
1032 mNextWakeupSec = seconds;
1033 } else {
Eric Jeong26f47c72020-07-22 15:45:24 -07001034 Slog.d(TAG, "Tried to schedule next wake up, but already had shorter "
Jim Kayed22f1d62019-12-03 16:08:00 -08001035 + "scheduled time");
1036 }
Serik Beketayev6e4c7822018-08-27 08:20:09 -07001037 }
1038 }
1039
Jim Kaye1842e822020-05-04 13:08:45 -07001040 @Override
1041 public int getPowerState() {
1042 ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
1043 synchronized (mLock) {
1044 return (mCurrentState == null) ? CarPowerStateListener.INVALID
1045 : mCurrentState.mCarPowerStateListenerState;
1046 }
1047 }
1048
Jim Kayee5133162019-04-22 12:50:27 -07001049 private void finishedImpl(IBinder binder) {
Jim Kaye9889f282020-05-28 09:17:17 -07001050 boolean allAreComplete;
Jim Kayed22f1d62019-12-03 16:08:00 -08001051 synchronized (mLock) {
Jim Kaye9889f282020-05-28 09:17:17 -07001052 mListenersWeAreWaitingFor.remove(binder);
1053 allAreComplete = mListenersWeAreWaitingFor.isEmpty();
Jim Kayee5133162019-04-22 12:50:27 -07001054 }
1055 if (allAreComplete) {
1056 signalComplete();
1057 }
1058 }
1059
1060 private void signalComplete() {
1061 if (mCurrentState.mState == CpmsState.SHUTDOWN_PREPARE
1062 || mCurrentState.mState == CpmsState.SIMULATE_SLEEP) {
1063 PowerHandler powerHandler;
1064 // All apps are ready to shutdown/suspend.
Jim Kayed22f1d62019-12-03 16:08:00 -08001065 synchronized (mLock) {
Jim Kayee5133162019-04-22 12:50:27 -07001066 if (!mShutdownOnFinish) {
1067 if (mLastSleepEntryTime > mProcessingStartTime
1068 && mLastSleepEntryTime < SystemClock.elapsedRealtime()) {
Eric Jeong26f47c72020-07-22 15:45:24 -07001069 Slog.i(TAG, "signalComplete: Already slept!");
Jim Kayee5133162019-04-22 12:50:27 -07001070 return;
Steve Paik07db5ed2018-09-24 16:48:52 -07001071 }
Steve Paik07db5ed2018-09-24 16:48:52 -07001072 }
Jim Kayee5133162019-04-22 12:50:27 -07001073 powerHandler = mHandler;
Steve Paik03124082018-02-16 11:19:26 -08001074 }
Eric Jeong26f47c72020-07-22 15:45:24 -07001075 Slog.i(TAG, "Apps are finished, call handleProcessingComplete()");
Jim Kayee5133162019-04-22 12:50:27 -07001076 powerHandler.handleProcessingComplete();
Steve Paik03124082018-02-16 11:19:26 -08001077 }
Steve Paik388d7772018-02-12 10:54:51 -08001078 }
1079
Keun young Parkb241d022020-04-20 20:31:34 -07001080 private static final class PowerHandler extends Handler {
1081 private static final String TAG = PowerHandler.class.getSimpleName();
Eric Jeongbc351e22020-07-31 13:54:17 -07001082 private static final int MSG_POWER_STATE_CHANGE = 0;
1083 private static final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1;
1084 private static final int MSG_MAIN_DISPLAY_STATE_CHANGE = 2;
1085 private static final int MSG_PROCESSING_COMPLETE = 3;
keunyoung4b0212c2015-10-29 17:11:57 -07001086
1087 // Do not handle this immediately but with some delay as there can be a race between
1088 // display off due to rear view camera and delivery to here.
Eric Jeongbc351e22020-07-31 13:54:17 -07001089 private static final long MAIN_DISPLAY_EVENT_DELAY_MS = 500;
keunyoung4b0212c2015-10-29 17:11:57 -07001090
Keun young Parkb241d022020-04-20 20:31:34 -07001091 private final WeakReference<CarPowerManagementService> mService;
1092
1093 private PowerHandler(Looper looper, CarPowerManagementService service) {
keunyoung4b0212c2015-10-29 17:11:57 -07001094 super(looper);
Keun young Parkb241d022020-04-20 20:31:34 -07001095 mService = new WeakReference<CarPowerManagementService>(service);
keunyoung4b0212c2015-10-29 17:11:57 -07001096 }
1097
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001098 private void handlePowerStateChange() {
1099 Message msg = obtainMessage(MSG_POWER_STATE_CHANGE);
keunyoung4b0212c2015-10-29 17:11:57 -07001100 sendMessage(msg);
1101 }
1102
1103 private void handleDisplayBrightnessChange(int brightness) {
1104 Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, brightness, 0);
1105 sendMessage(msg);
1106 }
1107
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001108 private void handleMainDisplayStateChange(boolean on) {
keunyoung4b0212c2015-10-29 17:11:57 -07001109 removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001110 Message msg = obtainMessage(MSG_MAIN_DISPLAY_STATE_CHANGE, Boolean.valueOf(on));
keunyoung4b0212c2015-10-29 17:11:57 -07001111 sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS);
1112 }
1113
Steve Paik07db5ed2018-09-24 16:48:52 -07001114 private void handleProcessingComplete() {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001115 removeMessages(MSG_PROCESSING_COMPLETE);
Steve Paik07db5ed2018-09-24 16:48:52 -07001116 Message msg = obtainMessage(MSG_PROCESSING_COMPLETE);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001117 sendMessage(msg);
1118 }
1119
1120 private void cancelProcessingComplete() {
1121 removeMessages(MSG_PROCESSING_COMPLETE);
1122 }
1123
keunyoung4b0212c2015-10-29 17:11:57 -07001124 private void cancelAll() {
1125 removeMessages(MSG_POWER_STATE_CHANGE);
1126 removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE);
1127 removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
1128 removeMessages(MSG_PROCESSING_COMPLETE);
1129 }
1130
1131 @Override
1132 public void handleMessage(Message msg) {
Keun young Parkb241d022020-04-20 20:31:34 -07001133 CarPowerManagementService service = mService.get();
1134 if (service == null) {
Eric Jeong26f47c72020-07-22 15:45:24 -07001135 Slog.i(TAG, "handleMessage null service");
Keun young Parkb241d022020-04-20 20:31:34 -07001136 return;
1137 }
keunyoung4b0212c2015-10-29 17:11:57 -07001138 switch (msg.what) {
1139 case MSG_POWER_STATE_CHANGE:
Keun young Parkb241d022020-04-20 20:31:34 -07001140 service.doHandlePowerStateChange();
keunyoung4b0212c2015-10-29 17:11:57 -07001141 break;
1142 case MSG_DISPLAY_BRIGHTNESS_CHANGE:
Keun young Parkb241d022020-04-20 20:31:34 -07001143 service.doHandleDisplayBrightnessChange(msg.arg1);
keunyoung4b0212c2015-10-29 17:11:57 -07001144 break;
1145 case MSG_MAIN_DISPLAY_STATE_CHANGE:
Keun young Parkb241d022020-04-20 20:31:34 -07001146 service.doHandleMainDisplayStateChange((Boolean) msg.obj);
Keun-young Park1f4d6a72016-02-11 09:49:47 -08001147 break;
keunyoung4b0212c2015-10-29 17:11:57 -07001148 case MSG_PROCESSING_COMPLETE:
Keun young Parkb241d022020-04-20 20:31:34 -07001149 service.doHandleProcessingComplete();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -08001150 break;
keunyoung4b0212c2015-10-29 17:11:57 -07001151 }
1152 }
1153 }
1154
keunyoung4b0212c2015-10-29 17:11:57 -07001155 private class ShutdownProcessingTimerTask extends TimerTask {
keunyoung4b0212c2015-10-29 17:11:57 -07001156 private final int mExpirationCount;
1157 private int mCurrentCount;
1158
Steve Paik07db5ed2018-09-24 16:48:52 -07001159 private ShutdownProcessingTimerTask(int expirationCount) {
keunyoung4b0212c2015-10-29 17:11:57 -07001160 mExpirationCount = expirationCount;
1161 mCurrentCount = 0;
1162 }
1163
1164 @Override
1165 public void run() {
Jim Kayed22f1d62019-12-03 16:08:00 -08001166 synchronized (mLock) {
Serik Beketayevf8287a02019-02-08 12:31:10 -08001167 if (!mTimerActive) {
1168 // Ignore timer expiration since we got cancelled
1169 return;
1170 }
1171 mCurrentCount++;
1172 if (mCurrentCount > mExpirationCount) {
1173 PowerHandler handler;
keunyoung4b0212c2015-10-29 17:11:57 -07001174 releaseTimerLocked();
Pavel Maltsevddbff982017-03-22 14:49:02 -07001175 handler = mHandler;
Serik Beketayevf8287a02019-02-08 12:31:10 -08001176 handler.handleProcessingComplete();
1177 } else {
1178 mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS);
keunyoung4b0212c2015-10-29 17:11:57 -07001179 }
keunyoung4b0212c2015-10-29 17:11:57 -07001180 }
1181 }
1182 }
Steve Paik07db5ed2018-09-24 16:48:52 -07001183
Jim Kayeee122fc2020-05-29 09:37:05 -07001184 // Send the command to enter Suspend to RAM.
1185 // If the command is not successful, try again.
1186 // If it fails repeatedly, send the command to shut down.
Jim Kayea94bb8b2020-07-28 09:42:35 -07001187 // If we decide to go to a different power state, abort this
1188 // retry mechanism.
Jim Kayeee122fc2020-05-29 09:37:05 -07001189 // Returns true if we successfully suspended.
1190 private boolean suspendWithRetries() {
Jim Kayea94bb8b2020-07-28 09:42:35 -07001191 final int maxTries = 9; // 0, 10, 20, ..., 1280 msec
1192 final long initialRetryIntervalMs = 10;
1193 long retryIntervalMs = initialRetryIntervalMs;
Jim Kayeee122fc2020-05-29 09:37:05 -07001194 int tryCount = 0;
1195
1196 while (true) {
Eric Jeong26f47c72020-07-22 15:45:24 -07001197 Slog.i(TAG, "Entering Suspend to RAM");
Jim Kayeee122fc2020-05-29 09:37:05 -07001198 boolean suspendSucceeded = mSystemInterface.enterDeepSleep();
1199 if (suspendSucceeded) {
1200 return true;
1201 }
1202 tryCount++;
1203 if (tryCount >= maxTries) {
1204 break;
1205 }
1206 // We failed to suspend. Block the thread briefly and try again.
Jim Kayea94bb8b2020-07-28 09:42:35 -07001207 synchronized (mLock) {
1208 if (mPendingPowerStates.isEmpty()) {
1209 Slog.w(TAG, "Failed to Suspend; will retry later.");
1210 try {
1211 mLock.wait(retryIntervalMs);
1212 } catch (InterruptedException ignored) { }
1213 retryIntervalMs *= 2;
1214 }
1215 // Check for a new power state now, before going around the loop again
1216 if (!mPendingPowerStates.isEmpty()) {
1217 Slog.i(TAG, "Terminating the attempt to Suspend to RAM");
1218 return false;
1219 }
1220 }
Jim Kayeee122fc2020-05-29 09:37:05 -07001221 }
1222 // Too many failures trying to suspend. Shut down.
Eric Jeong26f47c72020-07-22 15:45:24 -07001223 Slog.w(TAG, "Could not Suspend to RAM. Shutting down.");
Jim Kayeee122fc2020-05-29 09:37:05 -07001224 mSystemInterface.shutdown();
1225 return false;
1226 }
1227
Steve Paik07db5ed2018-09-24 16:48:52 -07001228 private static class CpmsState {
Yuncheol Heoe6e03472019-05-08 18:24:45 -07001229 // NOTE: When modifying states below, make sure to update CarPowerStateChanged.State in
1230 // frameworks/base/cmds/statsd/src/atoms.proto also.
Steve Paik07db5ed2018-09-24 16:48:52 -07001231 public static final int WAIT_FOR_VHAL = 0;
1232 public static final int ON = 1;
1233 public static final int SHUTDOWN_PREPARE = 2;
1234 public static final int WAIT_FOR_FINISH = 3;
1235 public static final int SUSPEND = 4;
Jim Kayed76c2742019-04-02 11:33:27 -07001236 public static final int SIMULATE_SLEEP = 5;
Steve Paik07db5ed2018-09-24 16:48:52 -07001237
1238 /* Config values from AP_POWER_STATE_REQ */
1239 public final boolean mCanPostpone;
1240 public final boolean mCanSleep;
1241 /* Message sent to CarPowerStateListener in response to this state */
1242 public final int mCarPowerStateListenerState;
1243 /* One of the above state variables */
1244 public final int mState;
1245
1246 /**
1247 * This constructor takes a PowerHalService.PowerState object and creates the corresponding
1248 * CPMS state from it.
1249 */
1250 CpmsState(PowerState halPowerState) {
1251 switch (halPowerState.mState) {
1252 case VehicleApPowerStateReq.ON:
1253 this.mCanPostpone = false;
1254 this.mCanSleep = false;
1255 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(ON);
1256 this.mState = ON;
1257 break;
1258 case VehicleApPowerStateReq.SHUTDOWN_PREPARE:
1259 this.mCanPostpone = halPowerState.canPostponeShutdown();
1260 this.mCanSleep = halPowerState.canEnterDeepSleep();
1261 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(
1262 SHUTDOWN_PREPARE);
1263 this.mState = SHUTDOWN_PREPARE;
1264 break;
1265 case VehicleApPowerStateReq.CANCEL_SHUTDOWN:
1266 this.mCanPostpone = false;
1267 this.mCanSleep = false;
1268 this.mCarPowerStateListenerState = CarPowerStateListener.SHUTDOWN_CANCELLED;
1269 this.mState = WAIT_FOR_VHAL;
1270 break;
1271 case VehicleApPowerStateReq.FINISHED:
1272 this.mCanPostpone = false;
1273 this.mCanSleep = false;
1274 this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(SUSPEND);
1275 this.mState = SUSPEND;
1276 break;
1277 default:
1278 // Illegal state from PowerState. Throw an exception?
1279 this.mCanPostpone = false;
1280 this.mCanSleep = false;
1281 this.mCarPowerStateListenerState = 0;
1282 this.mState = 0;
1283 break;
1284 }
1285 }
1286
1287 CpmsState(int state) {
1288 this(state, cpmsStateToPowerStateListenerState(state));
1289 }
1290
1291 CpmsState(int state, int carPowerStateListenerState) {
Jim Kayed76c2742019-04-02 11:33:27 -07001292 this.mCanPostpone = (state == SIMULATE_SLEEP);
1293 this.mCanSleep = (state == SIMULATE_SLEEP);
Steve Paik07db5ed2018-09-24 16:48:52 -07001294 this.mCarPowerStateListenerState = carPowerStateListenerState;
1295 this.mState = state;
1296 }
1297
Jim Kayed76c2742019-04-02 11:33:27 -07001298 public String name() {
1299 String baseName;
1300 switch(mState) {
1301 case WAIT_FOR_VHAL: baseName = "WAIT_FOR_VHAL"; break;
1302 case ON: baseName = "ON"; break;
1303 case SHUTDOWN_PREPARE: baseName = "SHUTDOWN_PREPARE"; break;
1304 case WAIT_FOR_FINISH: baseName = "WAIT_FOR_FINISH"; break;
1305 case SUSPEND: baseName = "SUSPEND"; break;
1306 case SIMULATE_SLEEP: baseName = "SIMULATE_SLEEP"; break;
1307 default: baseName = "<unknown>"; break;
1308 }
1309 return baseName + "(" + mState + ")";
1310 }
1311
Steve Paik07db5ed2018-09-24 16:48:52 -07001312 private static int cpmsStateToPowerStateListenerState(int state) {
1313 int powerStateListenerState = 0;
1314
1315 // Set the CarPowerStateListenerState based on current state
1316 switch (state) {
1317 case ON:
1318 powerStateListenerState = CarPowerStateListener.ON;
1319 break;
1320 case SHUTDOWN_PREPARE:
1321 powerStateListenerState = CarPowerStateListener.SHUTDOWN_PREPARE;
1322 break;
1323 case SUSPEND:
1324 powerStateListenerState = CarPowerStateListener.SUSPEND_ENTER;
1325 break;
1326 case WAIT_FOR_VHAL:
1327 case WAIT_FOR_FINISH:
1328 default:
1329 // Illegal state for this constructor. Throw an exception?
1330 break;
1331 }
1332 return powerStateListenerState;
1333 }
1334
1335 @Override
1336 public boolean equals(Object o) {
1337 if (this == o) {
1338 return true;
1339 }
1340 if (!(o instanceof CpmsState)) {
1341 return false;
1342 }
1343 CpmsState that = (CpmsState) o;
1344 return this.mState == that.mState
1345 && this.mCanSleep == that.mCanSleep
1346 && this.mCanPostpone == that.mCanPostpone
1347 && this.mCarPowerStateListenerState == that.mCarPowerStateListenerState;
1348 }
1349
1350 @Override
1351 public String toString() {
1352 return "CpmsState canSleep:" + mCanSleep + ", canPostpone=" + mCanPostpone
1353 + ", carPowerStateListenerState=" + mCarPowerStateListenerState
Jim Kayed76c2742019-04-02 11:33:27 -07001354 + ", CpmsState=" + this.name();
Steve Paik07db5ed2018-09-24 16:48:52 -07001355 }
1356 }
1357
Jim Kayed76c2742019-04-02 11:33:27 -07001358 /**
1359 * Resume after a manually-invoked suspend.
1360 * Invoked using "adb shell dumpsys activity service com.android.car resume".
1361 */
1362 public void forceSimulatedResume() {
Jim Kaye0ffbf522019-07-01 16:10:40 -07001363 PowerHandler handler;
Jim Kayed22f1d62019-12-03 16:08:00 -08001364 synchronized (mLock) {
Jim Kaye0ffbf522019-07-01 16:10:40 -07001365 // Cancel Garage Mode in case it's running
1366 mPendingPowerStates.addFirst(new CpmsState(CpmsState.WAIT_FOR_VHAL,
1367 CarPowerStateListener.SHUTDOWN_CANCELLED));
Jim Kayea94bb8b2020-07-28 09:42:35 -07001368 mLock.notify();
Jim Kaye0ffbf522019-07-01 16:10:40 -07001369 handler = mHandler;
1370 }
1371 handler.handlePowerStateChange();
1372
Jim Kayed22f1d62019-12-03 16:08:00 -08001373 synchronized (mSimulationWaitObject) {
Jim Kaye4ae10b42019-04-02 11:42:50 -07001374 mWakeFromSimulatedSleep = true;
Jim Kayed22f1d62019-12-03 16:08:00 -08001375 mSimulationWaitObject.notify();
Jim Kayed76c2742019-04-02 11:33:27 -07001376 }
1377 }
1378
1379 /**
Jim Kaye9a834ea2020-02-07 15:50:53 -08001380 * Manually enter simulated suspend (Deep Sleep) mode, trigging Garage mode.
1381 * If the parameter is 'true', reboot the system when Garage Mode completes.
1382 *
1383 * Invoked using "adb shell dumpsys activity service com.android.car suspend" or
1384 * "adb shell dumpsys activity service com.android.car garage-mode reboot".
Jim Kayed76c2742019-04-02 11:33:27 -07001385 * This is similar to 'onApPowerStateChange()' except that it needs to create a CpmsState
1386 * that is not directly derived from a VehicleApPowerStateReq.
1387 */
Eric Jeongbc351e22020-07-31 13:54:17 -07001388 public void forceSuspendAndMaybeReboot(boolean shouldReboot) {
Jim Kayed22f1d62019-12-03 16:08:00 -08001389 synchronized (mSimulationWaitObject) {
Jim Kaye4ae10b42019-04-02 11:42:50 -07001390 mInSimulatedDeepSleepMode = true;
1391 mWakeFromSimulatedSleep = false;
Jim Kaye9889f282020-05-28 09:17:17 -07001392 mGarageModeShouldExitImmediately = false;
Jim Kayed76c2742019-04-02 11:33:27 -07001393 }
1394 PowerHandler handler;
Jim Kayed22f1d62019-12-03 16:08:00 -08001395 synchronized (mLock) {
Jim Kaye9a834ea2020-02-07 15:50:53 -08001396 mRebootAfterGarageMode = shouldReboot;
Jim Kayed76c2742019-04-02 11:33:27 -07001397 mPendingPowerStates.addFirst(new CpmsState(CpmsState.SIMULATE_SLEEP,
1398 CarPowerStateListener.SHUTDOWN_PREPARE));
1399 handler = mHandler;
1400 }
1401 handler.handlePowerStateChange();
1402 }
1403
1404 // In a real Deep Sleep, the hardware removes power from the CPU (but retains power
1405 // on the RAM). This puts the processor to sleep. Upon some external signal, power
1406 // is re-applied to the CPU, and processing resumes right where it left off.
Jim Kayed22f1d62019-12-03 16:08:00 -08001407 // We simulate this behavior by calling wait().
1408 // We continue from wait() when forceSimulatedResume() is called.
1409 private void simulateSleepByWaiting() {
Eric Jeong26f47c72020-07-22 15:45:24 -07001410 Slog.i(TAG, "Starting to simulate Deep Sleep by waiting");
Jim Kayed22f1d62019-12-03 16:08:00 -08001411 synchronized (mSimulationWaitObject) {
Jim Kaye4ae10b42019-04-02 11:42:50 -07001412 while (!mWakeFromSimulatedSleep) {
Jim Kayed76c2742019-04-02 11:33:27 -07001413 try {
Jim Kayed22f1d62019-12-03 16:08:00 -08001414 mSimulationWaitObject.wait();
Jim Kayed76c2742019-04-02 11:33:27 -07001415 } catch (InterruptedException ignored) {
Jim Kayed22f1d62019-12-03 16:08:00 -08001416 Thread.currentThread().interrupt(); // Restore interrupted status
Jim Kayed76c2742019-04-02 11:33:27 -07001417 }
1418 }
Jim Kaye4ae10b42019-04-02 11:42:50 -07001419 mInSimulatedDeepSleepMode = false;
Jim Kayed76c2742019-04-02 11:33:27 -07001420 }
Eric Jeong26f47c72020-07-22 15:45:24 -07001421 Slog.i(TAG, "Exit Deep Sleep simulation");
Jim Kayed76c2742019-04-02 11:33:27 -07001422 }
keunyoung4b0212c2015-10-29 17:11:57 -07001423}