blob: 3f58c72cbdc23833a1344ef80e700c109232a5b8 [file] [log] [blame]
Dianne Hackborn0b4daca2015-04-27 09:47:32 -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 */
16
17package com.android.server;
18
Amith Yamasaniaf575b92015-05-29 15:35:26 -070019import android.Manifest;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080020import android.app.ActivityManager;
Dianne Hackborn85e35642017-01-12 15:10:57 -080021import android.app.ActivityManagerInternal;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070022import android.app.AlarmManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070023import android.content.BroadcastReceiver;
Adam Lesinski31c05d12015-06-09 17:34:04 -070024import android.content.ContentResolver;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070025import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.pm.ApplicationInfo;
29import android.content.pm.PackageManager;
Amith Yamasaniaf575b92015-05-29 15:35:26 -070030import android.content.pm.PackageManager.NameNotFoundException;
Adam Lesinski31c05d12015-06-09 17:34:04 -070031import android.database.ContentObserver;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070032import android.hardware.Sensor;
Nick Vaccaro20feaea2015-09-17 17:22:44 -070033import android.hardware.SensorEvent;
34import android.hardware.SensorEventListener;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070035import android.hardware.SensorManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070036import android.hardware.TriggerEvent;
37import android.hardware.TriggerEventListener;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -070038import android.location.Location;
39import android.location.LocationListener;
40import android.location.LocationManager;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070041import android.location.LocationRequest;
Dianne Hackborn88c41352016-04-07 15:18:58 -070042import android.net.ConnectivityManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070043import android.net.INetworkPolicyManager;
Dianne Hackborn88c41352016-04-07 15:18:58 -070044import android.net.NetworkInfo;
Adam Lesinski31c05d12015-06-09 17:34:04 -070045import android.net.Uri;
Robin Lee204cb222018-12-07 15:17:44 +010046import android.os.BatteryManager;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070047import android.os.BatteryStats;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070048import android.os.Binder;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -070049import android.os.Bundle;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070050import android.os.Environment;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070051import android.os.Handler;
52import android.os.IDeviceIdleController;
53import android.os.Looper;
54import android.os.Message;
55import android.os.PowerManager;
Kweku Adamsb396ccf2018-09-17 16:37:15 -070056import android.os.PowerManager.ServiceType;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070057import android.os.PowerManagerInternal;
Dianne Hackbornb6683c42015-06-18 17:40:33 -070058import android.os.Process;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070059import android.os.RemoteException;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -070060import android.os.ResultReceiver;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070061import android.os.ServiceManager;
Dianne Hackborn354736e2016-08-22 17:00:05 -070062import android.os.ShellCallback;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -070063import android.os.ShellCommand;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070064import android.os.SystemClock;
65import android.os.UserHandle;
Adam Lesinski31c05d12015-06-09 17:34:04 -070066import android.provider.Settings;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070067import android.util.ArrayMap;
68import android.util.ArraySet;
Makoto Onuki7ed0cad2019-09-04 16:06:51 -070069import android.util.AtomicFile;
Adam Lesinski31c05d12015-06-09 17:34:04 -070070import android.util.KeyValueListParser;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070071import android.util.MutableLong;
72import android.util.Pair;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070073import android.util.Slog;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070074import android.util.SparseArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070075import android.util.SparseBooleanArray;
76import android.util.TimeUtils;
77import android.util.Xml;
Amith Yamasani520d8f22015-05-08 16:36:21 -070078
Sudheer Shanka326b3112017-11-27 14:40:57 -080079import com.android.internal.annotations.GuardedBy;
Kweku Adams00e3a372018-09-28 16:57:09 -070080import com.android.internal.annotations.VisibleForTesting;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070081import com.android.internal.app.IBatteryStats;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070082import com.android.internal.os.BackgroundThread;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060083import com.android.internal.util.DumpUtils;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070084import com.android.internal.util.FastXmlSerializer;
85import com.android.internal.util.XmlUtils;
86import com.android.server.am.BatteryStatsService;
Robin Lee876b88542018-11-13 17:22:24 +010087import com.android.server.deviceidle.ConstraintController;
88import com.android.server.deviceidle.DeviceIdleConstraintTracker;
89import com.android.server.deviceidle.IDeviceIdleConstraint;
90import com.android.server.deviceidle.TvConstraintController;
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -070091import com.android.server.net.NetworkPolicyManagerInternal;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070092import com.android.server.wm.ActivityTaskManagerInternal;
Amith Yamasani520d8f22015-05-08 16:36:21 -070093
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070094import org.xmlpull.v1.XmlPullParser;
95import org.xmlpull.v1.XmlPullParserException;
96import org.xmlpull.v1.XmlSerializer;
97
98import java.io.ByteArrayOutputStream;
99import java.io.File;
100import java.io.FileDescriptor;
101import java.io.FileInputStream;
102import java.io.FileNotFoundException;
103import java.io.FileOutputStream;
104import java.io.IOException;
105import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100106import java.nio.charset.StandardCharsets;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700107import java.util.Arrays;
Kweku Adamsc2400c82019-10-09 15:56:04 -0700108import java.util.Collections;
109import java.util.List;
Robin Lee876b88542018-11-13 17:22:24 +0100110import java.util.stream.Collectors;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700111
112/**
113 * Keeps track of device idleness and drives low power mode based on that.
Kweku Adams00e3a372018-09-28 16:57:09 -0700114 *
115 * Test: atest com.android.server.DeviceIdleControllerTest
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700116 *
Kweku Adams3ba574f2019-03-19 12:45:55 -0700117 * Current idling state machine (as of Android Q). This can be visualized using Graphviz:
118 <pre>
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700119
120 digraph {
121 subgraph deep {
122 label="deep";
123
124 STATE_ACTIVE [label="STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon"]
125 STATE_INACTIVE [label="STATE_INACTIVE\nScreen off AND Not charging"]
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700126 STATE_QUICK_DOZE_DELAY [
127 label="STATE_QUICK_DOZE_DELAY\n"
128 + "Screen off AND Not charging\n"
129 + "Location, motion detection, and significant motion monitoring turned off"
130 ]
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700131 STATE_IDLE_PENDING [
132 label="STATE_IDLE_PENDING\nSignificant motion monitoring turned on"
133 ]
134 STATE_SENSING [label="STATE_SENSING\nMonitoring for ANY motion"]
135 STATE_LOCATING [
136 label="STATE_LOCATING\nRequesting location, motion monitoring still on"
137 ]
138 STATE_IDLE [
139 label="STATE_IDLE\nLocation and motion detection turned off\n"
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700140 + "Significant motion monitoring state unchanged"
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700141 ]
142 STATE_IDLE_MAINTENANCE [label="STATE_IDLE_MAINTENANCE\n"]
143
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700144 STATE_ACTIVE -> STATE_INACTIVE [
145 label="becomeInactiveIfAppropriateLocked() AND Quick Doze not enabled"
146 ]
147 STATE_ACTIVE -> STATE_QUICK_DOZE_DELAY [
148 label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
149 ]
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700150
151 STATE_INACTIVE -> STATE_ACTIVE [
152 label="handleMotionDetectedLocked(), becomeActiveLocked()"
153 ]
154 STATE_INACTIVE -> STATE_IDLE_PENDING [label="stepIdleStateLocked()"]
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700155 STATE_INACTIVE -> STATE_QUICK_DOZE_DELAY [
156 label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
157 ]
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700158
159 STATE_IDLE_PENDING -> STATE_ACTIVE [
160 label="handleMotionDetectedLocked(), becomeActiveLocked()"
161 ]
162 STATE_IDLE_PENDING -> STATE_SENSING [label="stepIdleStateLocked()"]
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700163 STATE_IDLE_PENDING -> STATE_QUICK_DOZE_DELAY [
164 label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
165 ]
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700166
167 STATE_SENSING -> STATE_ACTIVE [
168 label="handleMotionDetectedLocked(), becomeActiveLocked()"
169 ]
170 STATE_SENSING -> STATE_LOCATING [label="stepIdleStateLocked()"]
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700171 STATE_SENSING -> STATE_QUICK_DOZE_DELAY [
172 label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
173 ]
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700174 STATE_SENSING -> STATE_IDLE [
175 label="stepIdleStateLocked()\n"
176 + "No Location Manager OR (no Network provider AND no GPS provider)"
177 ]
178
179 STATE_LOCATING -> STATE_ACTIVE [
180 label="handleMotionDetectedLocked(), becomeActiveLocked()"
181 ]
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700182 STATE_LOCATING -> STATE_QUICK_DOZE_DELAY [
183 label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
184 ]
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700185 STATE_LOCATING -> STATE_IDLE [label="stepIdleStateLocked()"]
186
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700187 STATE_QUICK_DOZE_DELAY -> STATE_ACTIVE [
188 label="handleMotionDetectedLocked(), becomeActiveLocked()"
189 ]
190 STATE_QUICK_DOZE_DELAY -> STATE_IDLE [label="stepIdleStateLocked()"]
191
Kweku Adamsf596cfc2018-10-04 15:15:22 -0700192 STATE_IDLE -> STATE_ACTIVE [label="handleMotionDetectedLocked(), becomeActiveLocked()"]
193 STATE_IDLE -> STATE_IDLE_MAINTENANCE [label="stepIdleStateLocked()"]
194
195 STATE_IDLE_MAINTENANCE -> STATE_ACTIVE [
196 label="handleMotionDetectedLocked(), becomeActiveLocked()"
197 ]
198 STATE_IDLE_MAINTENANCE -> STATE_IDLE [
199 label="stepIdleStateLocked(), exitMaintenanceEarlyIfNeededLocked()"
200 ]
201 }
202
203 subgraph light {
204 label="light"
205
206 LIGHT_STATE_ACTIVE [
207 label="LIGHT_STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon"
208 ]
209 LIGHT_STATE_INACTIVE [label="LIGHT_STATE_INACTIVE\nScreen off AND Not charging"]
210 LIGHT_STATE_PRE_IDLE [
211 label="LIGHT_STATE_PRE_IDLE\n"
212 + "Delay going into LIGHT_STATE_IDLE due to some running jobs or alarms"
213 ]
214 LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n"]
215 LIGHT_STATE_WAITING_FOR_NETWORK [
216 label="LIGHT_STATE_WAITING_FOR_NETWORK\n"
217 + "Coming out of LIGHT_STATE_IDLE, waiting for network"
218 ]
219 LIGHT_STATE_IDLE_MAINTENANCE [label="LIGHT_STATE_IDLE_MAINTENANCE\n"]
220 LIGHT_STATE_OVERRIDE [
221 label="LIGHT_STATE_OVERRIDE\nDevice in deep doze, light no longer changing states"
222 ]
223
224 LIGHT_STATE_ACTIVE -> LIGHT_STATE_INACTIVE [
225 label="becomeInactiveIfAppropriateLocked()"
226 ]
227 LIGHT_STATE_ACTIVE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
228
229 LIGHT_STATE_INACTIVE -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
230 LIGHT_STATE_INACTIVE -> LIGHT_STATE_PRE_IDLE [label="active jobs"]
231 LIGHT_STATE_INACTIVE -> LIGHT_STATE_IDLE [label="no active jobs"]
232 LIGHT_STATE_INACTIVE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
233
234 LIGHT_STATE_PRE_IDLE -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
235 LIGHT_STATE_PRE_IDLE -> LIGHT_STATE_IDLE [
236 label="stepLightIdleStateLocked(), exitMaintenanceEarlyIfNeededLocked()"
237 ]
238 LIGHT_STATE_PRE_IDLE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
239
240 LIGHT_STATE_IDLE -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
241 LIGHT_STATE_IDLE -> LIGHT_STATE_WAITING_FOR_NETWORK [label="no network"]
242 LIGHT_STATE_IDLE -> LIGHT_STATE_IDLE_MAINTENANCE
243 LIGHT_STATE_IDLE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
244
245 LIGHT_STATE_WAITING_FOR_NETWORK -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
246 LIGHT_STATE_WAITING_FOR_NETWORK -> LIGHT_STATE_IDLE_MAINTENANCE
247 LIGHT_STATE_WAITING_FOR_NETWORK -> LIGHT_STATE_OVERRIDE [
248 label="deep goes to STATE_IDLE"
249 ]
250
251 LIGHT_STATE_IDLE_MAINTENANCE -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
252 LIGHT_STATE_IDLE_MAINTENANCE -> LIGHT_STATE_IDLE [
253 label="stepLightIdleStateLocked(), exitMaintenanceEarlyIfNeededLocked()"
254 ]
255 LIGHT_STATE_IDLE_MAINTENANCE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
256
257 LIGHT_STATE_OVERRIDE -> LIGHT_STATE_ACTIVE [
258 label="handleMotionDetectedLocked(), becomeActiveLocked()"
259 ]
260 }
261 }
Kweku Adams3ba574f2019-03-19 12:45:55 -0700262 </pre>
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700263 */
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700264public class DeviceIdleController extends SystemService
265 implements AnyMotionDetector.DeviceIdleCallback {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700266 private static final String TAG = "DeviceIdleController";
267
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700268 private static final boolean DEBUG = false;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700269
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700270 private static final boolean COMPRESS_TIME = false;
Amith Yamasani520d8f22015-05-08 16:36:21 -0700271
Dianne Hackborn953fc942016-03-29 15:36:24 -0700272 private static final int EVENT_BUFFER_SIZE = 100;
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800273
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700274 private AlarmManager mAlarmManager;
Kweku Adamsb7ce1902019-01-30 10:55:34 -0800275 private AlarmManagerInternal mLocalAlarmManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700276 private IBatteryStats mBatteryStats;
Dianne Hackborn85e35642017-01-12 15:10:57 -0800277 private ActivityManagerInternal mLocalActivityManager;
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700278 private ActivityTaskManagerInternal mLocalActivityTaskManager;
Kweku Adams810c77d2019-08-28 07:45:00 -0700279 private DeviceIdleInternal mLocalService;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700280 private PowerManagerInternal mLocalPowerManager;
Dianne Hackborn945c9c92016-03-30 14:55:00 -0700281 private PowerManager mPowerManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700282 private INetworkPolicyManager mNetworkPolicyManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700283 private SensorManager mSensorManager;
Robin Leec4d424c2018-12-07 15:09:13 +0100284 private final boolean mUseMotionSensor;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700285 private Sensor mMotionSensor;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700286 private LocationRequest mLocationRequest;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700287 private Intent mIdleIntent;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700288 private Intent mLightIdleIntent;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700289 private AnyMotionDetector mAnyMotionDetector;
Makoto Onukie4918212018-02-06 11:30:15 -0800290 private final AppStateTracker mAppStateTracker;
Dianne Hackbornb6843652016-02-22 12:20:13 -0800291 private boolean mLightEnabled;
292 private boolean mDeepEnabled;
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700293 private boolean mQuickDozeActivated;
Kweku Adams810c77d2019-08-28 07:45:00 -0700294 private boolean mQuickDozeActivatedWhileIdling;
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700295 private boolean mForceIdle;
Dianne Hackborn88c41352016-04-07 15:18:58 -0700296 private boolean mNetworkConnected;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700297 private boolean mScreenOn;
298 private boolean mCharging;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700299 private boolean mNotMoving;
300 private boolean mLocating;
301 private boolean mLocated;
Joe LaPenna23d681b2015-08-27 15:12:11 -0700302 private boolean mHasGps;
303 private boolean mHasNetworkLocation;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700304 private Location mLastGenericLocation;
305 private Location mLastGpsLocation;
Kweku Adams810c77d2019-08-28 07:45:00 -0700306
307 /** Time in the elapsed realtime timebase when this listener last received a motion event. */
308 private long mLastMotionEventElapsed;
309
Amith Yamasani396a10c2018-01-19 10:58:07 -0800310 // Current locked state of the screen
311 private boolean mScreenLocked;
Robin Lee876b88542018-11-13 17:22:24 +0100312 private int mNumBlockingConstraints = 0;
313
314 /**
315 * Constraints are the "handbrakes" that stop the device from moving into a lower state until
316 * every one is released at the same time.
317 *
318 * @see #registerDeviceIdleConstraintInternal(IDeviceIdleConstraint, String, int)
319 */
320 private final ArrayMap<IDeviceIdleConstraint, DeviceIdleConstraintTracker>
321 mConstraints = new ArrayMap<>();
322 private ConstraintController mConstraintController;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700323
324 /** Device is currently active. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700325 @VisibleForTesting
326 static final int STATE_ACTIVE = 0;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700327 /** Device is inactive (screen off, no motion) and we are waiting to for idle. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700328 @VisibleForTesting
329 static final int STATE_INACTIVE = 1;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700330 /** Device is past the initial inactive period, and waiting for the next idle period. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700331 @VisibleForTesting
332 static final int STATE_IDLE_PENDING = 2;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700333 /** Device is currently sensing motion. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700334 @VisibleForTesting
335 static final int STATE_SENSING = 3;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700336 /** Device is currently finding location (and may still be sensing). */
Kweku Adams00e3a372018-09-28 16:57:09 -0700337 @VisibleForTesting
338 static final int STATE_LOCATING = 4;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700339 /** Device is in the idle state, trying to stay asleep as much as possible. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700340 @VisibleForTesting
341 static final int STATE_IDLE = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700342 /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700343 @VisibleForTesting
344 static final int STATE_IDLE_MAINTENANCE = 6;
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700345 /**
346 * Device is inactive and should go straight into idle (foregoing motion and location
347 * monitoring), but allow some time for current work to complete first.
348 */
349 @VisibleForTesting
350 static final int STATE_QUICK_DOZE_DELAY = 7;
Amith Yamasani396a10c2018-01-19 10:58:07 -0800351
Denny cy Leec5a7c292019-01-01 17:37:55 +0800352 private static final int ACTIVE_REASON_UNKNOWN = 0;
353 private static final int ACTIVE_REASON_MOTION = 1;
354 private static final int ACTIVE_REASON_SCREEN = 2;
355 private static final int ACTIVE_REASON_CHARGING = 3;
356 private static final int ACTIVE_REASON_UNLOCKED = 4;
357 private static final int ACTIVE_REASON_FROM_BINDER_CALL = 5;
358 private static final int ACTIVE_REASON_FORCED = 6;
359 private static final int ACTIVE_REASON_ALARM = 7;
360 @VisibleForTesting
361 static final int SET_IDLE_FACTOR_RESULT_UNINIT = -1;
362 @VisibleForTesting
363 static final int SET_IDLE_FACTOR_RESULT_IGNORED = 0;
364 @VisibleForTesting
365 static final int SET_IDLE_FACTOR_RESULT_OK = 1;
366 @VisibleForTesting
367 static final int SET_IDLE_FACTOR_RESULT_NOT_SUPPORT = 2;
368 @VisibleForTesting
369 static final int SET_IDLE_FACTOR_RESULT_INVALID = 3;
370 @VisibleForTesting
371 static final long MIN_STATE_STEP_ALARM_CHANGE = 60 * 1000;
372 @VisibleForTesting
373 static final float MIN_PRE_IDLE_FACTOR_CHANGE = 0.05f;
374
Kweku Adams00e3a372018-09-28 16:57:09 -0700375 @VisibleForTesting
376 static String stateToString(int state) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700377 switch (state) {
378 case STATE_ACTIVE: return "ACTIVE";
379 case STATE_INACTIVE: return "INACTIVE";
380 case STATE_IDLE_PENDING: return "IDLE_PENDING";
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700381 case STATE_SENSING: return "SENSING";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700382 case STATE_LOCATING: return "LOCATING";
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700383 case STATE_IDLE: return "IDLE";
384 case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700385 case STATE_QUICK_DOZE_DELAY: return "QUICK_DOZE_DELAY";
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700386 default: return Integer.toString(state);
387 }
388 }
389
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700390 /** Device is currently active. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700391 @VisibleForTesting
392 static final int LIGHT_STATE_ACTIVE = 0;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700393 /** Device is inactive (screen off) and we are waiting to for the first light idle. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700394 @VisibleForTesting
395 static final int LIGHT_STATE_INACTIVE = 1;
Dianne Hackborn945c9c92016-03-30 14:55:00 -0700396 /** Device is about to go idle for the first time, wait for current work to complete. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700397 @VisibleForTesting
398 static final int LIGHT_STATE_PRE_IDLE = 3;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700399 /** Device is in the light idle state, trying to stay asleep as much as possible. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700400 @VisibleForTesting
401 static final int LIGHT_STATE_IDLE = 4;
Dianne Hackborn88c41352016-04-07 15:18:58 -0700402 /** Device is in the light idle state, we want to go in to idle maintenance but are
403 * waiting for network connectivity before doing so. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700404 @VisibleForTesting
405 static final int LIGHT_STATE_WAITING_FOR_NETWORK = 5;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700406 /** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700407 @VisibleForTesting
408 static final int LIGHT_STATE_IDLE_MAINTENANCE = 6;
Dianne Hackbornb6843652016-02-22 12:20:13 -0800409 /** Device light idle state is overriden, now applying deep doze state. */
Kweku Adams00e3a372018-09-28 16:57:09 -0700410 @VisibleForTesting
411 static final int LIGHT_STATE_OVERRIDE = 7;
412
413 @VisibleForTesting
414 static String lightStateToString(int state) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700415 switch (state) {
416 case LIGHT_STATE_ACTIVE: return "ACTIVE";
417 case LIGHT_STATE_INACTIVE: return "INACTIVE";
Dianne Hackborn945c9c92016-03-30 14:55:00 -0700418 case LIGHT_STATE_PRE_IDLE: return "PRE_IDLE";
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700419 case LIGHT_STATE_IDLE: return "IDLE";
Dianne Hackborn88c41352016-04-07 15:18:58 -0700420 case LIGHT_STATE_WAITING_FOR_NETWORK: return "WAITING_FOR_NETWORK";
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700421 case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
422 case LIGHT_STATE_OVERRIDE: return "OVERRIDE";
423 default: return Integer.toString(state);
424 }
425 }
426
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700427 private int mState;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700428 private int mLightState;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700429
430 private long mInactiveTimeout;
431 private long mNextAlarmTime;
432 private long mNextIdlePendingDelay;
433 private long mNextIdleDelay;
Dianne Hackborn953fc942016-03-29 15:36:24 -0700434 private long mNextLightIdleDelay;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700435 private long mNextLightAlarmTime;
Kevin Gabayan92f15e62016-04-04 17:52:22 -0700436 private long mNextSensingTimeoutAlarmTime;
Kweku Adams7c96f5182019-06-04 16:32:49 -0700437
438 /** How long a light idle maintenance window should last. */
439 private long mCurLightIdleBudget;
440
441 /**
442 * Start time of the current (light or full) maintenance window, in the elapsed timebase. Valid
443 * only if {@link #mState} == {@link #STATE_IDLE_MAINTENANCE} or
444 * {@link #mLightState} == {@link #LIGHT_STATE_IDLE_MAINTENANCE}.
445 */
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800446 private long mMaintenanceStartTime;
Denny cy Leec5a7c292019-01-01 17:37:55 +0800447 private long mIdleStartTime;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700448
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800449 private int mActiveIdleOpCount;
Joe Onorato8f0e9ced2016-12-08 17:48:49 -0800450 private PowerManager.WakeLock mActiveIdleWakeLock; // held when there are operations in progress
451 private PowerManager.WakeLock mGoingIdleWakeLock; // held when we are going idle so hardware
452 // (especially NetworkPolicyManager) can shut
453 // down.
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800454 private boolean mJobsActive;
455 private boolean mAlarmsActive;
456
Denny cy Leec5a7c292019-01-01 17:37:55 +0800457 /* Factor to apply to INACTIVE_TIMEOUT and IDLE_AFTER_INACTIVE_TIMEOUT in order to enter
458 * STATE_IDLE faster or slower. Don't apply this to SENSING_TIMEOUT or LOCATING_TIMEOUT because:
459 * - Both of them are shorter
460 * - Device sensor might take time be to become be stabilized
461 * Also don't apply the factor if the device is in motion because device motion provides a
462 * stronger signal than a prediction algorithm.
463 */
464 private float mPreIdleFactor;
465 private float mLastPreIdleFactor;
466 private int mActiveReason;
467
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700468 public final AtomicFile mConfigFile;
469
470 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700471 * Package names the system has white-listed to opt out of power save restrictions,
472 * except for device idle mode.
473 */
474 private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
475
476 /**
Sudheer Shanka3f4d7702017-04-28 17:38:03 -0700477 * Package names the user has white-listed using commandline option to opt out of
478 * power save restrictions, except for device idle mode.
479 */
480 private final ArraySet<String> mPowerSaveWhitelistUserAppsExceptIdle = new ArraySet<>();
481
482 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700483 * Package names the system has white-listed to opt out of power save restrictions for
484 * all modes.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700485 */
486 private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
487
488 /**
489 * Package names the user has white-listed to opt out of power save restrictions.
490 */
491 private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
492
493 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700494 * App IDs of built-in system apps that have been white-listed except for idle modes.
495 */
496 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
497 = new SparseBooleanArray();
498
499 /**
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700500 * App IDs of built-in system apps that have been white-listed.
501 */
502 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
503
504 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700505 * App IDs that have been white-listed to opt out of power save restrictions, except
506 * for device idle modes.
507 */
508 private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
509
510 /**
511 * Current app IDs that are in the complete power save white list, but shouldn't be
512 * excluded from idle modes. This array can be shared with others because it will not be
513 * modified once set.
514 */
515 private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
516
517 /**
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700518 * App IDs that have been white-listed to opt out of power save restrictions.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700519 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700520 private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700521
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700522 /**
523 * Current app IDs that are in the complete power save white list. This array can
524 * be shared with others because it will not be modified once set.
525 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700526 private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700527
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700528 /**
Dianne Hackborn262ae5c2016-02-10 16:28:29 -0800529 * App IDs that have been white-listed by the user to opt out of power save restrictions.
530 */
531 private final SparseBooleanArray mPowerSaveWhitelistUserAppIds = new SparseBooleanArray();
532
533 /**
534 * Current app IDs that are in the user power save white list. This array can
535 * be shared with others because it will not be modified once set.
536 */
537 private int[] mPowerSaveWhitelistUserAppIdArray = new int[0];
538
539 /**
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700540 * List of end times for UIDs that are temporarily marked as being allowed to access
541 * the network and acquire wakelocks. Times are in milliseconds.
542 */
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700543 private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
544 = new SparseArray<>();
545
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -0700546 private NetworkPolicyManagerInternal mNetworkPolicyManagerInternal;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700547
548 /**
549 * Current app IDs of temporarily whitelist apps for high-priority messages.
550 */
551 private int[] mTempWhitelistAppIdArray = new int[0];
552
Suprabh Shukla08105642017-09-26 14:45:30 -0700553 /**
554 * Apps in the system whitelist that have been taken out (probably because the user wanted to).
555 * They can be restored back by calling restoreAppToSystemWhitelist(String).
556 */
557 private ArrayMap<String, Integer> mRemovedFromSystemWhitelistApps = new ArrayMap<>();
558
Kweku Adams810c77d2019-08-28 07:45:00 -0700559 private final ArraySet<DeviceIdleInternal.StationaryListener> mStationaryListeners =
560 new ArraySet<>();
561
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800562 private static final int EVENT_NULL = 0;
563 private static final int EVENT_NORMAL = 1;
564 private static final int EVENT_LIGHT_IDLE = 2;
565 private static final int EVENT_LIGHT_MAINTENANCE = 3;
Dianne Hackbornb6843652016-02-22 12:20:13 -0800566 private static final int EVENT_DEEP_IDLE = 4;
567 private static final int EVENT_DEEP_MAINTENANCE = 5;
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800568
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700569 private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
570 private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
Amith Yamasaniac6517a2018-04-23 12:19:34 -0700571 private final String[] mEventReasons = new String[EVENT_BUFFER_SIZE];
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800572
Amith Yamasaniac6517a2018-04-23 12:19:34 -0700573 private void addEvent(int cmd, String reason) {
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800574 if (mEventCmds[0] != cmd) {
575 System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1);
576 System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1);
Amith Yamasaniac6517a2018-04-23 12:19:34 -0700577 System.arraycopy(mEventReasons, 0, mEventReasons, 1, EVENT_BUFFER_SIZE - 1);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800578 mEventCmds[0] = cmd;
579 mEventTimes[0] = SystemClock.elapsedRealtime();
Amith Yamasaniac6517a2018-04-23 12:19:34 -0700580 mEventReasons[0] = reason;
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800581 }
582 }
583
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700584 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
585 @Override public void onReceive(Context context, Intent intent) {
Dianne Hackborn88c41352016-04-07 15:18:58 -0700586 switch (intent.getAction()) {
587 case ConnectivityManager.CONNECTIVITY_ACTION: {
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -0700588 updateConnectivityState(intent);
Dianne Hackborn88c41352016-04-07 15:18:58 -0700589 } break;
590 case Intent.ACTION_BATTERY_CHANGED: {
Robin Lee204cb222018-12-07 15:17:44 +0100591 boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
592 boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
Dianne Hackborn88c41352016-04-07 15:18:58 -0700593 synchronized (DeviceIdleController.this) {
Robin Lee204cb222018-12-07 15:17:44 +0100594 updateChargingLocked(present && plugged);
Dianne Hackborn88c41352016-04-07 15:18:58 -0700595 }
596 } break;
597 case Intent.ACTION_PACKAGE_REMOVED: {
598 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
599 Uri data = intent.getData();
600 String ssp;
601 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
602 removePowerSaveWhitelistAppInternal(ssp);
603 }
604 }
605 } break;
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700606 }
607 }
608 };
609
610 private final AlarmManager.OnAlarmListener mLightAlarmListener
611 = new AlarmManager.OnAlarmListener() {
612 @Override
613 public void onAlarm() {
614 synchronized (DeviceIdleController.this) {
615 stepLightIdleStateLocked("s:alarm");
616 }
617 }
618 };
619
Kweku Adamsa890d282019-12-19 16:08:43 -0800620 /** AlarmListener to start monitoring motion if there are registered stationary listeners. */
621 private final AlarmManager.OnAlarmListener mMotionRegistrationAlarmListener = () -> {
622 synchronized (DeviceIdleController.this) {
623 if (mStationaryListeners.size() > 0) {
624 startMonitoringMotionLocked();
625 }
626 }
627 };
Kweku Adams810c77d2019-08-28 07:45:00 -0700628
629 private final AlarmManager.OnAlarmListener mMotionTimeoutAlarmListener = () -> {
630 synchronized (DeviceIdleController.this) {
631 if (!isStationaryLocked()) {
632 // If the device keeps registering motion, then the alarm should be
633 // rescheduled, so this shouldn't go off until the device is stationary.
634 // This case may happen in a race condition (alarm goes off right before
635 // motion is detected, but handleMotionDetectedLocked is called before
636 // we enter this block).
637 Slog.w(TAG, "motion timeout went off and device isn't stationary");
638 return;
639 }
640 }
641 postStationaryStatusUpdated();
642 };
643
Kevin Gabayan92f15e62016-04-04 17:52:22 -0700644 private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener
645 = new AlarmManager.OnAlarmListener() {
646 @Override
647 public void onAlarm() {
648 if (mState == STATE_SENSING) {
649 synchronized (DeviceIdleController.this) {
Kweku Adams00e3a372018-09-28 16:57:09 -0700650 // Restart the device idle progression in case the device moved but the screen
651 // didn't turn on.
Kevin Gabayan92f15e62016-04-04 17:52:22 -0700652 becomeInactiveIfAppropriateLocked();
653 }
654 }
655 }
656 };
657
Kweku Adamsb7ce1902019-01-30 10:55:34 -0800658 @VisibleForTesting
659 final AlarmManager.OnAlarmListener mDeepAlarmListener
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700660 = new AlarmManager.OnAlarmListener() {
661 @Override
662 public void onAlarm() {
663 synchronized (DeviceIdleController.this) {
664 stepIdleStateLocked("s:alarm");
665 }
666 }
667 };
668
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800669 private final BroadcastReceiver mIdleStartedDoneReceiver = new BroadcastReceiver() {
670 @Override public void onReceive(Context context, Intent intent) {
Dianne Hackborn945c9c92016-03-30 14:55:00 -0700671 // When coming out of a deep idle, we will add in some delay before we allow
672 // the system to settle down and finish the maintenance window. This is
673 // to give a chance for any pending work to be scheduled.
674 if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
675 mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP,
676 mConstants.MIN_DEEP_MAINTENANCE_TIME);
677 } else {
678 mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP,
679 mConstants.MIN_LIGHT_MAINTENANCE_TIME);
680 }
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800681 }
682 };
683
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -0700684 private final BroadcastReceiver mInteractivityReceiver = new BroadcastReceiver() {
685 @Override
686 public void onReceive(Context context, Intent intent) {
Dianne Hackborn9b5ebc92017-09-08 13:45:35 -0700687 synchronized (DeviceIdleController.this) {
688 updateInteractivityLocked();
689 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700690 }
691 };
692
Kweku Adams810c77d2019-08-28 07:45:00 -0700693 /** Post stationary status only to this listener. */
694 private void postStationaryStatus(DeviceIdleInternal.StationaryListener listener) {
695 mHandler.obtainMessage(MSG_REPORT_STATIONARY_STATUS, listener).sendToTarget();
696 }
697
698 /** Post stationary status to all registered listeners. */
699 private void postStationaryStatusUpdated() {
700 mHandler.sendEmptyMessage(MSG_REPORT_STATIONARY_STATUS);
701 }
702
703 private boolean isStationaryLocked() {
704 final long now = mInjector.getElapsedRealtime();
705 return mMotionListener.active
706 // Listening for motion for long enough and last motion was long enough ago.
707 && now - Math.max(mMotionListener.activatedTimeElapsed, mLastMotionEventElapsed)
708 >= mConstants.MOTION_INACTIVE_TIMEOUT;
709 }
710
711 @VisibleForTesting
712 void registerStationaryListener(DeviceIdleInternal.StationaryListener listener) {
713 synchronized (this) {
714 if (!mStationaryListeners.add(listener)) {
715 // Listener already registered.
716 return;
717 }
718 postStationaryStatus(listener);
719 if (mMotionListener.active) {
720 if (!isStationaryLocked() && mStationaryListeners.size() == 1) {
721 // First listener to be registered and the device isn't stationary, so we
722 // need to register the alarm to report the device is stationary.
723 scheduleMotionTimeoutAlarmLocked();
724 }
725 } else {
726 startMonitoringMotionLocked();
727 scheduleMotionTimeoutAlarmLocked();
728 }
729 }
730 }
731
732 private void unregisterStationaryListener(DeviceIdleInternal.StationaryListener listener) {
733 synchronized (this) {
734 if (mStationaryListeners.remove(listener) && mStationaryListeners.size() == 0
735 // Motion detection is started when transitioning from INACTIVE to IDLE_PENDING
736 // and so doesn't need to be on for ACTIVE or INACTIVE states.
737 // Motion detection isn't needed when idling due to Quick Doze.
738 && (mState == STATE_ACTIVE || mState == STATE_INACTIVE
739 || mQuickDozeActivated)) {
740 maybeStopMonitoringMotionLocked();
741 }
742 }
743 }
744
Kweku Adams00e3a372018-09-28 16:57:09 -0700745 @VisibleForTesting
746 final class MotionListener extends TriggerEventListener
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700747 implements SensorEventListener {
748
749 boolean active = false;
750
Kweku Adams810c77d2019-08-28 07:45:00 -0700751 /**
752 * Time in the elapsed realtime timebase when this listener was activated. Only valid if
753 * {@link #active} is true.
754 */
755 long activatedTimeElapsed;
756
Kweku Adams00e3a372018-09-28 16:57:09 -0700757 public boolean isActive() {
758 return active;
759 }
760
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700761 @Override
762 public void onTrigger(TriggerEvent event) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700763 synchronized (DeviceIdleController.this) {
Kweku Adamsa890d282019-12-19 16:08:43 -0800764 active = false;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700765 motionLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700766 }
767 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700768
769 @Override
770 public void onSensorChanged(SensorEvent event) {
771 synchronized (DeviceIdleController.this) {
Kweku Adamsa890d282019-12-19 16:08:43 -0800772 mSensorManager.unregisterListener(this, mMotionSensor);
773 active = false;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700774 motionLocked();
775 }
776 }
777
778 @Override
779 public void onAccuracyChanged(Sensor sensor, int accuracy) {}
780
781 public boolean registerLocked() {
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700782 boolean success;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700783 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
784 success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
785 } else {
786 success = mSensorManager.registerListener(
787 mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL);
788 }
789 if (success) {
790 active = true;
Kweku Adams810c77d2019-08-28 07:45:00 -0700791 activatedTimeElapsed = mInjector.getElapsedRealtime();
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700792 } else {
793 Slog.e(TAG, "Unable to register for " + mMotionSensor);
794 }
795 return success;
796 }
797
798 public void unregisterLocked() {
799 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
800 mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor);
801 } else {
802 mSensorManager.unregisterListener(mMotionListener);
803 }
804 active = false;
805 }
806 }
Kweku Adams00e3a372018-09-28 16:57:09 -0700807 @VisibleForTesting final MotionListener mMotionListener = new MotionListener();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700808
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700809 private final LocationListener mGenericLocationListener = new LocationListener() {
810 @Override
811 public void onLocationChanged(Location location) {
812 synchronized (DeviceIdleController.this) {
813 receivedGenericLocationLocked(location);
814 }
815 }
816
817 @Override
818 public void onStatusChanged(String provider, int status, Bundle extras) {
819 }
820
821 @Override
822 public void onProviderEnabled(String provider) {
823 }
824
825 @Override
826 public void onProviderDisabled(String provider) {
827 }
828 };
829
830 private final LocationListener mGpsLocationListener = new LocationListener() {
831 @Override
832 public void onLocationChanged(Location location) {
833 synchronized (DeviceIdleController.this) {
834 receivedGpsLocationLocked(location);
835 }
836 }
837
838 @Override
839 public void onStatusChanged(String provider, int status, Bundle extras) {
840 }
841
842 @Override
843 public void onProviderEnabled(String provider) {
844 }
845
846 @Override
847 public void onProviderDisabled(String provider) {
848 }
849 };
850
Adam Lesinski31c05d12015-06-09 17:34:04 -0700851 /**
852 * All times are in milliseconds. These constants are kept synchronized with the system
853 * global Settings. Any access to this class or its fields should be done while
854 * holding the DeviceIdleController lock.
855 */
Robin Lee876b88542018-11-13 17:22:24 +0100856 public final class Constants extends ContentObserver {
Adam Lesinski31c05d12015-06-09 17:34:04 -0700857 // Key names stored in the settings value.
Dianne Hackborn953fc942016-03-29 15:36:24 -0700858 private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
859 = "light_after_inactive_to";
Dianne Hackborn945c9c92016-03-30 14:55:00 -0700860 private static final String KEY_LIGHT_PRE_IDLE_TIMEOUT = "light_pre_idle_to";
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700861 private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
Dianne Hackborn953fc942016-03-29 15:36:24 -0700862 private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
863 private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800864 private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
865 = "light_idle_maintenance_min_budget";
866 private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
867 = "light_idle_maintenance_max_budget";
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700868 private static final String KEY_MIN_LIGHT_MAINTENANCE_TIME = "min_light_maintenance_time";
869 private static final String KEY_MIN_DEEP_MAINTENANCE_TIME = "min_deep_maintenance_time";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700870 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
871 private static final String KEY_SENSING_TIMEOUT = "sensing_to";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700872 private static final String KEY_LOCATING_TIMEOUT = "locating_to";
873 private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700874 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
875 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
876 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
877 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
878 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700879 private static final String KEY_QUICK_DOZE_DELAY_TIMEOUT = "quick_doze_delay_to";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700880 private static final String KEY_IDLE_TIMEOUT = "idle_to";
881 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
882 private static final String KEY_IDLE_FACTOR = "idle_factor";
883 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
884 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
885 "max_temp_app_whitelist_duration";
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700886 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
887 "mms_temp_app_whitelist_duration";
Dianne Hackborn451c3462015-07-21 17:39:46 -0700888 private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
889 "sms_temp_app_whitelist_duration";
Felipe Lemea1b79bf2016-05-24 13:06:54 -0700890 private static final String KEY_NOTIFICATION_WHITELIST_DURATION =
891 "notification_whitelist_duration";
Amith Yamasani396a10c2018-01-19 10:58:07 -0800892 /**
893 * Whether to wait for the user to unlock the device before causing screen-on to
894 * exit doze. Default = true
895 */
896 private static final String KEY_WAIT_FOR_UNLOCK = "wait_for_unlock";
Denny cy Leec5a7c292019-01-01 17:37:55 +0800897 private static final String KEY_PRE_IDLE_FACTOR_LONG =
898 "pre_idle_factor_long";
899 private static final String KEY_PRE_IDLE_FACTOR_SHORT =
900 "pre_idle_factor_short";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700901
902 /**
Dianne Hackborn953fc942016-03-29 15:36:24 -0700903 * This is the time, after becoming inactive, that we go in to the first
904 * light-weight idle mode.
905 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
906 * @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
907 */
908 public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
909
910 /**
Dianne Hackborn945c9c92016-03-30 14:55:00 -0700911 * This is amount of time we will wait from the point where we decide we would
912 * like to go idle until we actually do, while waiting for jobs and other current
913 * activity to finish.
914 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
915 * @see #KEY_LIGHT_PRE_IDLE_TIMEOUT
916 */
917 public long LIGHT_PRE_IDLE_TIMEOUT;
918
919 /**
Dianne Hackborn953fc942016-03-29 15:36:24 -0700920 * This is the initial time that we will run in idle maintenance mode.
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700921 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
922 * @see #KEY_LIGHT_IDLE_TIMEOUT
923 */
924 public long LIGHT_IDLE_TIMEOUT;
925
926 /**
Dianne Hackborn953fc942016-03-29 15:36:24 -0700927 * Scaling factor to apply to the light idle mode time each time we complete a cycle.
928 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
929 * @see #KEY_LIGHT_IDLE_FACTOR
930 */
931 public float LIGHT_IDLE_FACTOR;
932
933 /**
Kweku Adams00e3a372018-09-28 16:57:09 -0700934 * This is the maximum time we will run in idle maintenance mode.
Dianne Hackborn953fc942016-03-29 15:36:24 -0700935 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
936 * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
937 */
938 public long LIGHT_MAX_IDLE_TIMEOUT;
939
940 /**
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800941 * This is the minimum amount of time we want to make available for maintenance mode
942 * when lightly idling. That is, we will always have at least this amount of time
943 * available maintenance before timing out and cutting off maintenance mode.
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700944 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800945 * @see #KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700946 */
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800947 public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
948
949 /**
950 * This is the maximum amount of time we want to make available for maintenance mode
951 * when lightly idling. That is, if the system isn't using up its minimum maintenance
952 * budget and this time is being added to the budget reserve, this is the maximum
953 * reserve size we will allow to grow and thus the maximum amount of time we will
954 * allow for the maintenance window.
955 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
956 * @see #KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
957 */
958 public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700959
960 /**
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700961 * This is the minimum amount of time that we will stay in maintenance mode after
962 * a light doze. We have this minimum to allow various things to respond to switching
963 * in to maintenance mode and scheduling their work -- otherwise we may
Dianne Hackborn7ab40252016-06-15 17:30:24 -0700964 * see there is nothing to do (no jobs pending) and go out of maintenance
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700965 * mode immediately.
966 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
967 * @see #KEY_MIN_LIGHT_MAINTENANCE_TIME
968 */
969 public long MIN_LIGHT_MAINTENANCE_TIME;
970
971 /**
972 * This is the minimum amount of time that we will stay in maintenance mode after
973 * a full doze. We have this minimum to allow various things to respond to switching
974 * in to maintenance mode and scheduling their work -- otherwise we may
Dianne Hackborn7ab40252016-06-15 17:30:24 -0700975 * see there is nothing to do (no jobs pending) and go out of maintenance
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700976 * mode immediately.
977 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
978 * @see #KEY_MIN_DEEP_MAINTENANCE_TIME
979 */
980 public long MIN_DEEP_MAINTENANCE_TIME;
981
982 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -0700983 * This is the time, after becoming inactive, at which we start looking at the
984 * motion sensor to determine if the device is being left alone. We don't do this
985 * immediately after going inactive just because we don't want to be continually running
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700986 * the motion sensor whenever the screen is off.
Adam Lesinski31c05d12015-06-09 17:34:04 -0700987 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
988 * @see #KEY_INACTIVE_TIMEOUT
989 */
990 public long INACTIVE_TIMEOUT;
991
992 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700993 * If we don't receive a callback from AnyMotion in this amount of time +
994 * {@link #LOCATING_TIMEOUT}, we will change from
Adam Lesinski31c05d12015-06-09 17:34:04 -0700995 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
996 * will be ignored.
997 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
998 * @see #KEY_SENSING_TIMEOUT
999 */
1000 public long SENSING_TIMEOUT;
1001
1002 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001003 * This is how long we will wait to try to get a good location fix before going in to
1004 * idle mode.
1005 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1006 * @see #KEY_LOCATING_TIMEOUT
1007 */
1008 public long LOCATING_TIMEOUT;
1009
1010 /**
1011 * The desired maximum accuracy (in meters) we consider the location to be good enough to go
1012 * on to idle. We will be trying to get an accuracy fix at least this good or until
1013 * {@link #LOCATING_TIMEOUT} expires.
1014 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1015 * @see #KEY_LOCATION_ACCURACY
1016 */
1017 public float LOCATION_ACCURACY;
1018
1019 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -07001020 * This is the time, after seeing motion, that we wait after becoming inactive from
1021 * that until we start looking for motion again.
1022 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1023 * @see #KEY_MOTION_INACTIVE_TIMEOUT
1024 */
1025 public long MOTION_INACTIVE_TIMEOUT;
1026
1027 /**
1028 * This is the time, after the inactive timeout elapses, that we will wait looking
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001029 * for motion until we truly consider the device to be idle.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001030 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1031 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
1032 */
1033 public long IDLE_AFTER_INACTIVE_TIMEOUT;
1034
1035 /**
1036 * This is the initial time, after being idle, that we will allow ourself to be back
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001037 * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
1038 * idle.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001039 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1040 * @see #KEY_IDLE_PENDING_TIMEOUT
1041 */
1042 public long IDLE_PENDING_TIMEOUT;
1043
1044 /**
1045 * Maximum pending idle timeout (time spent running) we will be allowed to use.
1046 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1047 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
1048 */
1049 public long MAX_IDLE_PENDING_TIMEOUT;
1050
1051 /**
1052 * Scaling factor to apply to current pending idle timeout each time we cycle through
1053 * that state.
1054 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1055 * @see #KEY_IDLE_PENDING_FACTOR
1056 */
1057 public float IDLE_PENDING_FACTOR;
1058
1059 /**
Kweku Adamsb396ccf2018-09-17 16:37:15 -07001060 * This is amount of time we will wait from the point where we go into
1061 * STATE_QUICK_DOZE_DELAY until we actually go into STATE_IDLE, while waiting for jobs
1062 * and other current activity to finish.
1063 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1064 * @see #KEY_QUICK_DOZE_DELAY_TIMEOUT
1065 */
1066 public long QUICK_DOZE_DELAY_TIMEOUT;
1067
1068 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -07001069 * This is the initial time that we want to sit in the idle state before waking up
1070 * again to return to pending idle and allowing normal work to run.
1071 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1072 * @see #KEY_IDLE_TIMEOUT
1073 */
1074 public long IDLE_TIMEOUT;
1075
1076 /**
1077 * Maximum idle duration we will be allowed to use.
1078 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1079 * @see #KEY_MAX_IDLE_TIMEOUT
1080 */
1081 public long MAX_IDLE_TIMEOUT;
1082
1083 /**
1084 * Scaling factor to apply to current idle timeout each time we cycle through that state.
1085 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1086 * @see #KEY_IDLE_FACTOR
1087 */
1088 public float IDLE_FACTOR;
1089
1090 /**
1091 * This is the minimum time we will allow until the next upcoming alarm for us to
1092 * actually go in to idle mode.
1093 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1094 * @see #KEY_MIN_TIME_TO_ALARM
1095 */
1096 public long MIN_TIME_TO_ALARM;
1097
1098 /**
1099 * Max amount of time to temporarily whitelist an app when it receives a high priority
1100 * tickle.
1101 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1102 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
1103 */
1104 public long MAX_TEMP_APP_WHITELIST_DURATION;
1105
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001106 /**
1107 * Amount of time we would like to whitelist an app that is receiving an MMS.
1108 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1109 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
1110 */
1111 public long MMS_TEMP_APP_WHITELIST_DURATION;
1112
Dianne Hackborn451c3462015-07-21 17:39:46 -07001113 /**
1114 * Amount of time we would like to whitelist an app that is receiving an SMS.
1115 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1116 * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
1117 */
1118 public long SMS_TEMP_APP_WHITELIST_DURATION;
1119
Felipe Lemea1b79bf2016-05-24 13:06:54 -07001120 /**
1121 * Amount of time we would like to whitelist an app that is handling a
1122 * {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}.
1123 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1124 * @see #KEY_NOTIFICATION_WHITELIST_DURATION
1125 */
1126 public long NOTIFICATION_WHITELIST_DURATION;
1127
Denny cy Leec5a7c292019-01-01 17:37:55 +08001128 /**
1129 * Pre idle time factor use to make idle delay longer
1130 */
1131 public float PRE_IDLE_FACTOR_LONG;
1132
1133 /**
1134 * Pre idle time factor use to make idle delay shorter
1135 */
1136 public float PRE_IDLE_FACTOR_SHORT;
1137
Amith Yamasani396a10c2018-01-19 10:58:07 -08001138 public boolean WAIT_FOR_UNLOCK;
1139
Adam Lesinski31c05d12015-06-09 17:34:04 -07001140 private final ContentResolver mResolver;
shreerag597da8a2017-07-21 14:24:14 -07001141 private final boolean mSmallBatteryDevice;
Adam Lesinski31c05d12015-06-09 17:34:04 -07001142 private final KeyValueListParser mParser = new KeyValueListParser(',');
1143
1144 public Constants(Handler handler, ContentResolver resolver) {
1145 super(handler);
1146 mResolver = resolver;
shreerag597da8a2017-07-21 14:24:14 -07001147 mSmallBatteryDevice = ActivityManager.isSmallBatteryDevice();
1148 mResolver.registerContentObserver(
1149 Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS),
Joe LaPennaf33b5bf2016-03-23 15:19:47 -07001150 false, this);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001151 updateConstants();
1152 }
1153
1154 @Override
1155 public void onChange(boolean selfChange, Uri uri) {
1156 updateConstants();
1157 }
1158
1159 private void updateConstants() {
1160 synchronized (DeviceIdleController.this) {
1161 try {
1162 mParser.setString(Settings.Global.getString(mResolver,
shreerag597da8a2017-07-21 14:24:14 -07001163 Settings.Global.DEVICE_IDLE_CONSTANTS));
Adam Lesinski31c05d12015-06-09 17:34:04 -07001164 } catch (IllegalArgumentException e) {
1165 // Failed to parse the settings string, log this and move on
1166 // with defaults.
1167 Slog.e(TAG, "Bad device idle settings", e);
1168 }
1169
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001170 LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
Dianne Hackborn953fc942016-03-29 15:36:24 -07001171 KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
Suprabh Shukla85fff7d2018-05-08 17:39:24 -07001172 !COMPRESS_TIME ? 3 * 60 * 1000L : 15 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001173 LIGHT_PRE_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_PRE_IDLE_TIMEOUT,
Suprabh Shukla85fff7d2018-05-08 17:39:24 -07001174 !COMPRESS_TIME ? 3 * 60 * 1000L : 30 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001175 LIGHT_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_IDLE_TIMEOUT,
Dianne Hackborn953fc942016-03-29 15:36:24 -07001176 !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
1177 LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR,
1178 2f);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001179 LIGHT_MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_MAX_IDLE_TIMEOUT,
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001180 !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001181 LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getDurationMillis(
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08001182 KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001183 !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001184 LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getDurationMillis(
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08001185 KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET,
1186 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001187 MIN_LIGHT_MAINTENANCE_TIME = mParser.getDurationMillis(
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07001188 KEY_MIN_LIGHT_MAINTENANCE_TIME,
1189 !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001190 MIN_DEEP_MAINTENANCE_TIME = mParser.getDurationMillis(
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07001191 KEY_MIN_DEEP_MAINTENANCE_TIME,
1192 !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L);
Michael Kwan88871462017-08-21 13:13:37 -07001193 long inactiveTimeoutDefault = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001194 INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_INACTIVE_TIMEOUT,
Joe LaPenna0c5d3e92016-03-24 13:29:56 -07001195 !COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10));
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001196 SENSING_TIMEOUT = mParser.getDurationMillis(KEY_SENSING_TIMEOUT,
Kweku Adams9da2bb92018-12-20 06:34:39 -08001197 !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001198 LOCATING_TIMEOUT = mParser.getDurationMillis(KEY_LOCATING_TIMEOUT,
Kweku Adams9da2bb92018-12-20 06:34:39 -08001199 !COMPRESS_TIME ? 30 * 1000L : 15 * 1000L);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001200 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001201 MOTION_INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_MOTION_INACTIVE_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001202 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
Michael Kwan88871462017-08-21 13:13:37 -07001203 long idleAfterInactiveTimeout = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001204 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
1205 KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
Joe LaPenna0c5d3e92016-03-24 13:29:56 -07001206 !COMPRESS_TIME ? idleAfterInactiveTimeout
1207 : (idleAfterInactiveTimeout / 10));
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001208 IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_PENDING_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001209 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001210 MAX_IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_PENDING_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001211 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
1212 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
1213 2f);
Kweku Adamsb396ccf2018-09-17 16:37:15 -07001214 QUICK_DOZE_DELAY_TIMEOUT = mParser.getDurationMillis(
1215 KEY_QUICK_DOZE_DELAY_TIMEOUT, !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001216 IDLE_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001217 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001218 MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001219 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
1220 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
1221 2f);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001222 MIN_TIME_TO_ALARM = mParser.getDurationMillis(KEY_MIN_TIME_TO_ALARM,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001223 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001224 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001225 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001226 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
Dianne Hackborn0b6134b2015-07-14 18:48:07 -07001227 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001228 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
Dianne Hackborn451c3462015-07-21 17:39:46 -07001229 KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001230 NOTIFICATION_WHITELIST_DURATION = mParser.getDurationMillis(
Felipe Lemea1b79bf2016-05-24 13:06:54 -07001231 KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L);
Kweku Adams43fabba2019-03-07 15:47:37 -08001232 WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, true);
Denny cy Leec5a7c292019-01-01 17:37:55 +08001233 PRE_IDLE_FACTOR_LONG = mParser.getFloat(KEY_PRE_IDLE_FACTOR_LONG, 1.67f);
1234 PRE_IDLE_FACTOR_SHORT = mParser.getFloat(KEY_PRE_IDLE_FACTOR_SHORT, 0.33f);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001235 }
1236 }
1237
1238 void dump(PrintWriter pw) {
1239 pw.println(" Settings:");
1240
Dianne Hackborn953fc942016-03-29 15:36:24 -07001241 pw.print(" "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
1242 TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw);
1243 pw.println();
1244
Dianne Hackborn945c9c92016-03-30 14:55:00 -07001245 pw.print(" "); pw.print(KEY_LIGHT_PRE_IDLE_TIMEOUT); pw.print("=");
1246 TimeUtils.formatDuration(LIGHT_PRE_IDLE_TIMEOUT, pw);
1247 pw.println();
1248
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001249 pw.print(" "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
1250 TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
1251 pw.println();
1252
Dianne Hackborn953fc942016-03-29 15:36:24 -07001253 pw.print(" "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("=");
1254 pw.print(LIGHT_IDLE_FACTOR);
1255 pw.println();
1256
1257 pw.print(" "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT); pw.print("=");
1258 TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT, pw);
1259 pw.println();
1260
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08001261 pw.print(" "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); pw.print("=");
1262 TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, pw);
1263 pw.println();
1264
1265 pw.print(" "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET); pw.print("=");
1266 TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, pw);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001267 pw.println();
1268
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07001269 pw.print(" "); pw.print(KEY_MIN_LIGHT_MAINTENANCE_TIME); pw.print("=");
1270 TimeUtils.formatDuration(MIN_LIGHT_MAINTENANCE_TIME, pw);
1271 pw.println();
1272
1273 pw.print(" "); pw.print(KEY_MIN_DEEP_MAINTENANCE_TIME); pw.print("=");
1274 TimeUtils.formatDuration(MIN_DEEP_MAINTENANCE_TIME, pw);
1275 pw.println();
1276
Dianne Hackborna750a632015-06-16 17:18:23 -07001277 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001278 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
1279 pw.println();
1280
Dianne Hackborna750a632015-06-16 17:18:23 -07001281 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001282 TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
1283 pw.println();
1284
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001285 pw.print(" "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
1286 TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
1287 pw.println();
1288
1289 pw.print(" "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
1290 pw.print(LOCATION_ACCURACY); pw.print("m");
1291 pw.println();
1292
Dianne Hackborna750a632015-06-16 17:18:23 -07001293 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001294 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
1295 pw.println();
1296
Dianne Hackborna750a632015-06-16 17:18:23 -07001297 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001298 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
1299 pw.println();
1300
Dianne Hackborna750a632015-06-16 17:18:23 -07001301 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001302 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
1303 pw.println();
1304
Dianne Hackborna750a632015-06-16 17:18:23 -07001305 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001306 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
1307 pw.println();
1308
Dianne Hackborna750a632015-06-16 17:18:23 -07001309 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001310 pw.println(IDLE_PENDING_FACTOR);
1311
Kweku Adamsb396ccf2018-09-17 16:37:15 -07001312 pw.print(" "); pw.print(KEY_QUICK_DOZE_DELAY_TIMEOUT); pw.print("=");
1313 TimeUtils.formatDuration(QUICK_DOZE_DELAY_TIMEOUT, pw);
1314 pw.println();
1315
Dianne Hackborna750a632015-06-16 17:18:23 -07001316 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001317 TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
1318 pw.println();
1319
Dianne Hackborna750a632015-06-16 17:18:23 -07001320 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001321 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
1322 pw.println();
1323
Dianne Hackborna750a632015-06-16 17:18:23 -07001324 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001325 pw.println(IDLE_FACTOR);
1326
Dianne Hackborna750a632015-06-16 17:18:23 -07001327 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001328 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
1329 pw.println();
1330
Dianne Hackborna750a632015-06-16 17:18:23 -07001331 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001332 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
1333 pw.println();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001334
1335 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
1336 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
1337 pw.println();
Dianne Hackborn451c3462015-07-21 17:39:46 -07001338
1339 pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
1340 TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
1341 pw.println();
Felipe Lemea1b79bf2016-05-24 13:06:54 -07001342
1343 pw.print(" "); pw.print(KEY_NOTIFICATION_WHITELIST_DURATION); pw.print("=");
1344 TimeUtils.formatDuration(NOTIFICATION_WHITELIST_DURATION, pw);
1345 pw.println();
Amith Yamasani396a10c2018-01-19 10:58:07 -08001346
1347 pw.print(" "); pw.print(KEY_WAIT_FOR_UNLOCK); pw.print("=");
1348 pw.println(WAIT_FOR_UNLOCK);
Denny cy Leec5a7c292019-01-01 17:37:55 +08001349
1350 pw.print(" "); pw.print(KEY_PRE_IDLE_FACTOR_LONG); pw.print("=");
1351 pw.println(PRE_IDLE_FACTOR_LONG);
1352
1353 pw.print(" "); pw.print(KEY_PRE_IDLE_FACTOR_SHORT); pw.print("=");
1354 pw.println(PRE_IDLE_FACTOR_SHORT);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001355 }
1356 }
1357
1358 private Constants mConstants;
1359
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001360 @Override
1361 public void onAnyMotionResult(int result) {
1362 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
Kevin Gabayan92f15e62016-04-04 17:52:22 -07001363 if (result != AnyMotionDetector.RESULT_UNKNOWN) {
1364 synchronized (this) {
1365 cancelSensingTimeoutAlarmLocked();
1366 }
1367 }
Kevin Gabayandcf47012016-07-08 10:41:24 -07001368 if ((result == AnyMotionDetector.RESULT_MOVED) ||
1369 (result == AnyMotionDetector.RESULT_UNKNOWN)) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001370 synchronized (this) {
Kevin Gabayandcf47012016-07-08 10:41:24 -07001371 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001372 }
1373 } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001374 if (mState == STATE_SENSING) {
1375 // If we are currently sensing, it is time to move to locating.
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001376 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001377 mNotMoving = true;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001378 stepIdleStateLocked("s:stationary");
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001379 }
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001380 } else if (mState == STATE_LOCATING) {
1381 // If we are currently locating, note that we are not moving and step
1382 // if we have located the position.
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001383 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001384 mNotMoving = true;
1385 if (mLocated) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001386 stepIdleStateLocked("s:stationary");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001387 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001388 }
1389 }
1390 }
1391 }
1392
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001393 private static final int MSG_WRITE_CONFIG = 1;
1394 private static final int MSG_REPORT_IDLE_ON = 2;
1395 private static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
1396 private static final int MSG_REPORT_IDLE_OFF = 4;
1397 private static final int MSG_REPORT_ACTIVE = 5;
1398 private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
Kweku Adams810c77d2019-08-28 07:45:00 -07001399 @VisibleForTesting
1400 static final int MSG_REPORT_STATIONARY_STATUS = 7;
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001401 private static final int MSG_FINISH_IDLE_OP = 8;
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07001402 private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 9;
Robin Lee876b88542018-11-13 17:22:24 +01001403 private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
Denny cy Lee990ca332019-10-22 16:21:20 +08001404 @VisibleForTesting
1405 static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
1406 @VisibleForTesting
1407 static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001408
1409 final class MyHandler extends Handler {
1410 MyHandler(Looper looper) {
1411 super(looper);
1412 }
1413
1414 @Override public void handleMessage(Message msg) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001415 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001416 switch (msg.what) {
1417 case MSG_WRITE_CONFIG: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001418 // Does not hold a wakelock. Just let this happen whenever.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001419 handleWriteConfigFile();
1420 } break;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001421 case MSG_REPORT_IDLE_ON:
1422 case MSG_REPORT_IDLE_ON_LIGHT: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001423 // mGoingIdleWakeLock is held at this point
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001424 EventLogTags.writeDeviceIdleOnStart();
Dianne Hackbornb6843652016-02-22 12:20:13 -08001425 final boolean deepChanged;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001426 final boolean lightChanged;
1427 if (msg.what == MSG_REPORT_IDLE_ON) {
Dianne Hackbornb6843652016-02-22 12:20:13 -08001428 deepChanged = mLocalPowerManager.setDeviceIdleMode(true);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001429 lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1430 } else {
Dianne Hackbornb6843652016-02-22 12:20:13 -08001431 deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001432 lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
1433 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001434 try {
1435 mNetworkPolicyManager.setDeviceIdleMode(true);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001436 mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07001437 ? BatteryStats.DEVICE_IDLE_MODE_DEEP
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001438 : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001439 } catch (RemoteException e) {
1440 }
Dianne Hackbornb6843652016-02-22 12:20:13 -08001441 if (deepChanged) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001442 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1443 }
1444 if (lightChanged) {
1445 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1446 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001447 EventLogTags.writeDeviceIdleOnComplete();
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001448 mGoingIdleWakeLock.release();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001449 } break;
1450 case MSG_REPORT_IDLE_OFF: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001451 // mActiveIdleWakeLock is held at this point
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001452 EventLogTags.writeDeviceIdleOffStart("unknown");
Dianne Hackbornb6843652016-02-22 12:20:13 -08001453 final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001454 final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001455 try {
1456 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001457 mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1458 null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001459 } catch (RemoteException e) {
1460 }
Dianne Hackbornb6843652016-02-22 12:20:13 -08001461 if (deepChanged) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001462 incActiveIdleOps();
1463 getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL,
1464 null, mIdleStartedDoneReceiver, null, 0, null, null);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001465 }
1466 if (lightChanged) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001467 incActiveIdleOps();
1468 getContext().sendOrderedBroadcastAsUser(mLightIdleIntent, UserHandle.ALL,
1469 null, mIdleStartedDoneReceiver, null, 0, null, null);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001470 }
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001471 // Always start with one active op for the message being sent here.
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001472 // Now we are done!
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001473 decActiveIdleOps();
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001474 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001475 } break;
1476 case MSG_REPORT_ACTIVE: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001477 // The device is awake at this point, so no wakelock necessary.
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001478 String activeReason = (String)msg.obj;
1479 int activeUid = msg.arg1;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001480 EventLogTags.writeDeviceIdleOffStart(
1481 activeReason != null ? activeReason : "unknown");
Dianne Hackbornb6843652016-02-22 12:20:13 -08001482 final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001483 final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001484 try {
1485 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001486 mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1487 activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001488 } catch (RemoteException e) {
1489 }
Dianne Hackbornb6843652016-02-22 12:20:13 -08001490 if (deepChanged) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001491 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1492 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001493 if (lightChanged) {
1494 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1495 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001496 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001497 } break;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001498 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001499 // TODO: What is keeping the device awake at this point? Does it need to be?
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07001500 int appId = msg.arg1;
1501 checkTempAppWhitelistTimeout(appId);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001502 } break;
Dianne Hackborn945c9c92016-03-30 14:55:00 -07001503 case MSG_FINISH_IDLE_OP: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001504 // mActiveIdleWakeLock is held at this point
Dianne Hackborn945c9c92016-03-30 14:55:00 -07001505 decActiveIdleOps();
1506 } break;
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07001507 case MSG_REPORT_TEMP_APP_WHITELIST_CHANGED: {
1508 final int appId = msg.arg1;
1509 final boolean added = (msg.arg2 == 1);
1510 mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, added);
1511 } break;
Robin Lee876b88542018-11-13 17:22:24 +01001512 case MSG_SEND_CONSTRAINT_MONITORING: {
1513 final IDeviceIdleConstraint constraint = (IDeviceIdleConstraint) msg.obj;
1514 final boolean monitoring = (msg.arg1 == 1);
1515 if (monitoring) {
1516 constraint.startMonitoring();
1517 } else {
1518 constraint.stopMonitoring();
1519 }
1520 } break;
Denny cy Leec5a7c292019-01-01 17:37:55 +08001521 case MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR: {
1522 updatePreIdleFactor();
1523 } break;
1524 case MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR: {
1525 updatePreIdleFactor();
1526 maybeDoImmediateMaintenance();
1527 } break;
Kweku Adams810c77d2019-08-28 07:45:00 -07001528 case MSG_REPORT_STATIONARY_STATUS: {
1529 final DeviceIdleInternal.StationaryListener newListener =
1530 (DeviceIdleInternal.StationaryListener) msg.obj;
1531 final DeviceIdleInternal.StationaryListener[] listeners;
1532 final boolean isStationary;
1533 synchronized (DeviceIdleController.this) {
1534 isStationary = isStationaryLocked();
1535 if (newListener == null) {
1536 // Only notify all listeners if we aren't directing to one listener.
1537 listeners = mStationaryListeners.toArray(
1538 new DeviceIdleInternal.StationaryListener[
1539 mStationaryListeners.size()]);
1540 } else {
1541 listeners = null;
1542 }
1543 }
1544 if (listeners != null) {
1545 for (DeviceIdleInternal.StationaryListener listener : listeners) {
1546 listener.onDeviceStationaryChanged(isStationary);
1547 }
1548 }
1549 if (newListener != null) {
1550 newListener.onDeviceStationaryChanged(isStationary);
1551 }
1552 }
1553 break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001554 }
1555 }
1556 }
1557
1558 final MyHandler mHandler;
1559
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001560 BinderService mBinderService;
1561
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001562 private final class BinderService extends IDeviceIdleController.Stub {
1563 @Override public void addPowerSaveWhitelistApp(String name) {
Eugene Susla6a7006a2017-03-13 12:57:58 -07001564 if (DEBUG) {
1565 Slog.i(TAG, "addPowerSaveWhitelistApp(name = " + name + ")");
1566 }
Kweku Adamsc2400c82019-10-09 15:56:04 -07001567 addPowerSaveWhitelistApps(Collections.singletonList(name));
1568 }
1569
1570 @Override
1571 public int addPowerSaveWhitelistApps(List<String> packageNames) {
1572 if (DEBUG) {
1573 Slog.i(TAG,
1574 "addPowerSaveWhitelistApps(name = " + packageNames + ")");
1575 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001576 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1577 null);
Dianne Hackbornc9b2cd12016-01-20 10:54:29 -08001578 long ident = Binder.clearCallingIdentity();
1579 try {
Kweku Adamsc2400c82019-10-09 15:56:04 -07001580 return addPowerSaveWhitelistAppsInternal(packageNames);
Dianne Hackbornc9b2cd12016-01-20 10:54:29 -08001581 } finally {
1582 Binder.restoreCallingIdentity(ident);
1583 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001584 }
1585
1586 @Override public void removePowerSaveWhitelistApp(String name) {
Eugene Susla6a7006a2017-03-13 12:57:58 -07001587 if (DEBUG) {
1588 Slog.i(TAG, "removePowerSaveWhitelistApp(name = " + name + ")");
1589 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001590 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1591 null);
Dianne Hackbornc9b2cd12016-01-20 10:54:29 -08001592 long ident = Binder.clearCallingIdentity();
1593 try {
1594 removePowerSaveWhitelistAppInternal(name);
1595 } finally {
1596 Binder.restoreCallingIdentity(ident);
1597 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001598 }
1599
Suprabh Shukla08105642017-09-26 14:45:30 -07001600 @Override public void removeSystemPowerWhitelistApp(String name) {
1601 if (DEBUG) {
1602 Slog.d(TAG, "removeAppFromSystemWhitelist(name = " + name + ")");
1603 }
1604 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1605 null);
1606 long ident = Binder.clearCallingIdentity();
1607 try {
1608 removeSystemPowerWhitelistAppInternal(name);
1609 } finally {
1610 Binder.restoreCallingIdentity(ident);
1611 }
1612 }
1613
1614 @Override public void restoreSystemPowerWhitelistApp(String name) {
1615 if (DEBUG) {
1616 Slog.d(TAG, "restoreAppToSystemWhitelist(name = " + name + ")");
1617 }
1618 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1619 null);
1620 long ident = Binder.clearCallingIdentity();
1621 try {
1622 restoreSystemPowerWhitelistAppInternal(name);
1623 } finally {
1624 Binder.restoreCallingIdentity(ident);
1625 }
1626 }
1627
1628 public String[] getRemovedSystemPowerWhitelistApps() {
1629 return getRemovedSystemPowerWhitelistAppsInternal();
1630 }
1631
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001632 @Override public String[] getSystemPowerWhitelistExceptIdle() {
1633 return getSystemPowerWhitelistExceptIdleInternal();
1634 }
1635
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001636 @Override public String[] getSystemPowerWhitelist() {
1637 return getSystemPowerWhitelistInternal();
1638 }
1639
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001640 @Override public String[] getUserPowerWhitelist() {
1641 return getUserPowerWhitelistInternal();
1642 }
1643
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001644 @Override public String[] getFullPowerWhitelistExceptIdle() {
1645 return getFullPowerWhitelistExceptIdleInternal();
1646 }
1647
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001648 @Override public String[] getFullPowerWhitelist() {
1649 return getFullPowerWhitelistInternal();
1650 }
1651
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001652 @Override public int[] getAppIdWhitelistExceptIdle() {
1653 return getAppIdWhitelistExceptIdleInternal();
1654 }
1655
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001656 @Override public int[] getAppIdWhitelist() {
1657 return getAppIdWhitelistInternal();
1658 }
1659
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001660 @Override public int[] getAppIdUserWhitelist() {
1661 return getAppIdUserWhitelistInternal();
1662 }
1663
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001664 @Override public int[] getAppIdTempWhitelist() {
1665 return getAppIdTempWhitelistInternal();
1666 }
1667
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001668 @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
1669 return isPowerSaveWhitelistExceptIdleAppInternal(name);
1670 }
1671
Amith Yamasani06bf8242015-05-08 16:36:21 -07001672 @Override public boolean isPowerSaveWhitelistApp(String name) {
1673 return isPowerSaveWhitelistAppInternal(name);
1674 }
1675
Kweku Adams835283f2019-11-20 14:41:22 -08001676 @Override
1677 public long whitelistAppTemporarily(String packageName, int userId, String reason)
1678 throws RemoteException {
1679 // At least 10 seconds.
1680 long duration = Math.max(10_000L, mConstants.MAX_TEMP_APP_WHITELIST_DURATION / 2);
1681 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1682 return duration;
1683 }
1684
1685 @Override
1686 public void addPowerSaveTempWhitelistApp(String packageName, long duration,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001687 int userId, String reason) throws RemoteException {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001688 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001689 }
1690
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001691 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
1692 int userId, String reason) throws RemoteException {
1693 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001694 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001695 return duration;
1696 }
1697
Dianne Hackborn451c3462015-07-21 17:39:46 -07001698 @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
1699 int userId, String reason) throws RemoteException {
1700 long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001701 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Dianne Hackborn451c3462015-07-21 17:39:46 -07001702 return duration;
1703 }
1704
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001705 @Override public void exitIdle(String reason) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001706 getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001707 null);
Dianne Hackbornc9b2cd12016-01-20 10:54:29 -08001708 long ident = Binder.clearCallingIdentity();
1709 try {
1710 exitIdleInternal(reason);
1711 } finally {
1712 Binder.restoreCallingIdentity(ident);
1713 }
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001714 }
1715
Denny cy Leec5a7c292019-01-01 17:37:55 +08001716 @Override public int setPreIdleTimeoutMode(int mode) {
1717 getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1718 null);
1719 long ident = Binder.clearCallingIdentity();
1720 try {
1721 return DeviceIdleController.this.setPreIdleTimeoutMode(mode);
1722 } finally {
1723 Binder.restoreCallingIdentity(ident);
1724 }
1725 }
1726
1727 @Override public void resetPreIdleTimeoutMode() {
1728 getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1729 null);
1730 long ident = Binder.clearCallingIdentity();
1731 try {
1732 DeviceIdleController.this.resetPreIdleTimeoutMode();
1733 } finally {
1734 Binder.restoreCallingIdentity(ident);
1735 }
1736 }
1737
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001738 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1739 DeviceIdleController.this.dump(fd, pw, args);
1740 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001741
1742 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
Dianne Hackborn354736e2016-08-22 17:00:05 -07001743 FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
1744 (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001745 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001746 }
1747
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001748 private class LocalService implements DeviceIdleInternal {
1749 @Override
Robin Lee876b88542018-11-13 17:22:24 +01001750 public void onConstraintStateChanged(IDeviceIdleConstraint constraint, boolean active) {
1751 synchronized (DeviceIdleController.this) {
1752 onConstraintStateChangedLocked(constraint, active);
1753 }
1754 }
1755
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001756 @Override
Robin Lee876b88542018-11-13 17:22:24 +01001757 public void registerDeviceIdleConstraint(IDeviceIdleConstraint constraint, String name,
1758 @IDeviceIdleConstraint.MinimumState int minState) {
1759 registerDeviceIdleConstraintInternal(constraint, name, minState);
1760 }
1761
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001762 @Override
Robin Lee876b88542018-11-13 17:22:24 +01001763 public void unregisterDeviceIdleConstraint(IDeviceIdleConstraint constraint) {
1764 unregisterDeviceIdleConstraintInternal(constraint);
1765 }
1766
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001767 @Override
Robin Lee876b88542018-11-13 17:22:24 +01001768 public void exitIdle(String reason) {
1769 exitIdleInternal(reason);
1770 }
1771
Christopher Tatee0be7e82017-02-08 17:38:20 -08001772 // duration in milliseconds
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001773 @Override
Christopher Tatee0be7e82017-02-08 17:38:20 -08001774 public void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
1775 long duration, int userId, boolean sync, String reason) {
1776 addPowerSaveTempWhitelistAppInternal(callingUid, packageName, duration,
1777 userId, sync, reason);
1778 }
1779
1780 // duration in milliseconds
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001781 @Override
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07001782 public void addPowerSaveTempWhitelistAppDirect(int uid, long duration, boolean sync,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001783 String reason) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07001784 addPowerSaveTempWhitelistAppDirectInternal(0, uid, duration, sync, reason);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001785 }
1786
Christopher Tatee0be7e82017-02-08 17:38:20 -08001787 // duration in milliseconds
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001788 @Override
Felipe Lemea1b79bf2016-05-24 13:06:54 -07001789 public long getNotificationWhitelistDuration() {
1790 return mConstants.NOTIFICATION_WHITELIST_DURATION;
1791 }
1792
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001793 @Override
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001794 public void setJobsActive(boolean active) {
1795 DeviceIdleController.this.setJobsActive(active);
1796 }
1797
1798 // Up-call from alarm manager.
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001799 @Override
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001800 public void setAlarmsActive(boolean active) {
1801 DeviceIdleController.this.setAlarmsActive(active);
1802 }
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001803
Christopher Tate42a386b2016-11-07 12:21:21 -08001804 /** Is the app on any of the power save whitelists, whether system or user? */
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001805 @Override
Christopher Tate42a386b2016-11-07 12:21:21 -08001806 public boolean isAppOnWhitelist(int appid) {
1807 return DeviceIdleController.this.isAppOnWhitelistInternal(appid);
1808 }
1809
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001810 /**
1811 * Returns the array of app ids whitelisted by user. Take care not to
1812 * modify this, as it is a reference to the original copy. But the reference
1813 * can change when the list changes, so it needs to be re-acquired when
1814 * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent.
1815 */
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001816 @Override
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001817 public int[] getPowerSaveWhitelistUserAppIds() {
1818 return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
1819 }
Suprabh Shuklaa78acfd2017-10-13 19:29:36 -07001820
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001821 @Override
Suprabh Shuklaa78acfd2017-10-13 19:29:36 -07001822 public int[] getPowerSaveTempWhitelistAppIds() {
1823 return DeviceIdleController.this.getAppIdTempWhitelistInternal();
1824 }
Kweku Adams810c77d2019-08-28 07:45:00 -07001825
1826 @Override
1827 public void registerStationaryListener(StationaryListener listener) {
1828 DeviceIdleController.this.registerStationaryListener(listener);
1829 }
1830
1831 @Override
1832 public void unregisterStationaryListener(StationaryListener listener) {
1833 DeviceIdleController.this.unregisterStationaryListener(listener);
1834 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001835 }
1836
Kweku Adams00e3a372018-09-28 16:57:09 -07001837 static class Injector {
1838 private final Context mContext;
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07001839 private ConnectivityManager mConnectivityManager;
Kweku Adams9da2bb92018-12-20 06:34:39 -08001840 private Constants mConstants;
Kweku Adams799858b2018-10-08 17:19:08 -07001841 private LocationManager mLocationManager;
Kweku Adams00e3a372018-09-28 16:57:09 -07001842
1843 Injector(Context ctx) {
1844 mContext = ctx;
1845 }
1846
1847 AlarmManager getAlarmManager() {
1848 return mContext.getSystemService(AlarmManager.class);
1849 }
1850
1851 AnyMotionDetector getAnyMotionDetector(Handler handler, SensorManager sm,
1852 AnyMotionDetector.DeviceIdleCallback callback, float angleThreshold) {
1853 return new AnyMotionDetector(getPowerManager(), handler, sm, callback, angleThreshold);
1854 }
1855
1856 AppStateTracker getAppStateTracker(Context ctx, Looper looper) {
1857 return new AppStateTracker(ctx, looper);
1858 }
1859
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07001860 ConnectivityManager getConnectivityManager() {
1861 if (mConnectivityManager == null) {
1862 mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
Kweku Adams799858b2018-10-08 17:19:08 -07001863 }
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07001864 return mConnectivityManager;
Kweku Adams00e3a372018-09-28 16:57:09 -07001865 }
1866
Kweku Adamsa457f4e2018-10-03 15:56:06 -07001867 Constants getConstants(DeviceIdleController controller, Handler handler,
1868 ContentResolver resolver) {
Kweku Adams9da2bb92018-12-20 06:34:39 -08001869 if (mConstants == null) {
1870 mConstants = controller.new Constants(handler, resolver);
1871 }
1872 return mConstants;
Kweku Adamsa457f4e2018-10-03 15:56:06 -07001873 }
1874
Kweku Adamsecf98fb2019-07-22 17:12:41 -07001875
1876 /** Returns the current elapsed realtime in milliseconds. */
1877 long getElapsedRealtime() {
1878 return SystemClock.elapsedRealtime();
1879 }
1880
Kweku Adams00e3a372018-09-28 16:57:09 -07001881 LocationManager getLocationManager() {
Kweku Adams799858b2018-10-08 17:19:08 -07001882 if (mLocationManager == null) {
1883 mLocationManager = mContext.getSystemService(LocationManager.class);
1884 }
1885 return mLocationManager;
Kweku Adams00e3a372018-09-28 16:57:09 -07001886 }
1887
Kweku Adamsa457f4e2018-10-03 15:56:06 -07001888 MyHandler getHandler(DeviceIdleController controller) {
1889 return controller.new MyHandler(BackgroundThread.getHandler().getLooper());
Kweku Adams00e3a372018-09-28 16:57:09 -07001890 }
1891
Kweku Adamsa890d282019-12-19 16:08:43 -08001892 Sensor getMotionSensor() {
1893 final SensorManager sensorManager = getSensorManager();
1894 Sensor motionSensor = null;
1895 int sigMotionSensorId = mContext.getResources().getInteger(
1896 com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
1897 if (sigMotionSensorId > 0) {
1898 motionSensor = sensorManager.getDefaultSensor(sigMotionSensorId, true);
1899 }
1900 if (motionSensor == null && mContext.getResources().getBoolean(
1901 com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
1902 motionSensor = sensorManager.getDefaultSensor(
1903 Sensor.TYPE_WRIST_TILT_GESTURE, true);
1904 }
1905 if (motionSensor == null) {
1906 // As a last ditch, fall back to SMD.
1907 motionSensor = sensorManager.getDefaultSensor(
1908 Sensor.TYPE_SIGNIFICANT_MOTION, true);
1909 }
1910 return motionSensor;
1911 }
1912
Kweku Adams00e3a372018-09-28 16:57:09 -07001913 PowerManager getPowerManager() {
1914 return mContext.getSystemService(PowerManager.class);
1915 }
Robin Lee876b88542018-11-13 17:22:24 +01001916
1917 SensorManager getSensorManager() {
1918 return mContext.getSystemService(SensorManager.class);
1919 }
1920
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001921 ConstraintController getConstraintController(Handler handler,
1922 DeviceIdleInternal localService) {
Robin Lee876b88542018-11-13 17:22:24 +01001923 if (mContext.getPackageManager()
1924 .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
1925 return new TvConstraintController(mContext, handler);
1926 }
1927 return null;
1928 }
1929
1930 boolean useMotionSensor() {
1931 return mContext.getResources().getBoolean(
1932 com.android.internal.R.bool.config_autoPowerModeUseMotionSensor);
1933 }
Kweku Adams00e3a372018-09-28 16:57:09 -07001934 }
1935
1936 private final Injector mInjector;
1937
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001938 private ActivityTaskManagerInternal.ScreenObserver mScreenObserver =
1939 new ActivityTaskManagerInternal.ScreenObserver() {
Amith Yamasani396a10c2018-01-19 10:58:07 -08001940 @Override
1941 public void onAwakeStateChanged(boolean isAwake) { }
1942
1943 @Override
1944 public void onKeyguardStateChanged(boolean isShowing) {
1945 synchronized (DeviceIdleController.this) {
1946 DeviceIdleController.this.keyguardShowingLocked(isShowing);
1947 }
1948 }
1949 };
1950
Kweku Adams00e3a372018-09-28 16:57:09 -07001951 @VisibleForTesting DeviceIdleController(Context context, Injector injector) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001952 super(context);
Kweku Adams00e3a372018-09-28 16:57:09 -07001953 mInjector = injector;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001954 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
Kweku Adams00e3a372018-09-28 16:57:09 -07001955 mHandler = mInjector.getHandler(this);
1956 mAppStateTracker = mInjector.getAppStateTracker(context, FgThread.get().getLooper());
Makoto Onukie4918212018-02-06 11:30:15 -08001957 LocalServices.addService(AppStateTracker.class, mAppStateTracker);
Robin Lee876b88542018-11-13 17:22:24 +01001958 mUseMotionSensor = mInjector.useMotionSensor();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001959 }
1960
Kweku Adams00e3a372018-09-28 16:57:09 -07001961 public DeviceIdleController(Context context) {
1962 this(context, new Injector(context));
1963 }
1964
Christopher Tate42a386b2016-11-07 12:21:21 -08001965 boolean isAppOnWhitelistInternal(int appid) {
1966 synchronized (this) {
1967 return Arrays.binarySearch(mPowerSaveWhitelistAllAppIdArray, appid) >= 0;
1968 }
1969 }
1970
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001971 int[] getPowerSaveWhitelistUserAppIds() {
1972 synchronized (this) {
1973 return mPowerSaveWhitelistUserAppIdArray;
1974 }
1975 }
1976
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001977 private static File getSystemDir() {
1978 return new File(Environment.getDataDirectory(), "system");
1979 }
1980
1981 @Override
1982 public void onStart() {
1983 final PackageManager pm = getContext().getPackageManager();
1984
1985 synchronized (this) {
Dianne Hackbornb6843652016-02-22 12:20:13 -08001986 mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean(
Dianne Hackborn92617032015-06-19 15:32:19 -07001987 com.android.internal.R.bool.config_enableAutoPowerModes);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001988 SystemConfig sysConfig = SystemConfig.getInstance();
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001989 ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
1990 for (int i=0; i<allowPowerExceptIdle.size(); i++) {
1991 String pkg = allowPowerExceptIdle.valueAt(i);
1992 try {
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07001993 ApplicationInfo ai = pm.getApplicationInfo(pkg,
1994 PackageManager.MATCH_SYSTEM_ONLY);
1995 int appid = UserHandle.getAppId(ai.uid);
1996 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
1997 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001998 } catch (PackageManager.NameNotFoundException e) {
1999 }
2000 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002001 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
2002 for (int i=0; i<allowPower.size(); i++) {
2003 String pkg = allowPower.valueAt(i);
2004 try {
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07002005 ApplicationInfo ai = pm.getApplicationInfo(pkg,
2006 PackageManager.MATCH_SYSTEM_ONLY);
2007 int appid = UserHandle.getAppId(ai.uid);
2008 // These apps are on both the whitelist-except-idle as well
2009 // as the full whitelist, so they apply in all cases.
2010 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
2011 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
2012 mPowerSaveWhitelistApps.put(ai.packageName, appid);
2013 mPowerSaveWhitelistSystemAppIds.put(appid, true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002014 } catch (PackageManager.NameNotFoundException e) {
2015 }
2016 }
2017
Kweku Adamsa457f4e2018-10-03 15:56:06 -07002018 mConstants = mInjector.getConstants(this, mHandler, getContext().getContentResolver());
Adam Lesinski31c05d12015-06-09 17:34:04 -07002019
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002020 readConfigFileLocked();
2021 updateWhitelistAppIdsLocked();
2022
Dianne Hackborn88c41352016-04-07 15:18:58 -07002023 mNetworkConnected = true;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002024 mScreenOn = true;
Amith Yamasani396a10c2018-01-19 10:58:07 -08002025 mScreenLocked = false;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002026 // Start out assuming we are charging. If we aren't, we will at least get
2027 // a battery update the next time the level drops.
2028 mCharging = true;
Denny cy Leec5a7c292019-01-01 17:37:55 +08002029 mActiveReason = ACTIVE_REASON_UNKNOWN;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002030 mState = STATE_ACTIVE;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002031 mLightState = LIGHT_STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -07002032 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Denny cy Leec5a7c292019-01-01 17:37:55 +08002033 mPreIdleFactor = 1.0f;
2034 mLastPreIdleFactor = 1.0f;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002035 }
2036
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002037 mBinderService = new BinderService();
2038 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);
Kweku Adams810c77d2019-08-28 07:45:00 -07002039 mLocalService = new LocalService();
2040 publishLocalService(DeviceIdleInternal.class, mLocalService);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002041 }
2042
2043 @Override
2044 public void onBootPhase(int phase) {
2045 if (phase == PHASE_SYSTEM_SERVICES_READY) {
2046 synchronized (this) {
Kweku Adams00e3a372018-09-28 16:57:09 -07002047 mAlarmManager = mInjector.getAlarmManager();
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002048 mLocalAlarmManager = getLocalService(AlarmManagerInternal.class);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002049 mBatteryStats = BatteryStatsService.getService();
Dianne Hackborn85e35642017-01-12 15:10:57 -08002050 mLocalActivityManager = getLocalService(ActivityManagerInternal.class);
Wale Ogunwale6767eae2018-05-03 15:52:51 -07002051 mLocalActivityTaskManager = getLocalService(ActivityTaskManagerInternal.class);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002052 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
Kweku Adams00e3a372018-09-28 16:57:09 -07002053 mPowerManager = mInjector.getPowerManager();
Dianne Hackborn945c9c92016-03-30 14:55:00 -07002054 mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
2055 "deviceidle_maint");
2056 mActiveIdleWakeLock.setReferenceCounted(false);
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08002057 mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
2058 "deviceidle_going_idle");
2059 mGoingIdleWakeLock.setReferenceCounted(true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002060 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002061 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07002062 mNetworkPolicyManagerInternal = getLocalService(NetworkPolicyManagerInternal.class);
Robin Lee876b88542018-11-13 17:22:24 +01002063 mSensorManager = mInjector.getSensorManager();
Robin Leec4d424c2018-12-07 15:09:13 +01002064
2065 if (mUseMotionSensor) {
Kweku Adamsa890d282019-12-19 16:08:43 -08002066 mMotionSensor = mInjector.getMotionSensor();
Joe LaPenna23d681b2015-08-27 15:12:11 -07002067 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -07002068
Joe LaPenna23d681b2015-08-27 15:12:11 -07002069 if (getContext().getResources().getBoolean(
2070 com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07002071 mLocationRequest = LocationRequest.create()
Joe LaPenna23d681b2015-08-27 15:12:11 -07002072 .setQuality(LocationRequest.ACCURACY_FINE)
2073 .setInterval(0)
2074 .setFastestInterval(0)
2075 .setNumUpdates(1);
2076 }
2077
Robin Lee876b88542018-11-13 17:22:24 +01002078 mConstraintController = mInjector.getConstraintController(
2079 mHandler, getLocalService(LocalService.class));
2080 if (mConstraintController != null) {
2081 mConstraintController.start();
2082 }
2083
Joe LaPenna23d681b2015-08-27 15:12:11 -07002084 float angleThreshold = getContext().getResources().getInteger(
2085 com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
Kweku Adams00e3a372018-09-28 16:57:09 -07002086 mAnyMotionDetector = mInjector.getAnyMotionDetector(mHandler, mSensorManager, this,
2087 angleThreshold);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002088
Makoto Onukie4918212018-02-06 11:30:15 -08002089 mAppStateTracker.onSystemServicesReady();
2090
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002091 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002092 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
2093 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002094 mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
2095 mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
2096 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002097
2098 IntentFilter filter = new IntentFilter();
2099 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002100 getContext().registerReceiver(mReceiver, filter);
Amith Yamasaniac59f75e2016-05-05 12:38:17 -07002101
Dianne Hackborn1b79ad72015-10-12 10:59:47 -07002102 filter = new IntentFilter();
2103 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2104 filter.addDataScheme("package");
Amith Yamasaniac59f75e2016-05-05 12:38:17 -07002105 getContext().registerReceiver(mReceiver, filter);
2106
Dianne Hackborn88c41352016-04-07 15:18:58 -07002107 filter = new IntentFilter();
2108 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Dianne Hackborn1b79ad72015-10-12 10:59:47 -07002109 getContext().registerReceiver(mReceiver, filter);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002110
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -07002111 filter = new IntentFilter();
2112 filter.addAction(Intent.ACTION_SCREEN_OFF);
2113 filter.addAction(Intent.ACTION_SCREEN_ON);
2114 getContext().registerReceiver(mInteractivityReceiver, filter);
2115
Makoto Onukiaf8ff4f2018-06-04 14:44:19 -07002116 mLocalActivityManager.setDeviceIdleWhitelist(
2117 mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002118 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -07002119
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002120 mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE,
2121 state -> {
2122 synchronized (DeviceIdleController.this) {
2123 updateQuickDozeFlagLocked(state.batterySaverEnabled);
2124 }
2125 });
2126 updateQuickDozeFlagLocked(
2127 mLocalPowerManager.getLowPowerState(
2128 ServiceType.QUICK_DOZE).batterySaverEnabled);
2129
Wale Ogunwale6767eae2018-05-03 15:52:51 -07002130 mLocalActivityTaskManager.registerScreenObserver(mScreenObserver);
Amith Yamasani396a10c2018-01-19 10:58:07 -08002131
Suprabh Shukla5bf49812018-05-24 18:38:50 -07002132 passWhiteListsToForceAppStandbyTrackerLocked();
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -07002133 updateInteractivityLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002134 }
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -07002135 updateConnectivityState(null);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002136 }
2137 }
2138
Robin Lee876b88542018-11-13 17:22:24 +01002139 @VisibleForTesting
2140 boolean hasMotionSensor() {
2141 return mUseMotionSensor && mMotionSensor != null;
2142 }
2143
2144 private void registerDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint,
2145 final String name, final int type) {
2146 final int minState;
2147 switch (type) {
2148 case IDeviceIdleConstraint.ACTIVE:
2149 minState = STATE_ACTIVE;
2150 break;
2151 case IDeviceIdleConstraint.SENSING_OR_ABOVE:
2152 minState = STATE_SENSING;
2153 break;
2154 default:
2155 Slog.wtf(TAG, "Registering device-idle constraint with invalid type: " + type);
2156 return;
2157 }
2158 synchronized (this) {
2159 if (mConstraints.containsKey(constraint)) {
2160 Slog.e(TAG, "Re-registering device-idle constraint: " + constraint + ".");
2161 return;
2162 }
2163 DeviceIdleConstraintTracker tracker = new DeviceIdleConstraintTracker(name, minState);
2164 mConstraints.put(constraint, tracker);
2165 updateActiveConstraintsLocked();
2166 }
2167 }
2168
2169 private void unregisterDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint) {
2170 synchronized (this) {
Kweku Adamsecf98fb2019-07-22 17:12:41 -07002171 // Artificially force the constraint to inactive to unblock anything waiting for it.
Robin Lee876b88542018-11-13 17:22:24 +01002172 onConstraintStateChangedLocked(constraint, /* active= */ false);
2173
2174 // Let the constraint know that we are not listening to it any more.
2175 setConstraintMonitoringLocked(constraint, /* monitoring= */ false);
2176 mConstraints.remove(constraint);
2177 }
2178 }
2179
2180 @GuardedBy("this")
2181 private void onConstraintStateChangedLocked(IDeviceIdleConstraint constraint, boolean active) {
2182 DeviceIdleConstraintTracker tracker = mConstraints.get(constraint);
2183 if (tracker == null) {
2184 Slog.e(TAG, "device-idle constraint " + constraint + " has not been registered.");
2185 return;
2186 }
2187 if (active != tracker.active && tracker.monitoring) {
2188 tracker.active = active;
2189 mNumBlockingConstraints += (tracker.active ? +1 : -1);
2190 if (mNumBlockingConstraints == 0) {
2191 if (mState == STATE_ACTIVE) {
2192 becomeInactiveIfAppropriateLocked();
2193 } else if (mNextAlarmTime == 0 || mNextAlarmTime < SystemClock.elapsedRealtime()) {
2194 stepIdleStateLocked("s:" + tracker.name);
2195 }
2196 }
2197 }
2198 }
2199
2200 @GuardedBy("this")
2201 private void setConstraintMonitoringLocked(IDeviceIdleConstraint constraint, boolean monitor) {
2202 DeviceIdleConstraintTracker tracker = mConstraints.get(constraint);
2203 if (tracker.monitoring != monitor) {
2204 tracker.monitoring = monitor;
2205 updateActiveConstraintsLocked();
2206 // We send the callback on a separate thread instead of just relying on oneway as
2207 // the client could be in the system server with us and cause re-entry problems.
2208 mHandler.obtainMessage(MSG_SEND_CONSTRAINT_MONITORING,
2209 /* monitoring= */ monitor ? 1 : 0,
2210 /* <not used>= */ -1,
2211 /* constraint= */ constraint).sendToTarget();
2212 }
2213 }
2214
2215 @GuardedBy("this")
2216 private void updateActiveConstraintsLocked() {
2217 mNumBlockingConstraints = 0;
2218 for (int i = 0; i < mConstraints.size(); i++) {
2219 final IDeviceIdleConstraint constraint = mConstraints.keyAt(i);
2220 final DeviceIdleConstraintTracker tracker = mConstraints.valueAt(i);
2221 final boolean monitoring = (tracker.minState == mState);
2222 if (monitoring != tracker.monitoring) {
2223 setConstraintMonitoringLocked(constraint, monitoring);
2224 tracker.active = monitoring;
2225 }
2226 if (tracker.monitoring && tracker.active) {
2227 mNumBlockingConstraints++;
2228 }
2229 }
2230 }
2231
Kweku Adamsc2400c82019-10-09 15:56:04 -07002232 private int addPowerSaveWhitelistAppsInternal(List<String> pkgNames) {
2233 int numAdded = 0;
2234 int numErrors = 0;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002235 synchronized (this) {
Kweku Adamsc2400c82019-10-09 15:56:04 -07002236 for (int i = pkgNames.size() - 1; i >= 0; --i) {
2237 final String name = pkgNames.get(i);
2238 if (name == null) {
2239 numErrors++;
2240 continue;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002241 }
Kweku Adamsc2400c82019-10-09 15:56:04 -07002242 try {
2243 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
2244 PackageManager.MATCH_ANY_USER);
2245 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid))
2246 == null) {
2247 numAdded++;
2248 }
2249 } catch (PackageManager.NameNotFoundException e) {
2250 Slog.e(TAG, "Tried to add unknown package to power save whitelist: " + name);
2251 numErrors++;
2252 }
2253 }
2254 if (numAdded > 0) {
2255 reportPowerSaveWhitelistChangedLocked();
2256 updateWhitelistAppIdsLocked();
2257 writeConfigFileLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002258 }
2259 }
Kweku Adamsc2400c82019-10-09 15:56:04 -07002260 return pkgNames.size() - numErrors;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002261 }
2262
2263 public boolean removePowerSaveWhitelistAppInternal(String name) {
2264 synchronized (this) {
2265 if (mPowerSaveWhitelistUserApps.remove(name) != null) {
2266 reportPowerSaveWhitelistChangedLocked();
2267 updateWhitelistAppIdsLocked();
2268 writeConfigFileLocked();
2269 return true;
2270 }
2271 }
2272 return false;
2273 }
2274
Felipe Lemef8a46232016-02-10 13:51:54 -08002275 public boolean getPowerSaveWhitelistAppInternal(String name) {
2276 synchronized (this) {
2277 return mPowerSaveWhitelistUserApps.containsKey(name);
2278 }
2279 }
2280
Suprabh Shukla08105642017-09-26 14:45:30 -07002281 void resetSystemPowerWhitelistInternal() {
2282 synchronized (this) {
2283 mPowerSaveWhitelistApps.putAll(mRemovedFromSystemWhitelistApps);
2284 mRemovedFromSystemWhitelistApps.clear();
2285 reportPowerSaveWhitelistChangedLocked();
2286 updateWhitelistAppIdsLocked();
2287 writeConfigFileLocked();
2288 }
2289 }
2290
2291 public boolean restoreSystemPowerWhitelistAppInternal(String name) {
2292 synchronized (this) {
2293 if (!mRemovedFromSystemWhitelistApps.containsKey(name)) {
2294 return false;
2295 }
2296 mPowerSaveWhitelistApps.put(name, mRemovedFromSystemWhitelistApps.remove(name));
2297 reportPowerSaveWhitelistChangedLocked();
2298 updateWhitelistAppIdsLocked();
2299 writeConfigFileLocked();
2300 return true;
2301 }
2302 }
2303
2304 public boolean removeSystemPowerWhitelistAppInternal(String name) {
2305 synchronized (this) {
2306 if (!mPowerSaveWhitelistApps.containsKey(name)) {
2307 return false;
2308 }
2309 mRemovedFromSystemWhitelistApps.put(name, mPowerSaveWhitelistApps.remove(name));
2310 reportPowerSaveWhitelistChangedLocked();
2311 updateWhitelistAppIdsLocked();
2312 writeConfigFileLocked();
2313 return true;
2314 }
2315 }
2316
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07002317 public boolean addPowerSaveWhitelistExceptIdleInternal(String name) {
2318 synchronized (this) {
2319 try {
2320 final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
2321 PackageManager.MATCH_ANY_USER);
2322 if (mPowerSaveWhitelistAppsExceptIdle.put(name, UserHandle.getAppId(ai.uid))
2323 == null) {
2324 mPowerSaveWhitelistUserAppsExceptIdle.add(name);
2325 reportPowerSaveWhitelistChangedLocked();
2326 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
2327 mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
2328 mPowerSaveWhitelistExceptIdleAppIds);
Makoto Onuki71755c92018-01-16 14:15:44 -08002329
Suprabh Shukla5bf49812018-05-24 18:38:50 -07002330 passWhiteListsToForceAppStandbyTrackerLocked();
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07002331 }
2332 return true;
2333 } catch (PackageManager.NameNotFoundException e) {
2334 return false;
2335 }
2336 }
2337 }
2338
2339 public void resetPowerSaveWhitelistExceptIdleInternal() {
2340 synchronized (this) {
2341 if (mPowerSaveWhitelistAppsExceptIdle.removeAll(
2342 mPowerSaveWhitelistUserAppsExceptIdle)) {
2343 reportPowerSaveWhitelistChangedLocked();
2344 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
2345 mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
2346 mPowerSaveWhitelistExceptIdleAppIds);
2347 mPowerSaveWhitelistUserAppsExceptIdle.clear();
Makoto Onuki71755c92018-01-16 14:15:44 -08002348
Suprabh Shukla5bf49812018-05-24 18:38:50 -07002349 passWhiteListsToForceAppStandbyTrackerLocked();
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07002350 }
2351 }
2352 }
2353
2354 public boolean getPowerSaveWhitelistExceptIdleInternal(String name) {
2355 synchronized (this) {
2356 return mPowerSaveWhitelistAppsExceptIdle.containsKey(name);
2357 }
2358 }
2359
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002360 public String[] getSystemPowerWhitelistExceptIdleInternal() {
2361 synchronized (this) {
2362 int size = mPowerSaveWhitelistAppsExceptIdle.size();
2363 String[] apps = new String[size];
2364 for (int i = 0; i < size; i++) {
2365 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
2366 }
2367 return apps;
2368 }
2369 }
2370
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002371 public String[] getSystemPowerWhitelistInternal() {
2372 synchronized (this) {
2373 int size = mPowerSaveWhitelistApps.size();
2374 String[] apps = new String[size];
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002375 for (int i = 0; i < size; i++) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002376 apps[i] = mPowerSaveWhitelistApps.keyAt(i);
2377 }
2378 return apps;
2379 }
2380 }
2381
Suprabh Shukla08105642017-09-26 14:45:30 -07002382 public String[] getRemovedSystemPowerWhitelistAppsInternal() {
2383 synchronized (this) {
2384 int size = mRemovedFromSystemWhitelistApps.size();
2385 final String[] apps = new String[size];
2386 for (int i = 0; i < size; i++) {
2387 apps[i] = mRemovedFromSystemWhitelistApps.keyAt(i);
2388 }
2389 return apps;
2390 }
2391 }
2392
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08002393 public String[] getUserPowerWhitelistInternal() {
2394 synchronized (this) {
2395 int size = mPowerSaveWhitelistUserApps.size();
2396 String[] apps = new String[size];
2397 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2398 apps[i] = mPowerSaveWhitelistUserApps.keyAt(i);
2399 }
2400 return apps;
2401 }
2402 }
2403
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002404 public String[] getFullPowerWhitelistExceptIdleInternal() {
2405 synchronized (this) {
2406 int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
2407 String[] apps = new String[size];
2408 int cur = 0;
2409 for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
2410 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
2411 cur++;
2412 }
2413 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2414 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
2415 cur++;
2416 }
2417 return apps;
2418 }
2419 }
2420
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002421 public String[] getFullPowerWhitelistInternal() {
2422 synchronized (this) {
2423 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
2424 String[] apps = new String[size];
2425 int cur = 0;
2426 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
2427 apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
2428 cur++;
2429 }
2430 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2431 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
2432 cur++;
2433 }
2434 return apps;
2435 }
2436 }
2437
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002438 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
2439 synchronized (this) {
2440 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
2441 || mPowerSaveWhitelistUserApps.containsKey(packageName);
2442 }
2443 }
2444
Amith Yamasani06bf8242015-05-08 16:36:21 -07002445 public boolean isPowerSaveWhitelistAppInternal(String packageName) {
2446 synchronized (this) {
2447 return mPowerSaveWhitelistApps.containsKey(packageName)
2448 || mPowerSaveWhitelistUserApps.containsKey(packageName);
2449 }
2450 }
2451
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002452 public int[] getAppIdWhitelistExceptIdleInternal() {
2453 synchronized (this) {
2454 return mPowerSaveWhitelistExceptIdleAppIdArray;
2455 }
2456 }
2457
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002458 public int[] getAppIdWhitelistInternal() {
2459 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002460 return mPowerSaveWhitelistAllAppIdArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002461 }
2462 }
2463
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08002464 public int[] getAppIdUserWhitelistInternal() {
2465 synchronized (this) {
2466 return mPowerSaveWhitelistUserAppIdArray;
2467 }
2468 }
2469
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002470 public int[] getAppIdTempWhitelistInternal() {
2471 synchronized (this) {
2472 return mTempWhitelistAppIdArray;
2473 }
2474 }
2475
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002476 void addPowerSaveTempWhitelistAppChecked(String packageName, long duration,
2477 int userId, String reason) throws RemoteException {
2478 getContext().enforceCallingPermission(
2479 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
2480 "No permission to change device idle whitelist");
2481 final int callingUid = Binder.getCallingUid();
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002482 userId = ActivityManager.getService().handleIncomingUser(
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002483 Binder.getCallingPid(),
2484 callingUid,
2485 userId,
2486 /*allowAll=*/ false,
2487 /*requireFull=*/ false,
2488 "addPowerSaveTempWhitelistApp", null);
2489 final long token = Binder.clearCallingIdentity();
2490 try {
2491 addPowerSaveTempWhitelistAppInternal(callingUid,
2492 packageName, duration, userId, true, reason);
2493 } finally {
2494 Binder.restoreCallingIdentity(token);
2495 }
2496 }
2497
Sudheer Shanka326b3112017-11-27 14:40:57 -08002498 void removePowerSaveTempWhitelistAppChecked(String packageName, int userId)
2499 throws RemoteException {
2500 getContext().enforceCallingPermission(
2501 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
2502 "No permission to change device idle whitelist");
2503 final int callingUid = Binder.getCallingUid();
2504 userId = ActivityManager.getService().handleIncomingUser(
2505 Binder.getCallingPid(),
2506 callingUid,
2507 userId,
2508 /*allowAll=*/ false,
2509 /*requireFull=*/ false,
2510 "removePowerSaveTempWhitelistApp", null);
2511 final long token = Binder.clearCallingIdentity();
2512 try {
2513 removePowerSaveTempWhitelistAppInternal(packageName, userId);
2514 } finally {
2515 Binder.restoreCallingIdentity(token);
2516 }
2517 }
2518
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002519 /**
2520 * Adds an app to the temporary whitelist and resets the endTime for granting the
2521 * app an exemption to access network and acquire wakelocks.
2522 */
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002523 void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002524 long duration, int userId, boolean sync, String reason) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002525 try {
Jeff Sharkeye06b4d12016-01-06 14:51:50 -07002526 int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId);
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002527 addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, duration, sync, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002528 } catch (NameNotFoundException e) {
2529 }
2530 }
2531
Dianne Hackborna750a632015-06-16 17:18:23 -07002532 /**
2533 * Adds an app to the temporary whitelist and resets the endTime for granting the
2534 * app an exemption to access network and acquire wakelocks.
2535 */
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002536 void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int uid,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002537 long duration, boolean sync, String reason) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002538 final long timeNow = SystemClock.elapsedRealtime();
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07002539 boolean informWhitelistChanged = false;
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002540 int appId = UserHandle.getAppId(uid);
Dianne Hackborna750a632015-06-16 17:18:23 -07002541 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002542 int callingAppId = UserHandle.getAppId(callingUid);
2543 if (callingAppId >= Process.FIRST_APPLICATION_UID) {
2544 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
2545 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
2546 + " is not on whitelist");
2547 }
2548 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002549 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002550 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
2551 final boolean newEntry = entry == null;
Dianne Hackborna750a632015-06-16 17:18:23 -07002552 // Set the new end time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002553 if (newEntry) {
2554 entry = new Pair<>(new MutableLong(0), reason);
2555 mTempWhitelistAppIdEndTimes.put(appId, entry);
2556 }
2557 entry.first.value = timeNow + duration;
Dianne Hackborna750a632015-06-16 17:18:23 -07002558 if (DEBUG) {
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002559 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist. New entry: " + newEntry);
Dianne Hackborna750a632015-06-16 17:18:23 -07002560 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002561 if (newEntry) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002562 // No pending timeout for the app id, post a delayed message
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002563 try {
2564 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002565 reason, uid);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002566 } catch (RemoteException e) {
2567 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002568 postTempActiveTimeoutMessage(appId, duration);
Dianne Hackborn85e35642017-01-12 15:10:57 -08002569 updateTempWhitelistAppIdsLocked(appId, true);
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07002570 if (sync) {
2571 informWhitelistChanged = true;
2572 } else {
2573 mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED, appId, 1)
2574 .sendToTarget();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002575 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002576 reportTempWhitelistChangedLocked();
2577 }
2578 }
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07002579 if (informWhitelistChanged) {
2580 mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002581 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002582 }
2583
Sudheer Shanka326b3112017-11-27 14:40:57 -08002584 /**
2585 * Removes an app from the temporary whitelist and notifies the observers.
2586 */
2587 private void removePowerSaveTempWhitelistAppInternal(String packageName, int userId) {
2588 try {
2589 final int uid = getContext().getPackageManager().getPackageUidAsUser(
2590 packageName, userId);
2591 final int appId = UserHandle.getAppId(uid);
2592 removePowerSaveTempWhitelistAppDirectInternal(appId);
2593 } catch (NameNotFoundException e) {
2594 }
2595 }
2596
2597 private void removePowerSaveTempWhitelistAppDirectInternal(int appId) {
2598 synchronized (this) {
2599 final int idx = mTempWhitelistAppIdEndTimes.indexOfKey(appId);
2600 if (idx < 0) {
2601 // Nothing else to do
2602 return;
2603 }
2604 final String reason = mTempWhitelistAppIdEndTimes.valueAt(idx).second;
2605 mTempWhitelistAppIdEndTimes.removeAt(idx);
2606 onAppRemovedFromTempWhitelistLocked(appId, reason);
2607 }
2608 }
2609
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002610 private void postTempActiveTimeoutMessage(int appId, long delay) {
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002611 if (DEBUG) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002612 Slog.d(TAG, "postTempActiveTimeoutMessage: appId=" + appId + ", delay=" + delay);
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002613 }
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002614 mHandler.sendMessageDelayed(
2615 mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, appId, 0), delay);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002616 }
2617
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002618 void checkTempAppWhitelistTimeout(int appId) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002619 final long timeNow = SystemClock.elapsedRealtime();
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002620 if (DEBUG) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002621 Slog.d(TAG, "checkTempAppWhitelistTimeout: appId=" + appId + ", timeNow=" + timeNow);
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002622 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002623 synchronized (this) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002624 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002625 if (entry == null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002626 // Nothing to do
2627 return;
2628 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002629 if (timeNow >= entry.first.value) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002630 mTempWhitelistAppIdEndTimes.delete(appId);
2631 onAppRemovedFromTempWhitelistLocked(appId, entry.second);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002632 } else {
2633 // Need more time
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002634 if (DEBUG) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002635 Slog.d(TAG, "Time to remove AppId " + appId + ": " + entry.first.value);
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002636 }
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002637 postTempActiveTimeoutMessage(appId, entry.first.value - timeNow);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002638 }
2639 }
2640 }
2641
Sudheer Shanka326b3112017-11-27 14:40:57 -08002642 @GuardedBy("this")
2643 private void onAppRemovedFromTempWhitelistLocked(int appId, String reason) {
2644 if (DEBUG) {
2645 Slog.d(TAG, "Removing appId " + appId + " from temp whitelist");
2646 }
2647 updateTempWhitelistAppIdsLocked(appId, false);
2648 mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED, appId, 0)
2649 .sendToTarget();
2650 reportTempWhitelistChangedLocked();
2651 try {
2652 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
2653 reason, appId);
2654 } catch (RemoteException e) {
2655 }
2656 }
2657
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002658 public void exitIdleInternal(String reason) {
2659 synchronized (this) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002660 mActiveReason = ACTIVE_REASON_FROM_BINDER_CALL;
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002661 becomeActiveLocked(reason, Binder.getCallingUid());
2662 }
2663 }
2664
Kweku Adams799858b2018-10-08 17:19:08 -07002665 @VisibleForTesting
2666 boolean isNetworkConnected() {
2667 synchronized (this) {
2668 return mNetworkConnected;
2669 }
2670 }
2671
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -07002672 void updateConnectivityState(Intent connIntent) {
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07002673 ConnectivityManager cm;
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -07002674 synchronized (this) {
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07002675 cm = mInjector.getConnectivityManager();
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -07002676 }
2677 if (cm == null) {
2678 return;
2679 }
2680 // Note: can't call out to ConnectivityService with our lock held.
2681 NetworkInfo ni = cm.getActiveNetworkInfo();
2682 synchronized (this) {
Dianne Hackborn88c41352016-04-07 15:18:58 -07002683 boolean conn;
2684 if (ni == null) {
2685 conn = false;
2686 } else {
2687 if (connIntent == null) {
2688 conn = ni.isConnected();
2689 } else {
2690 final int networkType =
2691 connIntent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
2692 ConnectivityManager.TYPE_NONE);
2693 if (ni.getType() != networkType) {
2694 return;
2695 }
2696 conn = !connIntent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
2697 false);
2698 }
2699 }
2700 if (conn != mNetworkConnected) {
2701 mNetworkConnected = conn;
2702 if (conn && mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
2703 stepLightIdleStateLocked("network");
2704 }
2705 }
2706 }
2707 }
2708
Kweku Adams00e3a372018-09-28 16:57:09 -07002709 @VisibleForTesting
2710 boolean isScreenOn() {
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002711 synchronized (this) {
2712 return mScreenOn;
2713 }
Kweku Adams00e3a372018-09-28 16:57:09 -07002714 }
2715
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -07002716 void updateInteractivityLocked() {
2717 // The interactivity state from the power manager tells us whether the display is
2718 // in a state that we need to keep things running so they will update at a normal
2719 // frequency.
2720 boolean screenOn = mPowerManager.isInteractive();
2721 if (DEBUG) Slog.d(TAG, "updateInteractivityLocked: screenOn=" + screenOn);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002722 if (!screenOn && mScreenOn) {
2723 mScreenOn = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002724 if (!mForceIdle) {
2725 becomeInactiveIfAppropriateLocked();
2726 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002727 } else if (screenOn) {
2728 mScreenOn = true;
Amith Yamasani396a10c2018-01-19 10:58:07 -08002729 if (!mForceIdle && (!mScreenLocked || !mConstants.WAIT_FOR_UNLOCK)) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002730 mActiveReason = ACTIVE_REASON_SCREEN;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002731 becomeActiveLocked("screen", Process.myUid());
2732 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002733 }
2734 }
2735
Kweku Adams00e3a372018-09-28 16:57:09 -07002736 @VisibleForTesting
2737 boolean isCharging() {
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002738 synchronized (this) {
2739 return mCharging;
2740 }
Kweku Adams00e3a372018-09-28 16:57:09 -07002741 }
2742
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002743 void updateChargingLocked(boolean charging) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07002744 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002745 if (!charging && mCharging) {
2746 mCharging = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002747 if (!mForceIdle) {
2748 becomeInactiveIfAppropriateLocked();
2749 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002750 } else if (charging) {
2751 mCharging = charging;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002752 if (!mForceIdle) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002753 mActiveReason = ACTIVE_REASON_CHARGING;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002754 becomeActiveLocked("charging", Process.myUid());
2755 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002756 }
2757 }
2758
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002759 @VisibleForTesting
2760 boolean isQuickDozeEnabled() {
2761 synchronized (this) {
2762 return mQuickDozeActivated;
2763 }
2764 }
2765
2766 /** Updates the quick doze flag and enters deep doze if appropriate. */
2767 @VisibleForTesting
2768 void updateQuickDozeFlagLocked(boolean enabled) {
2769 if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
2770 mQuickDozeActivated = enabled;
Kweku Adams810c77d2019-08-28 07:45:00 -07002771 mQuickDozeActivatedWhileIdling =
2772 mQuickDozeActivated && (mState == STATE_IDLE || mState == STATE_IDLE_MAINTENANCE);
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002773 if (enabled) {
2774 // If Quick Doze is enabled, see if we should go straight into it.
2775 becomeInactiveIfAppropriateLocked();
2776 }
2777 // Going from Deep Doze to Light Idle (if quick doze becomes disabled) is tricky and
2778 // probably not worth the overhead, so leave in deep doze if that's the case until the
2779 // next natural time to come out of it.
2780 }
2781
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002782
2783 /** Returns true if the screen is locked. */
2784 @VisibleForTesting
2785 boolean isKeyguardShowing() {
2786 synchronized (this) {
2787 return mScreenLocked;
2788 }
2789 }
2790
2791 @VisibleForTesting
Amith Yamasani396a10c2018-01-19 10:58:07 -08002792 void keyguardShowingLocked(boolean showing) {
2793 if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing);
2794 if (mScreenLocked != showing) {
2795 mScreenLocked = showing;
2796 if (mScreenOn && !mForceIdle && !mScreenLocked) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002797 mActiveReason = ACTIVE_REASON_UNLOCKED;
Amith Yamasani396a10c2018-01-19 10:58:07 -08002798 becomeActiveLocked("unlocked", Process.myUid());
2799 }
2800 }
2801 }
2802
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002803 @VisibleForTesting
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002804 void scheduleReportActiveLocked(String activeReason, int activeUid) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002805 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002806 mHandler.sendMessage(msg);
2807 }
2808
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002809 void becomeActiveLocked(String activeReason, int activeUid) {
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002810 becomeActiveLocked(activeReason, activeUid, mConstants.INACTIVE_TIMEOUT, true);
2811 }
2812
2813 private void becomeActiveLocked(String activeReason, int activeUid,
2814 long newInactiveTimeout, boolean changeLightIdle) {
2815 if (DEBUG) {
2816 Slog.i(TAG, "becomeActiveLocked, reason=" + activeReason
2817 + ", changeLightIdle=" + changeLightIdle);
2818 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002819 if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002820 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002821 mState = STATE_ACTIVE;
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002822 mInactiveTimeout = newInactiveTimeout;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002823 resetIdleManagementLocked();
Kweku Adams7c96f5182019-06-04 16:32:49 -07002824 // Don't reset maintenance window start time if we're in a light idle maintenance window
2825 // because its used in the light idle budget calculation.
2826 if (mLightState != LIGHT_STATE_IDLE_MAINTENANCE) {
2827 mMaintenanceStartTime = 0;
2828 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002829
2830 if (changeLightIdle) {
2831 EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
2832 mLightState = LIGHT_STATE_ACTIVE;
2833 resetLightIdleManagementLocked();
2834 // Only report active if light is also ACTIVE.
2835 scheduleReportActiveLocked(activeReason, activeUid);
2836 addEvent(EVENT_NORMAL, activeReason);
2837 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002838 }
2839 }
2840
Kweku Adams00e3a372018-09-28 16:57:09 -07002841 /** Must only be used in tests. */
2842 @VisibleForTesting
2843 void setDeepEnabledForTest(boolean enabled) {
Kweku Adams799858b2018-10-08 17:19:08 -07002844 synchronized (this) {
2845 mDeepEnabled = enabled;
2846 }
Kweku Adams00e3a372018-09-28 16:57:09 -07002847 }
2848
2849 /** Must only be used in tests. */
2850 @VisibleForTesting
2851 void setLightEnabledForTest(boolean enabled) {
Kweku Adams799858b2018-10-08 17:19:08 -07002852 synchronized (this) {
2853 mLightEnabled = enabled;
2854 }
Kweku Adams00e3a372018-09-28 16:57:09 -07002855 }
2856
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002857 /** Sanity check to make sure DeviceIdleController and AlarmManager are on the same page. */
2858 private void verifyAlarmStateLocked() {
2859 if (mState == STATE_ACTIVE && mNextAlarmTime != 0) {
2860 Slog.wtf(TAG, "mState=ACTIVE but mNextAlarmTime=" + mNextAlarmTime);
2861 }
2862 if (mState != STATE_IDLE && mLocalAlarmManager.isIdling()) {
2863 Slog.wtf(TAG, "mState=" + stateToString(mState) + " but AlarmManager is idling");
2864 }
2865 if (mState == STATE_IDLE && !mLocalAlarmManager.isIdling()) {
2866 Slog.wtf(TAG, "mState=IDLE but AlarmManager is not idling");
2867 }
2868 if (mLightState == LIGHT_STATE_ACTIVE && mNextLightAlarmTime != 0) {
2869 Slog.wtf(TAG, "mLightState=ACTIVE but mNextLightAlarmTime is "
2870 + TimeUtils.formatDuration(mNextLightAlarmTime - SystemClock.elapsedRealtime())
2871 + " from now");
2872 }
2873 }
2874
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002875 void becomeInactiveIfAppropriateLocked() {
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002876 verifyAlarmStateLocked();
2877
2878 final boolean isScreenBlockingInactive =
2879 mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked);
2880 if (DEBUG) {
2881 Slog.d(TAG, "becomeInactiveIfAppropriateLocked():"
2882 + " isScreenBlockingInactive=" + isScreenBlockingInactive
2883 + " (mScreenOn=" + mScreenOn
2884 + ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK
2885 + ", mScreenLocked=" + mScreenLocked + ")"
2886 + " mCharging=" + mCharging
2887 + " mForceIdle=" + mForceIdle
2888 );
2889 }
2890 if (!mForceIdle && (mCharging || isScreenBlockingInactive)) {
2891 return;
2892 }
2893 // Become inactive and determine if we will ultimately go idle.
2894 if (mDeepEnabled) {
2895 if (mQuickDozeActivated) {
2896 if (mState == STATE_QUICK_DOZE_DELAY || mState == STATE_IDLE
2897 || mState == STATE_IDLE_MAINTENANCE) {
2898 // Already "idling". Don't want to restart the process.
2899 // mLightState can't be LIGHT_STATE_ACTIVE if mState is any of these 3
2900 // values, so returning here is safe.
2901 return;
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002902 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002903 if (DEBUG) {
2904 Slog.d(TAG, "Moved from "
2905 + stateToString(mState) + " to STATE_QUICK_DOZE_DELAY");
2906 }
2907 mState = STATE_QUICK_DOZE_DELAY;
2908 // Make sure any motion sensing or locating is stopped.
2909 resetIdleManagementLocked();
Kweku Adamsecf98fb2019-07-22 17:12:41 -07002910 if (isUpcomingAlarmClock()) {
2911 // If there's an upcoming AlarmClock alarm, we won't go into idle, so
2912 // setting a wakeup alarm before the upcoming alarm is futile. Set the quick
2913 // doze alarm to after the upcoming AlarmClock alarm.
2914 scheduleAlarmLocked(
2915 mAlarmManager.getNextWakeFromIdleTime() - mInjector.getElapsedRealtime()
2916 + mConstants.QUICK_DOZE_DELAY_TIMEOUT, false);
2917 } else {
2918 // Wait a small amount of time in case something (eg: background service from
2919 // recently closed app) needs to finish running.
2920 scheduleAlarmLocked(mConstants.QUICK_DOZE_DELAY_TIMEOUT, false);
2921 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002922 EventLogTags.writeDeviceIdle(mState, "no activity");
2923 } else if (mState == STATE_ACTIVE) {
2924 mState = STATE_INACTIVE;
2925 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
2926 resetIdleManagementLocked();
2927 long delay = mInactiveTimeout;
2928 if (shouldUseIdleTimeoutFactorLocked()) {
2929 delay = (long) (mPreIdleFactor * delay);
2930 }
Kweku Adamsecf98fb2019-07-22 17:12:41 -07002931 if (isUpcomingAlarmClock()) {
2932 // If there's an upcoming AlarmClock alarm, we won't go into idle, so
2933 // setting a wakeup alarm before the upcoming alarm is futile. Set the idle
2934 // alarm to after the upcoming AlarmClock alarm.
2935 scheduleAlarmLocked(
2936 mAlarmManager.getNextWakeFromIdleTime() - mInjector.getElapsedRealtime()
2937 + delay, false);
2938 } else {
2939 scheduleAlarmLocked(delay, false);
2940 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002941 EventLogTags.writeDeviceIdle(mState, "no activity");
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002942 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002943 }
2944 if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
2945 mLightState = LIGHT_STATE_INACTIVE;
2946 if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
2947 resetLightIdleManagementLocked();
2948 scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
2949 EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002950 }
2951 }
2952
Kweku Adams00e3a372018-09-28 16:57:09 -07002953 private void resetIdleManagementLocked() {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002954 mNextIdlePendingDelay = 0;
2955 mNextIdleDelay = 0;
Denny cy Leec5a7c292019-01-01 17:37:55 +08002956 mIdleStartTime = 0;
Kweku Adams810c77d2019-08-28 07:45:00 -07002957 mQuickDozeActivatedWhileIdling = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002958 cancelAlarmLocked();
Kevin Gabayan92f15e62016-04-04 17:52:22 -07002959 cancelSensingTimeoutAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002960 cancelLocatingLocked();
Kweku Adams810c77d2019-08-28 07:45:00 -07002961 maybeStopMonitoringMotionLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002962 mAnyMotionDetector.stop();
Robin Lee876b88542018-11-13 17:22:24 +01002963 updateActiveConstraintsLocked();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07002964 }
2965
Kweku Adams00e3a372018-09-28 16:57:09 -07002966 private void resetLightIdleManagementLocked() {
Kweku Adams7c96f5182019-06-04 16:32:49 -07002967 mNextLightIdleDelay = 0;
2968 mCurLightIdleBudget = 0;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002969 cancelLightAlarmLocked();
2970 }
2971
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002972 void exitForceIdleLocked() {
2973 if (mForceIdle) {
2974 mForceIdle = false;
2975 if (mScreenOn || mCharging) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002976 mActiveReason = ACTIVE_REASON_FORCED;
Dianne Hackborn88c41352016-04-07 15:18:58 -07002977 becomeActiveLocked("exit-force", Process.myUid());
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002978 }
2979 }
2980 }
2981
Kweku Adamsa457f4e2018-10-03 15:56:06 -07002982 /**
2983 * Must only be used in tests.
2984 *
2985 * This sets the state value directly and thus doesn't trigger any behavioral changes.
2986 */
2987 @VisibleForTesting
2988 void setLightStateForTest(int lightState) {
Kweku Adams799858b2018-10-08 17:19:08 -07002989 synchronized (this) {
2990 mLightState = lightState;
2991 }
Kweku Adamsa457f4e2018-10-03 15:56:06 -07002992 }
2993
Kweku Adams00e3a372018-09-28 16:57:09 -07002994 @VisibleForTesting
2995 int getLightState() {
2996 return mLightState;
2997 }
2998
Dianne Hackborn627dfa12015-11-11 18:10:30 -08002999 void stepLightIdleStateLocked(String reason) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003000 if (mLightState == LIGHT_STATE_OVERRIDE) {
Dianne Hackbornb6843652016-02-22 12:20:13 -08003001 // If we are already in deep device idle mode, then
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003002 // there is nothing left to do for light mode.
3003 return;
3004 }
3005
3006 if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState);
3007 EventLogTags.writeDeviceIdleLightStep();
3008
3009 switch (mLightState) {
3010 case LIGHT_STATE_INACTIVE:
Kweku Adams7c96f5182019-06-04 16:32:49 -07003011 mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
Dianne Hackborn953fc942016-03-29 15:36:24 -07003012 // Reset the upcoming idle delays.
3013 mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003014 mMaintenanceStartTime = 0;
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003015 if (!isOpsInactiveLocked()) {
3016 // We have some active ops going on... give them a chance to finish
3017 // before going in to our first idle.
3018 mLightState = LIGHT_STATE_PRE_IDLE;
3019 EventLogTags.writeDeviceIdleLight(mLightState, reason);
3020 scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT);
3021 break;
3022 }
3023 // Nothing active, fall through to immediately idle.
3024 case LIGHT_STATE_PRE_IDLE:
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003025 case LIGHT_STATE_IDLE_MAINTENANCE:
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003026 if (mMaintenanceStartTime != 0) {
3027 long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime;
3028 if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
3029 // We didn't use up all of our minimum budget; add this to the reserve.
Kweku Adams7c96f5182019-06-04 16:32:49 -07003030 mCurLightIdleBudget +=
3031 (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET - duration);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003032 } else {
3033 // We used more than our minimum budget; this comes out of the reserve.
Kweku Adams7c96f5182019-06-04 16:32:49 -07003034 mCurLightIdleBudget -=
3035 (duration - mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003036 }
3037 }
3038 mMaintenanceStartTime = 0;
Dianne Hackborn953fc942016-03-29 15:36:24 -07003039 scheduleLightAlarmLocked(mNextLightIdleDelay);
3040 mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
3041 (long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
3042 if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {
3043 mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
3044 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003045 if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
3046 mLightState = LIGHT_STATE_IDLE;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003047 EventLogTags.writeDeviceIdleLight(mLightState, reason);
Amith Yamasaniac6517a2018-04-23 12:19:34 -07003048 addEvent(EVENT_LIGHT_IDLE, null);
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08003049 mGoingIdleWakeLock.acquire();
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003050 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
3051 break;
3052 case LIGHT_STATE_IDLE:
Dianne Hackborn88c41352016-04-07 15:18:58 -07003053 case LIGHT_STATE_WAITING_FOR_NETWORK:
3054 if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
3055 // We have been idling long enough, now it is time to do some work.
3056 mActiveIdleOpCount = 1;
3057 mActiveIdleWakeLock.acquire();
3058 mMaintenanceStartTime = SystemClock.elapsedRealtime();
Kweku Adams7c96f5182019-06-04 16:32:49 -07003059 if (mCurLightIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
3060 mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
3061 } else if (mCurLightIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
3062 mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
Dianne Hackborn88c41352016-04-07 15:18:58 -07003063 }
Kweku Adams7c96f5182019-06-04 16:32:49 -07003064 scheduleLightAlarmLocked(mCurLightIdleBudget);
Dianne Hackborn88c41352016-04-07 15:18:58 -07003065 if (DEBUG) Slog.d(TAG,
3066 "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
3067 mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
3068 EventLogTags.writeDeviceIdleLight(mLightState, reason);
Amith Yamasaniac6517a2018-04-23 12:19:34 -07003069 addEvent(EVENT_LIGHT_MAINTENANCE, null);
Dianne Hackborn88c41352016-04-07 15:18:58 -07003070 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
3071 } else {
3072 // We'd like to do maintenance, but currently don't have network
3073 // connectivity... let's try to wait until the network comes back.
3074 // We'll only wait for another full idle period, however, and then give up.
3075 scheduleLightAlarmLocked(mNextLightIdleDelay);
3076 if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK.");
3077 mLightState = LIGHT_STATE_WAITING_FOR_NETWORK;
3078 EventLogTags.writeDeviceIdleLight(mLightState, reason);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003079 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003080 break;
3081 }
3082 }
3083
Kweku Adams00e3a372018-09-28 16:57:09 -07003084 @VisibleForTesting
3085 int getState() {
3086 return mState;
3087 }
3088
Kweku Adamsecf98fb2019-07-22 17:12:41 -07003089 /**
3090 * Returns true if there's an upcoming AlarmClock alarm that is soon enough to prevent the
3091 * device from going into idle.
3092 */
3093 private boolean isUpcomingAlarmClock() {
3094 return mInjector.getElapsedRealtime() + mConstants.MIN_TIME_TO_ALARM
3095 >= mAlarmManager.getNextWakeFromIdleTime();
3096 }
3097
Kweku Adams00e3a372018-09-28 16:57:09 -07003098 @VisibleForTesting
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003099 void stepIdleStateLocked(String reason) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003100 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003101 EventLogTags.writeDeviceIdleStep();
3102
Kweku Adamsecf98fb2019-07-22 17:12:41 -07003103 if (isUpcomingAlarmClock()) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003104 // Whoops, there is an upcoming alarm. We don't actually want to go idle.
3105 if (mState != STATE_ACTIVE) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08003106 mActiveReason = ACTIVE_REASON_ALARM;
Dianne Hackbornb6683c42015-06-18 17:40:33 -07003107 becomeActiveLocked("alarm", Process.myUid());
Koji Fukui27b33302015-12-16 19:43:01 +09003108 becomeInactiveIfAppropriateLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003109 }
3110 return;
3111 }
3112
Robin Lee876b88542018-11-13 17:22:24 +01003113 if (mNumBlockingConstraints != 0 && !mForceIdle) {
3114 // We have some constraints from other parts of the system server preventing
3115 // us from moving to the next state.
3116 if (DEBUG) {
3117 Slog.i(TAG, "Cannot step idle state. Blocked by: " + mConstraints.values().stream()
3118 .filter(x -> x.active)
3119 .map(x -> x.name)
3120 .collect(Collectors.joining(",")));
3121 }
3122 return;
3123 }
3124
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003125 switch (mState) {
3126 case STATE_INACTIVE:
3127 // We have now been inactive long enough, it is time to start looking
Nick Vaccaro20feaea2015-09-17 17:22:44 -07003128 // for motion and sleep some more while doing so.
3129 startMonitoringMotionLocked();
Denny cy Leec5a7c292019-01-01 17:37:55 +08003130 long delay = mConstants.IDLE_AFTER_INACTIVE_TIMEOUT;
3131 if (shouldUseIdleTimeoutFactorLocked()) {
3132 delay = (long) (mPreIdleFactor * delay);
3133 }
3134 scheduleAlarmLocked(delay, false);
Robin Lee876b88542018-11-13 17:22:24 +01003135 moveToStateLocked(STATE_IDLE_PENDING, reason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003136 break;
3137 case STATE_IDLE_PENDING:
Robin Lee876b88542018-11-13 17:22:24 +01003138 moveToStateLocked(STATE_SENSING, reason);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003139 cancelLocatingLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003140 mLocated = false;
3141 mLastGenericLocation = null;
3142 mLastGpsLocation = null;
Robin Lee876b88542018-11-13 17:22:24 +01003143 updateActiveConstraintsLocked();
Robin Leec4d424c2018-12-07 15:09:13 +01003144
Robin Lee876b88542018-11-13 17:22:24 +01003145 // Wait for open constraints and an accelerometer reading before moving on.
Robin Leec4d424c2018-12-07 15:09:13 +01003146 if (mUseMotionSensor && mAnyMotionDetector.hasSensor()) {
3147 scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
3148 mNotMoving = false;
3149 mAnyMotionDetector.checkForAnyMotion();
3150 break;
Robin Lee876b88542018-11-13 17:22:24 +01003151 } else if (mNumBlockingConstraints != 0) {
3152 cancelAlarmLocked();
3153 break;
Robin Leec4d424c2018-12-07 15:09:13 +01003154 }
3155
3156 mNotMoving = true;
3157 // Otherwise, fall through and check this off the list of requirements.
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003158 case STATE_SENSING:
Kevin Gabayan92f15e62016-04-04 17:52:22 -07003159 cancelSensingTimeoutAlarmLocked();
Robin Lee876b88542018-11-13 17:22:24 +01003160 moveToStateLocked(STATE_LOCATING, reason);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003161 scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
Kweku Adams799858b2018-10-08 17:19:08 -07003162 LocationManager locationManager = mInjector.getLocationManager();
3163 if (locationManager != null
3164 && locationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
3165 locationManager.requestLocationUpdates(mLocationRequest,
Joe LaPenna23d681b2015-08-27 15:12:11 -07003166 mGenericLocationListener, mHandler.getLooper());
3167 mLocating = true;
3168 } else {
3169 mHasNetworkLocation = false;
3170 }
Kweku Adams799858b2018-10-08 17:19:08 -07003171 if (locationManager != null
3172 && locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
Joe LaPenna23d681b2015-08-27 15:12:11 -07003173 mHasGps = true;
Kweku Adams799858b2018-10-08 17:19:08 -07003174 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003175 mGpsLocationListener, mHandler.getLooper());
Joe LaPenna23d681b2015-08-27 15:12:11 -07003176 mLocating = true;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003177 } else {
Joe LaPenna23d681b2015-08-27 15:12:11 -07003178 mHasGps = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003179 }
Joe LaPenna23d681b2015-08-27 15:12:11 -07003180 // If we have a location provider, we're all set, the listeners will move state
3181 // forward.
3182 if (mLocating) {
3183 break;
3184 }
3185
3186 // Otherwise, we have to move from locating into idle maintenance.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003187 case STATE_LOCATING:
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003188 cancelAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003189 cancelLocatingLocked();
3190 mAnyMotionDetector.stop();
Dianne Hackborn953fc942016-03-29 15:36:24 -07003191
Kweku Adamsb396ccf2018-09-17 16:37:15 -07003192 // Intentional fallthrough -- time to go into IDLE state.
3193 case STATE_QUICK_DOZE_DELAY:
3194 // Reset the upcoming idle delays.
3195 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
3196 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
3197
3198 // Everything is in place to go into IDLE state.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003199 case STATE_IDLE_MAINTENANCE:
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003200 scheduleAlarmLocked(mNextIdleDelay, true);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003201 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
3202 " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07003203 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003204 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
Denny cy Leec5a7c292019-01-01 17:37:55 +08003205 mIdleStartTime = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -07003206 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
Dianne Hackborn953fc942016-03-29 15:36:24 -07003207 if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
3208 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
3209 }
Robin Lee876b88542018-11-13 17:22:24 +01003210 moveToStateLocked(STATE_IDLE, reason);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003211 if (mLightState != LIGHT_STATE_OVERRIDE) {
3212 mLightState = LIGHT_STATE_OVERRIDE;
3213 cancelLightAlarmLocked();
3214 }
Amith Yamasaniac6517a2018-04-23 12:19:34 -07003215 addEvent(EVENT_DEEP_IDLE, null);
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08003216 mGoingIdleWakeLock.acquire();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003217 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
3218 break;
3219 case STATE_IDLE:
3220 // We have been idling long enough, now it is time to do some work.
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003221 mActiveIdleOpCount = 1;
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003222 mActiveIdleWakeLock.acquire();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003223 scheduleAlarmLocked(mNextIdlePendingDelay, false);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003224 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
3225 "Next alarm in " + mNextIdlePendingDelay + " ms.");
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003226 mMaintenanceStartTime = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -07003227 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
3228 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
Dianne Hackborn953fc942016-03-29 15:36:24 -07003229 if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
3230 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
3231 }
Robin Lee876b88542018-11-13 17:22:24 +01003232 moveToStateLocked(STATE_IDLE_MAINTENANCE, reason);
Amith Yamasaniac6517a2018-04-23 12:19:34 -07003233 addEvent(EVENT_DEEP_MAINTENANCE, null);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003234 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
3235 break;
3236 }
3237 }
3238
Robin Lee876b88542018-11-13 17:22:24 +01003239 private void moveToStateLocked(int state, String reason) {
3240 final int oldState = mState;
3241 mState = state;
3242 if (DEBUG) {
3243 Slog.d(TAG, String.format("Moved from STATE_%s to STATE_%s.",
3244 stateToString(oldState), stateToString(mState)));
3245 }
3246 EventLogTags.writeDeviceIdle(mState, reason);
3247 updateActiveConstraintsLocked();
3248 }
3249
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003250 void incActiveIdleOps() {
3251 synchronized (this) {
3252 mActiveIdleOpCount++;
3253 }
3254 }
3255
3256 void decActiveIdleOps() {
3257 synchronized (this) {
3258 mActiveIdleOpCount--;
3259 if (mActiveIdleOpCount <= 0) {
3260 exitMaintenanceEarlyIfNeededLocked();
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003261 mActiveIdleWakeLock.release();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003262 }
3263 }
3264 }
3265
Kweku Adamsa457f4e2018-10-03 15:56:06 -07003266 /** Must only be used in tests. */
3267 @VisibleForTesting
3268 void setActiveIdleOpsForTest(int count) {
Kweku Adams799858b2018-10-08 17:19:08 -07003269 synchronized (this) {
3270 mActiveIdleOpCount = count;
3271 }
Kweku Adamsa457f4e2018-10-03 15:56:06 -07003272 }
3273
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003274 void setJobsActive(boolean active) {
3275 synchronized (this) {
3276 mJobsActive = active;
3277 if (!active) {
3278 exitMaintenanceEarlyIfNeededLocked();
3279 }
3280 }
3281 }
3282
3283 void setAlarmsActive(boolean active) {
3284 synchronized (this) {
3285 mAlarmsActive = active;
3286 if (!active) {
3287 exitMaintenanceEarlyIfNeededLocked();
3288 }
3289 }
3290 }
3291
Denny cy Leec5a7c292019-01-01 17:37:55 +08003292 @VisibleForTesting
3293 int setPreIdleTimeoutMode(int mode) {
3294 return setPreIdleTimeoutFactor(getPreIdleTimeoutByMode(mode));
3295 }
3296
3297 @VisibleForTesting
3298 float getPreIdleTimeoutByMode(int mode) {
3299 switch (mode) {
3300 case PowerManager.PRE_IDLE_TIMEOUT_MODE_LONG: {
3301 return mConstants.PRE_IDLE_FACTOR_LONG;
3302 }
3303 case PowerManager.PRE_IDLE_TIMEOUT_MODE_SHORT: {
3304 return mConstants.PRE_IDLE_FACTOR_SHORT;
3305 }
3306 case PowerManager.PRE_IDLE_TIMEOUT_MODE_NORMAL: {
3307 return 1.0f;
3308 }
3309 default: {
3310 Slog.w(TAG, "Invalid time out factor mode: " + mode);
3311 return 1.0f;
3312 }
3313 }
3314 }
3315
3316 @VisibleForTesting
3317 float getPreIdleTimeoutFactor() {
3318 return mPreIdleFactor;
3319 }
3320
3321 @VisibleForTesting
3322 int setPreIdleTimeoutFactor(float ratio) {
3323 if (!mDeepEnabled) {
3324 if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Deep Idle disable");
3325 return SET_IDLE_FACTOR_RESULT_NOT_SUPPORT;
3326 } else if (ratio <= MIN_PRE_IDLE_FACTOR_CHANGE) {
3327 if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Invalid input");
3328 return SET_IDLE_FACTOR_RESULT_INVALID;
3329 } else if (Math.abs(ratio - mPreIdleFactor) < MIN_PRE_IDLE_FACTOR_CHANGE) {
3330 if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: New factor same as previous factor");
3331 return SET_IDLE_FACTOR_RESULT_IGNORED;
3332 }
3333 synchronized (this) {
3334 mLastPreIdleFactor = mPreIdleFactor;
3335 mPreIdleFactor = ratio;
3336 }
3337 if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: " + ratio);
3338 postUpdatePreIdleFactor();
3339 return SET_IDLE_FACTOR_RESULT_OK;
3340 }
3341
3342 @VisibleForTesting
3343 void resetPreIdleTimeoutMode() {
3344 synchronized (this) {
3345 mLastPreIdleFactor = mPreIdleFactor;
3346 mPreIdleFactor = 1.0f;
3347 }
3348 if (DEBUG) Slog.d(TAG, "resetPreIdleTimeoutMode to 1.0");
3349 postResetPreIdleTimeoutFactor();
3350 }
3351
3352 private void postUpdatePreIdleFactor() {
3353 mHandler.sendEmptyMessage(MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR);
3354 }
3355
3356 private void postResetPreIdleTimeoutFactor() {
3357 mHandler.sendEmptyMessage(MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR);
3358 }
3359
Denny cy Lee990ca332019-10-22 16:21:20 +08003360 private void updatePreIdleFactor() {
Denny cy Leec5a7c292019-01-01 17:37:55 +08003361 synchronized (this) {
3362 if (!shouldUseIdleTimeoutFactorLocked()) {
3363 return;
3364 }
3365 if (mState == STATE_INACTIVE || mState == STATE_IDLE_PENDING) {
3366 if (mNextAlarmTime == 0) {
3367 return;
3368 }
3369 long delay = mNextAlarmTime - SystemClock.elapsedRealtime();
3370 if (delay < MIN_STATE_STEP_ALARM_CHANGE) {
3371 return;
3372 }
3373 long newDelay = (long) (delay / mLastPreIdleFactor * mPreIdleFactor);
3374 if (Math.abs(delay - newDelay) < MIN_STATE_STEP_ALARM_CHANGE) {
3375 return;
3376 }
3377 scheduleAlarmLocked(newDelay, false);
3378 }
3379 }
3380 }
3381
Denny cy Lee990ca332019-10-22 16:21:20 +08003382 private void maybeDoImmediateMaintenance() {
Denny cy Leec5a7c292019-01-01 17:37:55 +08003383 synchronized (this) {
3384 if (mState == STATE_IDLE) {
3385 long duration = SystemClock.elapsedRealtime() - mIdleStartTime;
3386 /* Let's trgger a immediate maintenance,
3387 * if it has been idle for a long time */
3388 if (duration > mConstants.IDLE_TIMEOUT) {
3389 scheduleAlarmLocked(0, false);
3390 }
3391 }
3392 }
3393 }
3394
3395 private boolean shouldUseIdleTimeoutFactorLocked() {
3396 // exclude ACTIVE_REASON_MOTION, for exclude device in pocket case
3397 if (mActiveReason == ACTIVE_REASON_MOTION) {
3398 return false;
3399 }
3400 return true;
3401 }
3402
3403 /** Must only be used in tests. */
3404 @VisibleForTesting
3405 void setIdleStartTimeForTest(long idleStartTime) {
3406 synchronized (this) {
3407 mIdleStartTime = idleStartTime;
Denny cy Lee990ca332019-10-22 16:21:20 +08003408 maybeDoImmediateMaintenance();
Denny cy Leec5a7c292019-01-01 17:37:55 +08003409 }
3410 }
3411
Denny cy Leec5a7c292019-01-01 17:37:55 +08003412 @VisibleForTesting
3413 long getNextAlarmTime() {
3414 return mNextAlarmTime;
3415 }
3416
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003417 boolean isOpsInactiveLocked() {
Dianne Hackborn7ab40252016-06-15 17:30:24 -07003418 return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003419 }
3420
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003421 void exitMaintenanceEarlyIfNeededLocked() {
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003422 if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE
3423 || mLightState == LIGHT_STATE_PRE_IDLE) {
3424 if (isOpsInactiveLocked()) {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003425 final long now = SystemClock.elapsedRealtime();
3426 if (DEBUG) {
3427 StringBuilder sb = new StringBuilder();
3428 sb.append("Exit: start=");
3429 TimeUtils.formatDuration(mMaintenanceStartTime, sb);
3430 sb.append(" now=");
3431 TimeUtils.formatDuration(now, sb);
3432 Slog.d(TAG, sb.toString());
3433 }
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003434 if (mState == STATE_IDLE_MAINTENANCE) {
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003435 stepIdleStateLocked("s:early");
3436 } else if (mLightState == LIGHT_STATE_PRE_IDLE) {
3437 stepLightIdleStateLocked("s:predone");
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003438 } else {
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003439 stepLightIdleStateLocked("s:early");
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003440 }
3441 }
3442 }
3443 }
3444
Nick Vaccaro20feaea2015-09-17 17:22:44 -07003445 void motionLocked() {
3446 if (DEBUG) Slog.d(TAG, "motionLocked()");
Kweku Adams810c77d2019-08-28 07:45:00 -07003447 mLastMotionEventElapsed = mInjector.getElapsedRealtime();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003448 handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
3449 }
3450
3451 void handleMotionDetectedLocked(long timeout, String type) {
Kweku Adams810c77d2019-08-28 07:45:00 -07003452 if (mStationaryListeners.size() > 0) {
3453 postStationaryStatusUpdated();
3454 scheduleMotionTimeoutAlarmLocked();
Kweku Adamsa890d282019-12-19 16:08:43 -08003455 // We need to re-register the motion listener, but we don't want the sensors to be
3456 // constantly active or to churn the CPU by registering too early, register after some
3457 // delay.
3458 scheduleMotionRegistrationAlarmLocked();
Kweku Adams810c77d2019-08-28 07:45:00 -07003459 }
3460 if (mQuickDozeActivated && !mQuickDozeActivatedWhileIdling) {
3461 // Don't exit idle due to motion if quick doze is enabled.
3462 // However, if the device started idling due to the normal progression (going through
3463 // all the states) and then had quick doze activated, come out briefly on motion so the
3464 // user can get slightly fresher content.
3465 return;
3466 }
3467 maybeStopMonitoringMotionLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003468 // The device is not yet active, so we want to go back to the pending idle
Nick Vaccaro20feaea2015-09-17 17:22:44 -07003469 // state to wait again for no motion. Note that we only monitor for motion
3470 // after moving out of the inactive state, so no need to worry about that.
Kweku Adamsb7ce1902019-01-30 10:55:34 -08003471 final boolean becomeInactive = mState != STATE_ACTIVE
3472 || mLightState == LIGHT_STATE_OVERRIDE;
3473 // We only want to change the IDLE state if it's OVERRIDE.
3474 becomeActiveLocked(type, Process.myUid(), timeout, mLightState == LIGHT_STATE_OVERRIDE);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003475 if (becomeInactive) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003476 becomeInactiveIfAppropriateLocked();
3477 }
3478 }
3479
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003480 void receivedGenericLocationLocked(Location location) {
3481 if (mState != STATE_LOCATING) {
3482 cancelLocatingLocked();
3483 return;
3484 }
3485 if (DEBUG) Slog.d(TAG, "Generic location: " + location);
3486 mLastGenericLocation = new Location(location);
Joe LaPenna23d681b2015-08-27 15:12:11 -07003487 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003488 return;
3489 }
3490 mLocated = true;
3491 if (mNotMoving) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003492 stepIdleStateLocked("s:location");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003493 }
3494 }
3495
3496 void receivedGpsLocationLocked(Location location) {
3497 if (mState != STATE_LOCATING) {
3498 cancelLocatingLocked();
3499 return;
3500 }
3501 if (DEBUG) Slog.d(TAG, "GPS location: " + location);
3502 mLastGpsLocation = new Location(location);
3503 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
3504 return;
3505 }
3506 mLocated = true;
3507 if (mNotMoving) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003508 stepIdleStateLocked("s:gps");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003509 }
3510 }
3511
Nick Vaccaro20feaea2015-09-17 17:22:44 -07003512 void startMonitoringMotionLocked() {
3513 if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()");
3514 if (mMotionSensor != null && !mMotionListener.active) {
3515 mMotionListener.registerLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003516 }
3517 }
3518
Kweku Adams810c77d2019-08-28 07:45:00 -07003519 /**
3520 * Stops motion monitoring. Will not stop monitoring if there are registered stationary
3521 * listeners.
3522 */
3523 private void maybeStopMonitoringMotionLocked() {
3524 if (DEBUG) Slog.d(TAG, "maybeStopMonitoringMotionLocked()");
Kweku Adamsa890d282019-12-19 16:08:43 -08003525 if (mMotionSensor != null && mStationaryListeners.size() == 0) {
3526 if (mMotionListener.active) {
3527 mMotionListener.unregisterLocked();
3528 cancelMotionTimeoutAlarmLocked();
3529 }
3530 cancelMotionRegistrationAlarmLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003531 }
3532 }
3533
3534 void cancelAlarmLocked() {
3535 if (mNextAlarmTime != 0) {
3536 mNextAlarmTime = 0;
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003537 mAlarmManager.cancel(mDeepAlarmListener);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003538 }
3539 }
3540
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003541 void cancelLightAlarmLocked() {
3542 if (mNextLightAlarmTime != 0) {
3543 mNextLightAlarmTime = 0;
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003544 mAlarmManager.cancel(mLightAlarmListener);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003545 }
3546 }
3547
3548 void cancelLocatingLocked() {
3549 if (mLocating) {
Kweku Adams799858b2018-10-08 17:19:08 -07003550 LocationManager locationManager = mInjector.getLocationManager();
3551 locationManager.removeUpdates(mGenericLocationListener);
3552 locationManager.removeUpdates(mGpsLocationListener);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003553 mLocating = false;
3554 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003555 }
3556
Kweku Adams810c77d2019-08-28 07:45:00 -07003557 private void cancelMotionTimeoutAlarmLocked() {
3558 mAlarmManager.cancel(mMotionTimeoutAlarmListener);
3559 }
3560
Kweku Adamsa890d282019-12-19 16:08:43 -08003561 private void cancelMotionRegistrationAlarmLocked() {
3562 mAlarmManager.cancel(mMotionRegistrationAlarmListener);
3563 }
3564
Kevin Gabayan92f15e62016-04-04 17:52:22 -07003565 void cancelSensingTimeoutAlarmLocked() {
3566 if (mNextSensingTimeoutAlarmTime != 0) {
3567 mNextSensingTimeoutAlarmTime = 0;
3568 mAlarmManager.cancel(mSensingTimeoutAlarmListener);
3569 }
3570 }
3571
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003572 void scheduleAlarmLocked(long delay, boolean idleUntil) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003573 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
Robin Leec4d424c2018-12-07 15:09:13 +01003574
3575 if (mUseMotionSensor && mMotionSensor == null
3576 && mState != STATE_QUICK_DOZE_DELAY
3577 && mState != STATE_IDLE
3578 && mState != STATE_IDLE_MAINTENANCE) {
3579 // If there is no motion sensor on this device, but we need one, then we won't schedule
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003580 // alarms, because we can't determine if the device is not moving. This effectively
Joe LaPenna23d681b2015-08-27 15:12:11 -07003581 // turns off normal execution of device idling, although it is still possible to
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003582 // manually poke it by pretending like the alarm is going off.
Kweku Adamsb396ccf2018-09-17 16:37:15 -07003583 // STATE_QUICK_DOZE_DELAY skips the motion sensing so if the state is past the motion
3584 // sensing stage (ie, is QUICK_DOZE_DELAY, IDLE, or IDLE_MAINTENANCE), then idling
3585 // can continue until the user interacts with the device.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003586 return;
3587 }
3588 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
3589 if (idleUntil) {
3590 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003591 mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003592 } else {
3593 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003594 mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003595 }
3596 }
3597
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003598 void scheduleLightAlarmLocked(long delay) {
3599 if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003600 mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003601 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003602 mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003603 }
3604
Kweku Adamsa890d282019-12-19 16:08:43 -08003605 private void scheduleMotionRegistrationAlarmLocked() {
3606 if (DEBUG) Slog.d(TAG, "scheduleMotionRegistrationAlarmLocked");
3607 long nextMotionRegistrationAlarmTime =
3608 mInjector.getElapsedRealtime() + mConstants.MOTION_INACTIVE_TIMEOUT / 2;
3609 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionRegistrationAlarmTime,
3610 "DeviceIdleController.motion_registration", mMotionRegistrationAlarmListener,
3611 mHandler);
3612 }
3613
Kweku Adams810c77d2019-08-28 07:45:00 -07003614 private void scheduleMotionTimeoutAlarmLocked() {
3615 if (DEBUG) Slog.d(TAG, "scheduleMotionAlarmLocked");
3616 long nextMotionTimeoutAlarmTime =
3617 mInjector.getElapsedRealtime() + mConstants.MOTION_INACTIVE_TIMEOUT;
3618 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionTimeoutAlarmTime,
3619 "DeviceIdleController.motion", mMotionTimeoutAlarmListener, mHandler);
3620 }
3621
Kevin Gabayan92f15e62016-04-04 17:52:22 -07003622 void scheduleSensingTimeoutAlarmLocked(long delay) {
3623 if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
3624 mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
3625 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
3626 "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
3627 }
3628
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003629 private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
3630 ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
3631 outAppIds.clear();
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08003632 if (systemApps != null) {
3633 for (int i = 0; i < systemApps.size(); i++) {
3634 outAppIds.put(systemApps.valueAt(i), true);
3635 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003636 }
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08003637 if (userApps != null) {
3638 for (int i = 0; i < userApps.size(); i++) {
3639 outAppIds.put(userApps.valueAt(i), true);
3640 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003641 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003642 int size = outAppIds.size();
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003643 int[] appids = new int[size];
3644 for (int i = 0; i < size; i++) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003645 appids[i] = outAppIds.keyAt(i);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003646 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003647 return appids;
3648 }
3649
3650 private void updateWhitelistAppIdsLocked() {
3651 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
3652 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
3653 mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
3654 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08003655 mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
3656 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
Dianne Hackborn85e35642017-01-12 15:10:57 -08003657 if (mLocalActivityManager != null) {
Makoto Onukiaf8ff4f2018-06-04 14:44:19 -07003658 mLocalActivityManager.setDeviceIdleWhitelist(
3659 mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
Dianne Hackborn85e35642017-01-12 15:10:57 -08003660 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003661 if (mLocalPowerManager != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003662 if (DEBUG) {
3663 Slog.d(TAG, "Setting wakelock whitelist to "
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07003664 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003665 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07003666 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003667 }
Suprabh Shukla5bf49812018-05-24 18:38:50 -07003668 passWhiteListsToForceAppStandbyTrackerLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003669 }
3670
Dianne Hackborn85e35642017-01-12 15:10:57 -08003671 private void updateTempWhitelistAppIdsLocked(int appId, boolean adding) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003672 final int size = mTempWhitelistAppIdEndTimes.size();
3673 if (mTempWhitelistAppIdArray.length != size) {
3674 mTempWhitelistAppIdArray = new int[size];
3675 }
3676 for (int i = 0; i < size; i++) {
3677 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
3678 }
Dianne Hackborn85e35642017-01-12 15:10:57 -08003679 if (mLocalActivityManager != null) {
3680 if (DEBUG) {
3681 Slog.d(TAG, "Setting activity manager temp whitelist to "
3682 + Arrays.toString(mTempWhitelistAppIdArray));
3683 }
3684 mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, appId,
3685 adding);
3686 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003687 if (mLocalPowerManager != null) {
3688 if (DEBUG) {
3689 Slog.d(TAG, "Setting wakelock temp whitelist to "
3690 + Arrays.toString(mTempWhitelistAppIdArray));
3691 }
3692 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
3693 }
Suprabh Shukla5bf49812018-05-24 18:38:50 -07003694 passWhiteListsToForceAppStandbyTrackerLocked();
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003695 }
3696
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003697 private void reportPowerSaveWhitelistChangedLocked() {
3698 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
3699 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003700 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003701 }
3702
3703 private void reportTempWhitelistChangedLocked() {
3704 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
3705 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003706 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003707 }
3708
Suprabh Shukla5bf49812018-05-24 18:38:50 -07003709 private void passWhiteListsToForceAppStandbyTrackerLocked() {
Makoto Onukie4918212018-02-06 11:30:15 -08003710 mAppStateTracker.setPowerSaveWhitelistAppIds(
Makoto Onuki71755c92018-01-16 14:15:44 -08003711 mPowerSaveWhitelistExceptIdleAppIdArray,
Suprabh Shukla5bf49812018-05-24 18:38:50 -07003712 mPowerSaveWhitelistUserAppIdArray,
Makoto Onuki2206af32017-11-21 16:25:35 -08003713 mTempWhitelistAppIdArray);
3714 }
3715
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003716 void readConfigFileLocked() {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07003717 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003718 mPowerSaveWhitelistUserApps.clear();
3719 FileInputStream stream;
3720 try {
3721 stream = mConfigFile.openRead();
3722 } catch (FileNotFoundException e) {
3723 return;
3724 }
3725 try {
3726 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01003727 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003728 readConfigFileLocked(parser);
3729 } catch (XmlPullParserException e) {
3730 } finally {
3731 try {
3732 stream.close();
3733 } catch (IOException e) {
3734 }
3735 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003736 }
3737
3738 private void readConfigFileLocked(XmlPullParser parser) {
3739 final PackageManager pm = getContext().getPackageManager();
3740
3741 try {
3742 int type;
3743 while ((type = parser.next()) != XmlPullParser.START_TAG
3744 && type != XmlPullParser.END_DOCUMENT) {
3745 ;
3746 }
3747
3748 if (type != XmlPullParser.START_TAG) {
3749 throw new IllegalStateException("no start tag found");
3750 }
3751
3752 int outerDepth = parser.getDepth();
3753 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3754 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3755 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3756 continue;
3757 }
3758
3759 String tagName = parser.getName();
Suprabh Shukla08105642017-09-26 14:45:30 -07003760 switch (tagName) {
3761 case "wl":
3762 String name = parser.getAttributeValue(null, "n");
3763 if (name != null) {
3764 try {
3765 ApplicationInfo ai = pm.getApplicationInfo(name,
3766 PackageManager.MATCH_ANY_USER);
3767 mPowerSaveWhitelistUserApps.put(ai.packageName,
3768 UserHandle.getAppId(ai.uid));
3769 } catch (PackageManager.NameNotFoundException e) {
3770 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003771 }
Suprabh Shukla08105642017-09-26 14:45:30 -07003772 break;
3773 case "un-wl":
3774 final String packageName = parser.getAttributeValue(null, "n");
3775 if (mPowerSaveWhitelistApps.containsKey(packageName)) {
3776 mRemovedFromSystemWhitelistApps.put(packageName,
3777 mPowerSaveWhitelistApps.remove(packageName));
3778 }
3779 break;
3780 default:
3781 Slog.w(TAG, "Unknown element under <config>: "
3782 + parser.getName());
3783 XmlUtils.skipCurrentTag(parser);
3784 break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003785 }
3786 }
3787
3788 } catch (IllegalStateException e) {
3789 Slog.w(TAG, "Failed parsing config " + e);
3790 } catch (NullPointerException e) {
3791 Slog.w(TAG, "Failed parsing config " + e);
3792 } catch (NumberFormatException e) {
3793 Slog.w(TAG, "Failed parsing config " + e);
3794 } catch (XmlPullParserException e) {
3795 Slog.w(TAG, "Failed parsing config " + e);
3796 } catch (IOException e) {
3797 Slog.w(TAG, "Failed parsing config " + e);
3798 } catch (IndexOutOfBoundsException e) {
3799 Slog.w(TAG, "Failed parsing config " + e);
3800 }
3801 }
3802
3803 void writeConfigFileLocked() {
3804 mHandler.removeMessages(MSG_WRITE_CONFIG);
3805 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
3806 }
3807
3808 void handleWriteConfigFile() {
3809 final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
3810
3811 try {
3812 synchronized (this) {
3813 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01003814 out.setOutput(memStream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003815 writeConfigFileLocked(out);
3816 }
3817 } catch (IOException e) {
3818 }
3819
3820 synchronized (mConfigFile) {
3821 FileOutputStream stream = null;
3822 try {
3823 stream = mConfigFile.startWrite();
3824 memStream.writeTo(stream);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003825 mConfigFile.finishWrite(stream);
3826 } catch (IOException e) {
3827 Slog.w(TAG, "Error writing config file", e);
3828 mConfigFile.failWrite(stream);
3829 }
3830 }
3831 }
3832
3833 void writeConfigFileLocked(XmlSerializer out) throws IOException {
3834 out.startDocument(null, true);
3835 out.startTag(null, "config");
3836 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
3837 String name = mPowerSaveWhitelistUserApps.keyAt(i);
3838 out.startTag(null, "wl");
3839 out.attribute(null, "n", name);
3840 out.endTag(null, "wl");
3841 }
Suprabh Shukla08105642017-09-26 14:45:30 -07003842 for (int i = 0; i < mRemovedFromSystemWhitelistApps.size(); i++) {
3843 out.startTag(null, "un-wl");
3844 out.attribute(null, "n", mRemovedFromSystemWhitelistApps.keyAt(i));
3845 out.endTag(null, "un-wl");
3846 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003847 out.endTag(null, "config");
3848 out.endDocument();
3849 }
3850
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003851 static void dumpHelp(PrintWriter pw) {
3852 pw.println("Device idle controller (deviceidle) commands:");
3853 pw.println(" help");
3854 pw.println(" Print this help text.");
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003855 pw.println(" step [light|deep]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003856 pw.println(" Immediately step to next state, without waiting for alarm.");
Dianne Hackborn88c41352016-04-07 15:18:58 -07003857 pw.println(" force-idle [light|deep]");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003858 pw.println(" Force directly into idle mode, regardless of other device state.");
Dianne Hackborn88c41352016-04-07 15:18:58 -07003859 pw.println(" force-inactive");
3860 pw.println(" Force to be inactive, ready to freely step idle states.");
3861 pw.println(" unforce");
3862 pw.println(" Resume normal functioning after force-idle or force-inactive.");
3863 pw.println(" get [light|deep|force|screen|charging|network]");
3864 pw.println(" Retrieve the current given state.");
Dianne Hackbornb6843652016-02-22 12:20:13 -08003865 pw.println(" disable [light|deep|all]");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003866 pw.println(" Completely disable device idle mode.");
Dianne Hackbornb6843652016-02-22 12:20:13 -08003867 pw.println(" enable [light|deep|all]");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003868 pw.println(" Re-enable device idle mode after it had previously been disabled.");
Dianne Hackbornb6843652016-02-22 12:20:13 -08003869 pw.println(" enabled [light|deep|all]");
Dianne Hackborn92617032015-06-19 15:32:19 -07003870 pw.println(" Print 1 if device idle mode is currently enabled, else 0.");
Dianne Hackborn1b139682015-07-06 15:13:37 -07003871 pw.println(" whitelist");
3872 pw.println(" Print currently whitelisted apps.");
Dianne Hackborn92617032015-06-19 15:32:19 -07003873 pw.println(" whitelist [package ...]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003874 pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
Suprabh Shukla08105642017-09-26 14:45:30 -07003875 pw.println(" sys-whitelist [package ...|reset]");
3876 pw.println(" Prefix the package with '-' to remove it from the system whitelist or '+'"
3877 + " to put it back in the system whitelist.");
3878 pw.println(" Note that only packages that were"
3879 + " earlier removed from the system whitelist can be added back.");
3880 pw.println(" reset will reset the whitelist to the original state");
3881 pw.println(" Prints the system whitelist if no arguments are specified");
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07003882 pw.println(" except-idle-whitelist [package ...|reset]");
3883 pw.println(" Prefix the package with '+' to add it to whitelist or "
3884 + "'=' to check if it is already whitelisted");
3885 pw.println(" [reset] will reset the whitelist to it's original state");
3886 pw.println(" Note that unlike <whitelist> cmd, "
3887 + "changes made using this won't be persisted across boots");
Felipe Lemea1b79bf2016-05-24 13:06:54 -07003888 pw.println(" tempwhitelist");
3889 pw.println(" Print packages that are temporarily whitelisted.");
Sudheer Shanka326b3112017-11-27 14:40:57 -08003890 pw.println(" tempwhitelist [-u USER] [-d DURATION] [-r] [package]");
3891 pw.println(" Temporarily place package in whitelist for DURATION milliseconds.");
Dianne Hackborn85e35642017-01-12 15:10:57 -08003892 pw.println(" If no DURATION is specified, 10 seconds is used");
Sudheer Shanka326b3112017-11-27 14:40:57 -08003893 pw.println(" If [-r] option is used, then the package is removed from temp whitelist "
3894 + "and any [-d] is ignored");
Amith Yamasani4cb42572018-04-27 10:02:57 -07003895 pw.println(" motion");
3896 pw.println(" Simulate a motion event to bring the device out of deep doze");
Denny cy Leec5a7c292019-01-01 17:37:55 +08003897 pw.println(" pre-idle-factor [0|1|2]");
3898 pw.println(" Set a new factor to idle time before step to idle"
3899 + "(inactive_to and idle_after_inactive_to)");
3900 pw.println(" reset-pre-idle-factor");
3901 pw.println(" Reset factor to idle time to default");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003902 }
3903
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003904 class Shell extends ShellCommand {
3905 int userId = UserHandle.USER_SYSTEM;
3906
3907 @Override
3908 public int onCommand(String cmd) {
3909 return onShellCommand(this, cmd);
3910 }
3911
3912 @Override
3913 public void onHelp() {
3914 PrintWriter pw = getOutPrintWriter();
3915 dumpHelp(pw);
3916 }
3917 }
3918
3919 int onShellCommand(Shell shell, String cmd) {
3920 PrintWriter pw = shell.getOutPrintWriter();
3921 if ("step".equals(cmd)) {
3922 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3923 null);
3924 synchronized (this) {
3925 long token = Binder.clearCallingIdentity();
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003926 String arg = shell.getNextArg();
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003927 try {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003928 if (arg == null || "deep".equals(arg)) {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003929 stepIdleStateLocked("s:shell");
3930 pw.print("Stepped to deep: ");
3931 pw.println(stateToString(mState));
3932 } else if ("light".equals(arg)) {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003933 stepLightIdleStateLocked("s:shell");
3934 pw.print("Stepped to light: "); pw.println(lightStateToString(mLightState));
3935 } else {
3936 pw.println("Unknown idle mode: " + arg);
3937 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003938 } finally {
3939 Binder.restoreCallingIdentity(token);
3940 }
3941 }
3942 } else if ("force-idle".equals(cmd)) {
3943 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3944 null);
3945 synchronized (this) {
3946 long token = Binder.clearCallingIdentity();
Dianne Hackborn88c41352016-04-07 15:18:58 -07003947 String arg = shell.getNextArg();
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003948 try {
Dianne Hackborn88c41352016-04-07 15:18:58 -07003949 if (arg == null || "deep".equals(arg)) {
3950 if (!mDeepEnabled) {
3951 pw.println("Unable to go deep idle; not enabled");
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003952 return -1;
3953 }
Dianne Hackborn88c41352016-04-07 15:18:58 -07003954 mForceIdle = true;
3955 becomeInactiveIfAppropriateLocked();
3956 int curState = mState;
3957 while (curState != STATE_IDLE) {
3958 stepIdleStateLocked("s:shell");
3959 if (curState == mState) {
3960 pw.print("Unable to go deep idle; stopped at ");
3961 pw.println(stateToString(mState));
3962 exitForceIdleLocked();
3963 return -1;
3964 }
3965 curState = mState;
3966 }
3967 pw.println("Now forced in to deep idle mode");
3968 } else if ("light".equals(arg)) {
3969 mForceIdle = true;
3970 becomeInactiveIfAppropriateLocked();
3971 int curLightState = mLightState;
3972 while (curLightState != LIGHT_STATE_IDLE) {
Tej Singh93cf3e32017-12-07 13:05:38 -08003973 stepLightIdleStateLocked("s:shell");
Dianne Hackborn88c41352016-04-07 15:18:58 -07003974 if (curLightState == mLightState) {
3975 pw.print("Unable to go light idle; stopped at ");
3976 pw.println(lightStateToString(mLightState));
3977 exitForceIdleLocked();
3978 return -1;
3979 }
3980 curLightState = mLightState;
3981 }
3982 pw.println("Now forced in to light idle mode");
3983 } else {
3984 pw.println("Unknown idle mode: " + arg);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003985 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003986 } finally {
3987 Binder.restoreCallingIdentity(token);
3988 }
3989 }
Dianne Hackborn88c41352016-04-07 15:18:58 -07003990 } else if ("force-inactive".equals(cmd)) {
3991 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3992 null);
3993 synchronized (this) {
3994 long token = Binder.clearCallingIdentity();
3995 try {
3996 mForceIdle = true;
3997 becomeInactiveIfAppropriateLocked();
3998 pw.print("Light state: ");
3999 pw.print(lightStateToString(mLightState));
4000 pw.print(", deep state: ");
4001 pw.println(stateToString(mState));
4002 } finally {
4003 Binder.restoreCallingIdentity(token);
4004 }
4005 }
4006 } else if ("unforce".equals(cmd)) {
4007 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4008 null);
4009 synchronized (this) {
4010 long token = Binder.clearCallingIdentity();
4011 try {
4012 exitForceIdleLocked();
4013 pw.print("Light state: ");
4014 pw.print(lightStateToString(mLightState));
4015 pw.print(", deep state: ");
4016 pw.println(stateToString(mState));
4017 } finally {
4018 Binder.restoreCallingIdentity(token);
4019 }
4020 }
4021 } else if ("get".equals(cmd)) {
4022 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4023 null);
4024 synchronized (this) {
4025 String arg = shell.getNextArg();
4026 if (arg != null) {
4027 long token = Binder.clearCallingIdentity();
4028 try {
4029 switch (arg) {
4030 case "light": pw.println(lightStateToString(mLightState)); break;
4031 case "deep": pw.println(stateToString(mState)); break;
4032 case "force": pw.println(mForceIdle); break;
Kweku Adamsb396ccf2018-09-17 16:37:15 -07004033 case "quick": pw.println(mQuickDozeActivated); break;
Dianne Hackborn88c41352016-04-07 15:18:58 -07004034 case "screen": pw.println(mScreenOn); break;
4035 case "charging": pw.println(mCharging); break;
4036 case "network": pw.println(mNetworkConnected); break;
4037 default: pw.println("Unknown get option: " + arg); break;
4038 }
4039 } finally {
4040 Binder.restoreCallingIdentity(token);
4041 }
4042 } else {
4043 pw.println("Argument required");
4044 }
4045 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004046 } else if ("disable".equals(cmd)) {
4047 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4048 null);
4049 synchronized (this) {
4050 long token = Binder.clearCallingIdentity();
Dianne Hackbornb6843652016-02-22 12:20:13 -08004051 String arg = shell.getNextArg();
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004052 try {
Dianne Hackbornb6843652016-02-22 12:20:13 -08004053 boolean becomeActive = false;
4054 boolean valid = false;
4055 if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
4056 valid = true;
4057 if (mDeepEnabled) {
4058 mDeepEnabled = false;
4059 becomeActive = true;
4060 pw.println("Deep idle mode disabled");
4061 }
4062 }
4063 if (arg == null || "light".equals(arg) || "all".equals(arg)) {
4064 valid = true;
4065 if (mLightEnabled) {
4066 mLightEnabled = false;
4067 becomeActive = true;
4068 pw.println("Light idle mode disabled");
4069 }
4070 }
4071 if (becomeActive) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08004072 mActiveReason = ACTIVE_REASON_FORCED;
Dianne Hackbornb6843652016-02-22 12:20:13 -08004073 becomeActiveLocked((arg == null ? "all" : arg) + "-disabled",
4074 Process.myUid());
4075 }
4076 if (!valid) {
4077 pw.println("Unknown idle mode: " + arg);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004078 }
4079 } finally {
4080 Binder.restoreCallingIdentity(token);
4081 }
4082 }
4083 } else if ("enable".equals(cmd)) {
4084 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4085 null);
4086 synchronized (this) {
4087 long token = Binder.clearCallingIdentity();
Dianne Hackbornb6843652016-02-22 12:20:13 -08004088 String arg = shell.getNextArg();
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004089 try {
Dianne Hackbornb6843652016-02-22 12:20:13 -08004090 boolean becomeInactive = false;
4091 boolean valid = false;
4092 if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
4093 valid = true;
4094 if (!mDeepEnabled) {
4095 mDeepEnabled = true;
4096 becomeInactive = true;
4097 pw.println("Deep idle mode enabled");
4098 }
4099 }
4100 if (arg == null || "light".equals(arg) || "all".equals(arg)) {
4101 valid = true;
4102 if (!mLightEnabled) {
4103 mLightEnabled = true;
4104 becomeInactive = true;
4105 pw.println("Light idle mode enable");
4106 }
4107 }
4108 if (becomeInactive) {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004109 becomeInactiveIfAppropriateLocked();
Dianne Hackbornb6843652016-02-22 12:20:13 -08004110 }
4111 if (!valid) {
4112 pw.println("Unknown idle mode: " + arg);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004113 }
4114 } finally {
4115 Binder.restoreCallingIdentity(token);
4116 }
4117 }
4118 } else if ("enabled".equals(cmd)) {
4119 synchronized (this) {
Dianne Hackbornb6843652016-02-22 12:20:13 -08004120 String arg = shell.getNextArg();
4121 if (arg == null || "all".equals(arg)) {
4122 pw.println(mDeepEnabled && mLightEnabled ? "1" : 0);
4123 } else if ("deep".equals(arg)) {
4124 pw.println(mDeepEnabled ? "1" : 0);
4125 } else if ("light".equals(arg)) {
4126 pw.println(mLightEnabled ? "1" : 0);
4127 } else {
4128 pw.println("Unknown idle mode: " + arg);
4129 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004130 }
4131 } else if ("whitelist".equals(cmd)) {
Dianne Hackborneb909e32016-09-29 14:35:15 -07004132 String arg = shell.getNextArg();
4133 if (arg != null) {
4134 getContext().enforceCallingOrSelfPermission(
4135 android.Manifest.permission.DEVICE_POWER, null);
4136 long token = Binder.clearCallingIdentity();
4137 try {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004138 do {
4139 if (arg.length() < 1 || (arg.charAt(0) != '-'
Felipe Lemef8a46232016-02-10 13:51:54 -08004140 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
4141 pw.println("Package must be prefixed with +, -, or =: " + arg);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004142 return -1;
4143 }
4144 char op = arg.charAt(0);
4145 String pkg = arg.substring(1);
4146 if (op == '+') {
Kweku Adamsc2400c82019-10-09 15:56:04 -07004147 if (addPowerSaveWhitelistAppsInternal(Collections.singletonList(pkg))
4148 == 1) {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004149 pw.println("Added: " + pkg);
4150 } else {
4151 pw.println("Unknown package: " + pkg);
4152 }
Felipe Lemef8a46232016-02-10 13:51:54 -08004153 } else if (op == '-') {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004154 if (removePowerSaveWhitelistAppInternal(pkg)) {
4155 pw.println("Removed: " + pkg);
4156 }
Felipe Lemef8a46232016-02-10 13:51:54 -08004157 } else {
4158 pw.println(getPowerSaveWhitelistAppInternal(pkg));
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004159 }
4160 } while ((arg=shell.getNextArg()) != null);
Dianne Hackborneb909e32016-09-29 14:35:15 -07004161 } finally {
4162 Binder.restoreCallingIdentity(token);
4163 }
4164 } else {
4165 synchronized (this) {
4166 for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
4167 pw.print("system-excidle,");
4168 pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
4169 pw.print(",");
4170 pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
4171 }
4172 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
4173 pw.print("system,");
4174 pw.print(mPowerSaveWhitelistApps.keyAt(j));
4175 pw.print(",");
4176 pw.println(mPowerSaveWhitelistApps.valueAt(j));
4177 }
4178 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
4179 pw.print("user,");
4180 pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
4181 pw.print(",");
4182 pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004183 }
4184 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004185 }
4186 } else if ("tempwhitelist".equals(cmd)) {
Dianne Hackborn85e35642017-01-12 15:10:57 -08004187 long duration = 10000;
Sudheer Shanka326b3112017-11-27 14:40:57 -08004188 boolean removePkg = false;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004189 String opt;
4190 while ((opt=shell.getNextOption()) != null) {
4191 if ("-u".equals(opt)) {
4192 opt = shell.getNextArg();
4193 if (opt == null) {
4194 pw.println("-u requires a user number");
4195 return -1;
4196 }
4197 shell.userId = Integer.parseInt(opt);
Dianne Hackborn85e35642017-01-12 15:10:57 -08004198 } else if ("-d".equals(opt)) {
4199 opt = shell.getNextArg();
4200 if (opt == null) {
4201 pw.println("-d requires a duration");
4202 return -1;
4203 }
4204 duration = Long.parseLong(opt);
Sudheer Shanka326b3112017-11-27 14:40:57 -08004205 } else if ("-r".equals(opt)) {
4206 removePkg = true;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004207 }
4208 }
4209 String arg = shell.getNextArg();
4210 if (arg != null) {
4211 try {
Sudheer Shanka326b3112017-11-27 14:40:57 -08004212 if (removePkg) {
4213 removePowerSaveTempWhitelistAppChecked(arg, shell.userId);
4214 } else {
4215 addPowerSaveTempWhitelistAppChecked(arg, duration, shell.userId, "shell");
4216 }
Christopher Tateec3a9f32017-03-21 17:43:47 -07004217 } catch (Exception e) {
4218 pw.println("Failed: " + e);
4219 return -1;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004220 }
Sudheer Shanka326b3112017-11-27 14:40:57 -08004221 } else if (removePkg) {
4222 pw.println("[-r] requires a package name");
4223 return -1;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004224 } else {
Felipe Lemea1b79bf2016-05-24 13:06:54 -07004225 dumpTempWhitelistSchedule(pw, false);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004226 }
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07004227 } else if ("except-idle-whitelist".equals(cmd)) {
4228 getContext().enforceCallingOrSelfPermission(
4229 android.Manifest.permission.DEVICE_POWER, null);
4230 final long token = Binder.clearCallingIdentity();
4231 try {
4232 String arg = shell.getNextArg();
4233 if (arg == null) {
4234 pw.println("No arguments given");
4235 return -1;
4236 } else if ("reset".equals(arg)) {
4237 resetPowerSaveWhitelistExceptIdleInternal();
4238 } else {
4239 do {
4240 if (arg.length() < 1 || (arg.charAt(0) != '-'
4241 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
4242 pw.println("Package must be prefixed with +, -, or =: " + arg);
4243 return -1;
4244 }
4245 char op = arg.charAt(0);
4246 String pkg = arg.substring(1);
4247 if (op == '+') {
4248 if (addPowerSaveWhitelistExceptIdleInternal(pkg)) {
4249 pw.println("Added: " + pkg);
4250 } else {
4251 pw.println("Unknown package: " + pkg);
4252 }
4253 } else if (op == '=') {
4254 pw.println(getPowerSaveWhitelistExceptIdleInternal(pkg));
4255 } else {
4256 pw.println("Unknown argument: " + arg);
4257 return -1;
4258 }
4259 } while ((arg = shell.getNextArg()) != null);
4260 }
4261 } finally {
4262 Binder.restoreCallingIdentity(token);
4263 }
Suprabh Shukla08105642017-09-26 14:45:30 -07004264 } else if ("sys-whitelist".equals(cmd)) {
4265 String arg = shell.getNextArg();
4266 if (arg != null) {
4267 getContext().enforceCallingOrSelfPermission(
4268 android.Manifest.permission.DEVICE_POWER, null);
4269 final long token = Binder.clearCallingIdentity();
4270 try {
4271 if ("reset".equals(arg)) {
4272 resetSystemPowerWhitelistInternal();
4273 } else {
4274 do {
4275 if (arg.length() < 1
4276 || (arg.charAt(0) != '-' && arg.charAt(0) != '+')) {
4277 pw.println("Package must be prefixed with + or - " + arg);
4278 return -1;
4279 }
4280 final char op = arg.charAt(0);
4281 final String pkg = arg.substring(1);
4282 switch (op) {
4283 case '+':
4284 if (restoreSystemPowerWhitelistAppInternal(pkg)) {
4285 pw.println("Restored " + pkg);
4286 }
4287 break;
4288 case '-':
4289 if (removeSystemPowerWhitelistAppInternal(pkg)) {
4290 pw.println("Removed " + pkg);
4291 }
4292 break;
4293 }
4294 } while ((arg = shell.getNextArg()) != null);
4295 }
4296 } finally {
4297 Binder.restoreCallingIdentity(token);
4298 }
4299 } else {
4300 synchronized (this) {
Amith Yamasani4cb42572018-04-27 10:02:57 -07004301 for (int j = 0; j < mPowerSaveWhitelistApps.size(); j++) {
Suprabh Shukla08105642017-09-26 14:45:30 -07004302 pw.print(mPowerSaveWhitelistApps.keyAt(j));
4303 pw.print(",");
4304 pw.println(mPowerSaveWhitelistApps.valueAt(j));
4305 }
4306 }
4307 }
Amith Yamasani4cb42572018-04-27 10:02:57 -07004308 } else if ("motion".equals(cmd)) {
4309 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4310 null);
4311 synchronized (this) {
4312 long token = Binder.clearCallingIdentity();
4313 try {
4314 motionLocked();
4315 pw.print("Light state: ");
4316 pw.print(lightStateToString(mLightState));
4317 pw.print(", deep state: ");
4318 pw.println(stateToString(mState));
4319 } finally {
4320 Binder.restoreCallingIdentity(token);
4321 }
4322 }
Denny cy Leec5a7c292019-01-01 17:37:55 +08004323 } else if ("pre-idle-factor".equals(cmd)) {
4324 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4325 null);
4326 synchronized (this) {
4327 long token = Binder.clearCallingIdentity();
4328 int ret = SET_IDLE_FACTOR_RESULT_UNINIT;
4329 try {
4330 String arg = shell.getNextArg();
4331 boolean valid = false;
4332 int mode = 0;
4333 if (arg != null) {
4334 mode = Integer.parseInt(arg);
4335 ret = setPreIdleTimeoutMode(mode);
4336 if (ret == SET_IDLE_FACTOR_RESULT_OK) {
4337 pw.println("pre-idle-factor: " + mode);
4338 valid = true;
4339 } else if (ret == SET_IDLE_FACTOR_RESULT_NOT_SUPPORT) {
4340 valid = true;
4341 pw.println("Deep idle not supported");
4342 } else if (ret == SET_IDLE_FACTOR_RESULT_IGNORED) {
4343 valid = true;
4344 pw.println("Idle timeout factor not changed");
4345 }
4346 }
4347 if (!valid) {
4348 pw.println("Unknown idle timeout factor: " + arg
4349 + ",(error code: " + ret + ")");
4350 }
4351 } catch (NumberFormatException e) {
4352 pw.println("Unknown idle timeout factor"
4353 + ",(error code: " + ret + ")");
4354 } finally {
4355 Binder.restoreCallingIdentity(token);
4356 }
4357 }
4358 } else if ("reset-pre-idle-factor".equals(cmd)) {
4359 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4360 null);
4361 synchronized (this) {
4362 long token = Binder.clearCallingIdentity();
4363 try {
4364 resetPreIdleTimeoutMode();
4365 } finally {
4366 Binder.restoreCallingIdentity(token);
4367 }
4368 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004369 } else {
4370 return shell.handleDefaultCommands(cmd);
4371 }
4372 return 0;
4373 }
4374
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004375 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06004376 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004377
4378 if (args != null) {
Xiaohui Chen7c696362015-09-16 09:56:14 -07004379 int userId = UserHandle.USER_SYSTEM;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004380 for (int i=0; i<args.length; i++) {
4381 String arg = args[i];
4382 if ("-h".equals(arg)) {
4383 dumpHelp(pw);
4384 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07004385 } else if ("-u".equals(arg)) {
4386 i++;
4387 if (i < args.length) {
4388 arg = args[i];
4389 userId = Integer.parseInt(arg);
4390 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07004391 } else if ("-a".equals(arg)) {
4392 // Ignore, we always dump all.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004393 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
4394 pw.println("Unknown option: " + arg);
4395 return;
4396 } else {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004397 Shell shell = new Shell();
4398 shell.userId = userId;
4399 String[] newArgs = new String[args.length-i];
4400 System.arraycopy(args, i, newArgs, 0, args.length-i);
Dianne Hackborn354736e2016-08-22 17:00:05 -07004401 shell.exec(mBinderService, null, fd, null, newArgs, null,
4402 new ResultReceiver(null));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004403 return;
4404 }
4405 }
4406 }
4407
4408 synchronized (this) {
Dianne Hackborna750a632015-06-16 17:18:23 -07004409 mConstants.dump(pw);
4410
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004411 if (mEventCmds[0] != EVENT_NULL) {
4412 pw.println(" Idling history:");
4413 long now = SystemClock.elapsedRealtime();
4414 for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) {
4415 int cmd = mEventCmds[i];
4416 if (cmd == EVENT_NULL) {
4417 continue;
4418 }
4419 String label;
4420 switch (mEventCmds[i]) {
4421 case EVENT_NORMAL: label = " normal"; break;
4422 case EVENT_LIGHT_IDLE: label = " light-idle"; break;
4423 case EVENT_LIGHT_MAINTENANCE: label = "light-maint"; break;
Dianne Hackbornb6843652016-02-22 12:20:13 -08004424 case EVENT_DEEP_IDLE: label = " deep-idle"; break;
4425 case EVENT_DEEP_MAINTENANCE: label = " deep-maint"; break;
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004426 default: label = " ??"; break;
4427 }
4428 pw.print(" ");
4429 pw.print(label);
4430 pw.print(": ");
Amith Yamasaniac6517a2018-04-23 12:19:34 -07004431 TimeUtils.formatDuration(mEventTimes[i], now, pw);
4432 if (mEventReasons[i] != null) {
4433 pw.print(" (");
4434 pw.print(mEventReasons[i]);
4435 pw.print(")");
4436 }
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004437 pw.println();
Amith Yamasaniac6517a2018-04-23 12:19:34 -07004438
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004439 }
4440 }
4441
Dianne Hackborn4a503b12015-08-06 22:19:06 -07004442 int size = mPowerSaveWhitelistAppsExceptIdle.size();
4443 if (size > 0) {
4444 pw.println(" Whitelist (except idle) system apps:");
4445 for (int i = 0; i < size; i++) {
4446 pw.print(" ");
4447 pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
4448 }
4449 }
4450 size = mPowerSaveWhitelistApps.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004451 if (size > 0) {
4452 pw.println(" Whitelist system apps:");
4453 for (int i = 0; i < size; i++) {
4454 pw.print(" ");
4455 pw.println(mPowerSaveWhitelistApps.keyAt(i));
4456 }
4457 }
Suprabh Shukla08105642017-09-26 14:45:30 -07004458 size = mRemovedFromSystemWhitelistApps.size();
4459 if (size > 0) {
4460 pw.println(" Removed from whitelist system apps:");
4461 for (int i = 0; i < size; i++) {
4462 pw.print(" ");
4463 pw.println(mRemovedFromSystemWhitelistApps.keyAt(i));
4464 }
4465 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004466 size = mPowerSaveWhitelistUserApps.size();
4467 if (size > 0) {
4468 pw.println(" Whitelist user apps:");
4469 for (int i = 0; i < size; i++) {
4470 pw.print(" ");
4471 pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
4472 }
4473 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07004474 size = mPowerSaveWhitelistExceptIdleAppIds.size();
4475 if (size > 0) {
4476 pw.println(" Whitelist (except idle) all app ids:");
4477 for (int i = 0; i < size; i++) {
4478 pw.print(" ");
4479 pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
4480 pw.println();
4481 }
4482 }
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08004483 size = mPowerSaveWhitelistUserAppIds.size();
4484 if (size > 0) {
4485 pw.println(" Whitelist user app ids:");
4486 for (int i = 0; i < size; i++) {
4487 pw.print(" ");
4488 pw.print(mPowerSaveWhitelistUserAppIds.keyAt(i));
4489 pw.println();
4490 }
4491 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07004492 size = mPowerSaveWhitelistAllAppIds.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004493 if (size > 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07004494 pw.println(" Whitelist all app ids:");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004495 for (int i = 0; i < size; i++) {
Dianne Hackborna750a632015-06-16 17:18:23 -07004496 pw.print(" ");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07004497 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004498 pw.println();
4499 }
4500 }
Felipe Lemea1b79bf2016-05-24 13:06:54 -07004501 dumpTempWhitelistSchedule(pw, true);
4502
Dianne Hackborna750a632015-06-16 17:18:23 -07004503 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
4504 if (size > 0) {
4505 pw.println(" Temp whitelist app ids:");
4506 for (int i = 0; i < size; i++) {
4507 pw.print(" ");
4508 pw.print(mTempWhitelistAppIdArray[i]);
4509 pw.println();
4510 }
4511 }
Adam Lesinski31c05d12015-06-09 17:34:04 -07004512
Dianne Hackbornb6843652016-02-22 12:20:13 -08004513 pw.print(" mLightEnabled="); pw.print(mLightEnabled);
Felipe Lemea1b79bf2016-05-24 13:06:54 -07004514 pw.print(" mDeepEnabled="); pw.println(mDeepEnabled);
Dianne Hackborn4a503b12015-08-06 22:19:06 -07004515 pw.print(" mForceIdle="); pw.println(mForceIdle);
Robin Leec4d424c2018-12-07 15:09:13 +01004516 pw.print(" mUseMotionSensor="); pw.print(mUseMotionSensor);
4517 if (mUseMotionSensor) {
4518 pw.print(" mMotionSensor="); pw.println(mMotionSensor);
4519 } else {
4520 pw.println();
4521 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004522 pw.print(" mScreenOn="); pw.println(mScreenOn);
Amith Yamasani396a10c2018-01-19 10:58:07 -08004523 pw.print(" mScreenLocked="); pw.println(mScreenLocked);
Dianne Hackborn88c41352016-04-07 15:18:58 -07004524 pw.print(" mNetworkConnected="); pw.println(mNetworkConnected);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004525 pw.print(" mCharging="); pw.println(mCharging);
Robin Lee876b88542018-11-13 17:22:24 +01004526 if (mConstraints.size() != 0) {
4527 pw.println(" mConstraints={");
4528 for (int i = 0; i < mConstraints.size(); i++) {
4529 final DeviceIdleConstraintTracker tracker = mConstraints.valueAt(i);
4530 pw.print(" \""); pw.print(tracker.name); pw.print("\"=");
4531 if (tracker.minState == mState) {
4532 pw.println(tracker.active);
4533 } else {
4534 pw.print("ignored <mMinState="); pw.print(stateToString(tracker.minState));
4535 pw.println(">");
4536 }
4537 }
4538 pw.println(" }");
4539 }
Kweku Adams810c77d2019-08-28 07:45:00 -07004540 if (mUseMotionSensor || mStationaryListeners.size() > 0) {
Robin Lee876b88542018-11-13 17:22:24 +01004541 pw.print(" mMotionActive="); pw.println(mMotionListener.active);
Robin Leec4d424c2018-12-07 15:09:13 +01004542 pw.print(" mNotMoving="); pw.println(mNotMoving);
Kweku Adams810c77d2019-08-28 07:45:00 -07004543 pw.print(" mMotionListener.activatedTimeElapsed=");
4544 pw.println(mMotionListener.activatedTimeElapsed);
4545 pw.print(" mLastMotionEventElapsed="); pw.println(mLastMotionEventElapsed);
4546 pw.print(" "); pw.print(mStationaryListeners.size());
4547 pw.println(" stationary listeners registered");
Robin Leec4d424c2018-12-07 15:09:13 +01004548 }
Joe LaPenna23d681b2015-08-27 15:12:11 -07004549 pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
4550 pw.print(mHasGps); pw.print(" mHasNetwork=");
4551 pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07004552 if (mLastGenericLocation != null) {
4553 pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation);
4554 }
4555 if (mLastGpsLocation != null) {
4556 pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation);
4557 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07004558 pw.print(" mState="); pw.print(stateToString(mState));
4559 pw.print(" mLightState=");
4560 pw.println(lightStateToString(mLightState));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004561 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
4562 pw.println();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004563 if (mActiveIdleOpCount != 0) {
4564 pw.print(" mActiveIdleOpCount="); pw.println(mActiveIdleOpCount);
4565 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004566 if (mNextAlarmTime != 0) {
4567 pw.print(" mNextAlarmTime=");
4568 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
4569 pw.println();
4570 }
4571 if (mNextIdlePendingDelay != 0) {
4572 pw.print(" mNextIdlePendingDelay=");
4573 TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
4574 pw.println();
4575 }
4576 if (mNextIdleDelay != 0) {
4577 pw.print(" mNextIdleDelay=");
4578 TimeUtils.formatDuration(mNextIdleDelay, pw);
4579 pw.println();
4580 }
Dianne Hackborn953fc942016-03-29 15:36:24 -07004581 if (mNextLightIdleDelay != 0) {
4582 pw.print(" mNextIdleDelay=");
4583 TimeUtils.formatDuration(mNextLightIdleDelay, pw);
4584 pw.println();
4585 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07004586 if (mNextLightAlarmTime != 0) {
4587 pw.print(" mNextLightAlarmTime=");
4588 TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
4589 pw.println();
4590 }
Kweku Adams7c96f5182019-06-04 16:32:49 -07004591 if (mCurLightIdleBudget != 0) {
4592 pw.print(" mCurLightIdleBudget=");
4593 TimeUtils.formatDuration(mCurLightIdleBudget, pw);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004594 pw.println();
4595 }
4596 if (mMaintenanceStartTime != 0) {
4597 pw.print(" mMaintenanceStartTime=");
4598 TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw);
4599 pw.println();
4600 }
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004601 if (mJobsActive) {
4602 pw.print(" mJobsActive="); pw.println(mJobsActive);
4603 }
4604 if (mAlarmsActive) {
4605 pw.print(" mAlarmsActive="); pw.println(mAlarmsActive);
4606 }
Denny cy Leec5a7c292019-01-01 17:37:55 +08004607 if (Math.abs(mPreIdleFactor - 1.0f) > MIN_PRE_IDLE_FACTOR_CHANGE) {
4608 pw.print(" mPreIdleFactor="); pw.println(mPreIdleFactor);
4609 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004610 }
4611 }
Felipe Lemea1b79bf2016-05-24 13:06:54 -07004612
4613 void dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle) {
4614 final int size = mTempWhitelistAppIdEndTimes.size();
4615 if (size > 0) {
4616 String prefix = "";
4617 if (printTitle) {
4618 pw.println(" Temp whitelist schedule:");
4619 prefix = " ";
4620 }
4621 final long timeNow = SystemClock.elapsedRealtime();
4622 for (int i = 0; i < size; i++) {
4623 pw.print(prefix);
4624 pw.print("UID=");
4625 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
4626 pw.print(": ");
4627 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
4628 TimeUtils.formatDuration(entry.first.value, timeNow, pw);
4629 pw.print(" - ");
4630 pw.println(entry.second);
4631 }
4632 }
4633 }
4634 }