blob: ac58f3d6a94d342164a37f470e0b0857942d8205 [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 Adams5ad67f02020-01-09 12:23:37 -0800764 // One_shot sensors (which call onTrigger) are unregistered when onTrigger is called
Kweku Adamsa890d282019-12-19 16:08:43 -0800765 active = false;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700766 motionLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700767 }
768 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700769
770 @Override
771 public void onSensorChanged(SensorEvent event) {
772 synchronized (DeviceIdleController.this) {
Kweku Adams5ad67f02020-01-09 12:23:37 -0800773 // Since one_shot sensors are unregistered when onTrigger is called, unregister
774 // listeners here so that the MotionListener is in a consistent state when it calls
775 // out to motionLocked.
Kweku Adamsa890d282019-12-19 16:08:43 -0800776 mSensorManager.unregisterListener(this, mMotionSensor);
777 active = false;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700778 motionLocked();
779 }
780 }
781
782 @Override
783 public void onAccuracyChanged(Sensor sensor, int accuracy) {}
784
785 public boolean registerLocked() {
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700786 boolean success;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700787 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
788 success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
789 } else {
790 success = mSensorManager.registerListener(
791 mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL);
792 }
793 if (success) {
794 active = true;
Kweku Adams810c77d2019-08-28 07:45:00 -0700795 activatedTimeElapsed = mInjector.getElapsedRealtime();
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700796 } else {
797 Slog.e(TAG, "Unable to register for " + mMotionSensor);
798 }
799 return success;
800 }
801
802 public void unregisterLocked() {
803 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
804 mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor);
805 } else {
806 mSensorManager.unregisterListener(mMotionListener);
807 }
808 active = false;
809 }
810 }
Kweku Adams00e3a372018-09-28 16:57:09 -0700811 @VisibleForTesting final MotionListener mMotionListener = new MotionListener();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700812
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700813 private final LocationListener mGenericLocationListener = new LocationListener() {
814 @Override
815 public void onLocationChanged(Location location) {
816 synchronized (DeviceIdleController.this) {
817 receivedGenericLocationLocked(location);
818 }
819 }
820
821 @Override
822 public void onStatusChanged(String provider, int status, Bundle extras) {
823 }
824
825 @Override
826 public void onProviderEnabled(String provider) {
827 }
828
829 @Override
830 public void onProviderDisabled(String provider) {
831 }
832 };
833
834 private final LocationListener mGpsLocationListener = new LocationListener() {
835 @Override
836 public void onLocationChanged(Location location) {
837 synchronized (DeviceIdleController.this) {
838 receivedGpsLocationLocked(location);
839 }
840 }
841
842 @Override
843 public void onStatusChanged(String provider, int status, Bundle extras) {
844 }
845
846 @Override
847 public void onProviderEnabled(String provider) {
848 }
849
850 @Override
851 public void onProviderDisabled(String provider) {
852 }
853 };
854
Adam Lesinski31c05d12015-06-09 17:34:04 -0700855 /**
856 * All times are in milliseconds. These constants are kept synchronized with the system
857 * global Settings. Any access to this class or its fields should be done while
858 * holding the DeviceIdleController lock.
859 */
Robin Lee876b88542018-11-13 17:22:24 +0100860 public final class Constants extends ContentObserver {
Adam Lesinski31c05d12015-06-09 17:34:04 -0700861 // Key names stored in the settings value.
Dianne Hackborn953fc942016-03-29 15:36:24 -0700862 private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
863 = "light_after_inactive_to";
Dianne Hackborn945c9c92016-03-30 14:55:00 -0700864 private static final String KEY_LIGHT_PRE_IDLE_TIMEOUT = "light_pre_idle_to";
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700865 private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
Dianne Hackborn953fc942016-03-29 15:36:24 -0700866 private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
867 private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800868 private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
869 = "light_idle_maintenance_min_budget";
870 private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
871 = "light_idle_maintenance_max_budget";
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700872 private static final String KEY_MIN_LIGHT_MAINTENANCE_TIME = "min_light_maintenance_time";
873 private static final String KEY_MIN_DEEP_MAINTENANCE_TIME = "min_deep_maintenance_time";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700874 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
875 private static final String KEY_SENSING_TIMEOUT = "sensing_to";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700876 private static final String KEY_LOCATING_TIMEOUT = "locating_to";
877 private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700878 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
879 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
880 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
881 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
882 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
Kweku Adamsb396ccf2018-09-17 16:37:15 -0700883 private static final String KEY_QUICK_DOZE_DELAY_TIMEOUT = "quick_doze_delay_to";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700884 private static final String KEY_IDLE_TIMEOUT = "idle_to";
885 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
886 private static final String KEY_IDLE_FACTOR = "idle_factor";
887 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
888 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
889 "max_temp_app_whitelist_duration";
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700890 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
891 "mms_temp_app_whitelist_duration";
Dianne Hackborn451c3462015-07-21 17:39:46 -0700892 private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
893 "sms_temp_app_whitelist_duration";
Felipe Lemea1b79bf2016-05-24 13:06:54 -0700894 private static final String KEY_NOTIFICATION_WHITELIST_DURATION =
895 "notification_whitelist_duration";
Amith Yamasani396a10c2018-01-19 10:58:07 -0800896 /**
897 * Whether to wait for the user to unlock the device before causing screen-on to
898 * exit doze. Default = true
899 */
900 private static final String KEY_WAIT_FOR_UNLOCK = "wait_for_unlock";
Denny cy Leec5a7c292019-01-01 17:37:55 +0800901 private static final String KEY_PRE_IDLE_FACTOR_LONG =
902 "pre_idle_factor_long";
903 private static final String KEY_PRE_IDLE_FACTOR_SHORT =
904 "pre_idle_factor_short";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700905
906 /**
Dianne Hackborn953fc942016-03-29 15:36:24 -0700907 * This is the time, after becoming inactive, that we go in to the first
908 * light-weight idle mode.
909 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
910 * @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
911 */
912 public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
913
914 /**
Dianne Hackborn945c9c92016-03-30 14:55:00 -0700915 * This is amount of time we will wait from the point where we decide we would
916 * like to go idle until we actually do, while waiting for jobs and other current
917 * activity to finish.
918 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
919 * @see #KEY_LIGHT_PRE_IDLE_TIMEOUT
920 */
921 public long LIGHT_PRE_IDLE_TIMEOUT;
922
923 /**
Dianne Hackborn953fc942016-03-29 15:36:24 -0700924 * This is the initial time that we will run in idle maintenance mode.
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700925 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
926 * @see #KEY_LIGHT_IDLE_TIMEOUT
927 */
928 public long LIGHT_IDLE_TIMEOUT;
929
930 /**
Dianne Hackborn953fc942016-03-29 15:36:24 -0700931 * Scaling factor to apply to the light idle mode time each time we complete a cycle.
932 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
933 * @see #KEY_LIGHT_IDLE_FACTOR
934 */
935 public float LIGHT_IDLE_FACTOR;
936
937 /**
Kweku Adams00e3a372018-09-28 16:57:09 -0700938 * This is the maximum time we will run in idle maintenance mode.
Dianne Hackborn953fc942016-03-29 15:36:24 -0700939 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
940 * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
941 */
942 public long LIGHT_MAX_IDLE_TIMEOUT;
943
944 /**
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800945 * This is the minimum amount of time we want to make available for maintenance mode
946 * when lightly idling. That is, we will always have at least this amount of time
947 * available maintenance before timing out and cutting off maintenance mode.
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700948 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800949 * @see #KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700950 */
Dianne Hackborn8ed2b972015-11-18 14:52:04 -0800951 public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
952
953 /**
954 * This is the maximum amount of time we want to make available for maintenance mode
955 * when lightly idling. That is, if the system isn't using up its minimum maintenance
956 * budget and this time is being added to the budget reserve, this is the maximum
957 * reserve size we will allow to grow and thus the maximum amount of time we will
958 * allow for the maintenance window.
959 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
960 * @see #KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
961 */
962 public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700963
964 /**
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700965 * This is the minimum amount of time that we will stay in maintenance mode after
966 * a light doze. We have this minimum to allow various things to respond to switching
967 * in to maintenance mode and scheduling their work -- otherwise we may
Dianne Hackborn7ab40252016-06-15 17:30:24 -0700968 * see there is nothing to do (no jobs pending) and go out of maintenance
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700969 * mode immediately.
970 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
971 * @see #KEY_MIN_LIGHT_MAINTENANCE_TIME
972 */
973 public long MIN_LIGHT_MAINTENANCE_TIME;
974
975 /**
976 * This is the minimum amount of time that we will stay in maintenance mode after
977 * a full doze. We have this minimum to allow various things to respond to switching
978 * in to maintenance mode and scheduling their work -- otherwise we may
Dianne Hackborn7ab40252016-06-15 17:30:24 -0700979 * see there is nothing to do (no jobs pending) and go out of maintenance
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -0700980 * mode immediately.
981 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
982 * @see #KEY_MIN_DEEP_MAINTENANCE_TIME
983 */
984 public long MIN_DEEP_MAINTENANCE_TIME;
985
986 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -0700987 * This is the time, after becoming inactive, at which we start looking at the
988 * motion sensor to determine if the device is being left alone. We don't do this
989 * immediately after going inactive just because we don't want to be continually running
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700990 * the motion sensor whenever the screen is off.
Adam Lesinski31c05d12015-06-09 17:34:04 -0700991 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
992 * @see #KEY_INACTIVE_TIMEOUT
993 */
994 public long INACTIVE_TIMEOUT;
995
996 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700997 * If we don't receive a callback from AnyMotion in this amount of time +
998 * {@link #LOCATING_TIMEOUT}, we will change from
Adam Lesinski31c05d12015-06-09 17:34:04 -0700999 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
1000 * will be ignored.
1001 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1002 * @see #KEY_SENSING_TIMEOUT
1003 */
1004 public long SENSING_TIMEOUT;
1005
1006 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001007 * This is how long we will wait to try to get a good location fix before going in to
1008 * idle mode.
1009 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1010 * @see #KEY_LOCATING_TIMEOUT
1011 */
1012 public long LOCATING_TIMEOUT;
1013
1014 /**
1015 * The desired maximum accuracy (in meters) we consider the location to be good enough to go
1016 * on to idle. We will be trying to get an accuracy fix at least this good or until
1017 * {@link #LOCATING_TIMEOUT} expires.
1018 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1019 * @see #KEY_LOCATION_ACCURACY
1020 */
1021 public float LOCATION_ACCURACY;
1022
1023 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -07001024 * This is the time, after seeing motion, that we wait after becoming inactive from
1025 * that until we start looking for motion again.
1026 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1027 * @see #KEY_MOTION_INACTIVE_TIMEOUT
1028 */
1029 public long MOTION_INACTIVE_TIMEOUT;
1030
1031 /**
1032 * This is the time, after the inactive timeout elapses, that we will wait looking
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001033 * for motion until we truly consider the device to be idle.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001034 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1035 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
1036 */
1037 public long IDLE_AFTER_INACTIVE_TIMEOUT;
1038
1039 /**
1040 * This is the initial time, after being idle, that we will allow ourself to be back
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001041 * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
1042 * idle.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001043 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1044 * @see #KEY_IDLE_PENDING_TIMEOUT
1045 */
1046 public long IDLE_PENDING_TIMEOUT;
1047
1048 /**
1049 * Maximum pending idle timeout (time spent running) we will be allowed to use.
1050 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1051 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
1052 */
1053 public long MAX_IDLE_PENDING_TIMEOUT;
1054
1055 /**
1056 * Scaling factor to apply to current pending idle timeout each time we cycle through
1057 * that state.
1058 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1059 * @see #KEY_IDLE_PENDING_FACTOR
1060 */
1061 public float IDLE_PENDING_FACTOR;
1062
1063 /**
Kweku Adamsb396ccf2018-09-17 16:37:15 -07001064 * This is amount of time we will wait from the point where we go into
1065 * STATE_QUICK_DOZE_DELAY until we actually go into STATE_IDLE, while waiting for jobs
1066 * and other current activity to finish.
1067 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1068 * @see #KEY_QUICK_DOZE_DELAY_TIMEOUT
1069 */
1070 public long QUICK_DOZE_DELAY_TIMEOUT;
1071
1072 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -07001073 * This is the initial time that we want to sit in the idle state before waking up
1074 * again to return to pending idle and allowing normal work to run.
1075 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1076 * @see #KEY_IDLE_TIMEOUT
1077 */
1078 public long IDLE_TIMEOUT;
1079
1080 /**
1081 * Maximum idle duration we will be allowed to use.
1082 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1083 * @see #KEY_MAX_IDLE_TIMEOUT
1084 */
1085 public long MAX_IDLE_TIMEOUT;
1086
1087 /**
1088 * Scaling factor to apply to current idle timeout each time we cycle through that state.
1089 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1090 * @see #KEY_IDLE_FACTOR
1091 */
1092 public float IDLE_FACTOR;
1093
1094 /**
1095 * This is the minimum time we will allow until the next upcoming alarm for us to
1096 * actually go in to idle mode.
1097 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1098 * @see #KEY_MIN_TIME_TO_ALARM
1099 */
1100 public long MIN_TIME_TO_ALARM;
1101
1102 /**
1103 * Max amount of time to temporarily whitelist an app when it receives a high priority
1104 * tickle.
1105 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1106 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
1107 */
1108 public long MAX_TEMP_APP_WHITELIST_DURATION;
1109
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001110 /**
1111 * Amount of time we would like to whitelist an app that is receiving an MMS.
1112 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1113 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
1114 */
1115 public long MMS_TEMP_APP_WHITELIST_DURATION;
1116
Dianne Hackborn451c3462015-07-21 17:39:46 -07001117 /**
1118 * Amount of time we would like to whitelist an app that is receiving an SMS.
1119 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1120 * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
1121 */
1122 public long SMS_TEMP_APP_WHITELIST_DURATION;
1123
Felipe Lemea1b79bf2016-05-24 13:06:54 -07001124 /**
1125 * Amount of time we would like to whitelist an app that is handling a
1126 * {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}.
1127 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1128 * @see #KEY_NOTIFICATION_WHITELIST_DURATION
1129 */
1130 public long NOTIFICATION_WHITELIST_DURATION;
1131
Denny cy Leec5a7c292019-01-01 17:37:55 +08001132 /**
1133 * Pre idle time factor use to make idle delay longer
1134 */
1135 public float PRE_IDLE_FACTOR_LONG;
1136
1137 /**
1138 * Pre idle time factor use to make idle delay shorter
1139 */
1140 public float PRE_IDLE_FACTOR_SHORT;
1141
Amith Yamasani396a10c2018-01-19 10:58:07 -08001142 public boolean WAIT_FOR_UNLOCK;
1143
Adam Lesinski31c05d12015-06-09 17:34:04 -07001144 private final ContentResolver mResolver;
shreerag597da8a2017-07-21 14:24:14 -07001145 private final boolean mSmallBatteryDevice;
Adam Lesinski31c05d12015-06-09 17:34:04 -07001146 private final KeyValueListParser mParser = new KeyValueListParser(',');
1147
1148 public Constants(Handler handler, ContentResolver resolver) {
1149 super(handler);
1150 mResolver = resolver;
shreerag597da8a2017-07-21 14:24:14 -07001151 mSmallBatteryDevice = ActivityManager.isSmallBatteryDevice();
1152 mResolver.registerContentObserver(
1153 Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS),
Joe LaPennaf33b5bf2016-03-23 15:19:47 -07001154 false, this);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001155 updateConstants();
1156 }
1157
1158 @Override
1159 public void onChange(boolean selfChange, Uri uri) {
1160 updateConstants();
1161 }
1162
1163 private void updateConstants() {
1164 synchronized (DeviceIdleController.this) {
1165 try {
1166 mParser.setString(Settings.Global.getString(mResolver,
shreerag597da8a2017-07-21 14:24:14 -07001167 Settings.Global.DEVICE_IDLE_CONSTANTS));
Adam Lesinski31c05d12015-06-09 17:34:04 -07001168 } catch (IllegalArgumentException e) {
1169 // Failed to parse the settings string, log this and move on
1170 // with defaults.
1171 Slog.e(TAG, "Bad device idle settings", e);
1172 }
1173
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001174 LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
Dianne Hackborn953fc942016-03-29 15:36:24 -07001175 KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
Suprabh Shukla85fff7d2018-05-08 17:39:24 -07001176 !COMPRESS_TIME ? 3 * 60 * 1000L : 15 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001177 LIGHT_PRE_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_PRE_IDLE_TIMEOUT,
Suprabh Shukla85fff7d2018-05-08 17:39:24 -07001178 !COMPRESS_TIME ? 3 * 60 * 1000L : 30 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001179 LIGHT_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_IDLE_TIMEOUT,
Dianne Hackborn953fc942016-03-29 15:36:24 -07001180 !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
1181 LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR,
1182 2f);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001183 LIGHT_MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_MAX_IDLE_TIMEOUT,
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001184 !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001185 LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getDurationMillis(
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08001186 KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001187 !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001188 LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getDurationMillis(
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08001189 KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET,
1190 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001191 MIN_LIGHT_MAINTENANCE_TIME = mParser.getDurationMillis(
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07001192 KEY_MIN_LIGHT_MAINTENANCE_TIME,
1193 !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001194 MIN_DEEP_MAINTENANCE_TIME = mParser.getDurationMillis(
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07001195 KEY_MIN_DEEP_MAINTENANCE_TIME,
1196 !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L);
Michael Kwan88871462017-08-21 13:13:37 -07001197 long inactiveTimeoutDefault = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001198 INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_INACTIVE_TIMEOUT,
Joe LaPenna0c5d3e92016-03-24 13:29:56 -07001199 !COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10));
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001200 SENSING_TIMEOUT = mParser.getDurationMillis(KEY_SENSING_TIMEOUT,
Kweku Adams9da2bb92018-12-20 06:34:39 -08001201 !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001202 LOCATING_TIMEOUT = mParser.getDurationMillis(KEY_LOCATING_TIMEOUT,
Kweku Adams9da2bb92018-12-20 06:34:39 -08001203 !COMPRESS_TIME ? 30 * 1000L : 15 * 1000L);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001204 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001205 MOTION_INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_MOTION_INACTIVE_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001206 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
Michael Kwan88871462017-08-21 13:13:37 -07001207 long idleAfterInactiveTimeout = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001208 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
1209 KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
Joe LaPenna0c5d3e92016-03-24 13:29:56 -07001210 !COMPRESS_TIME ? idleAfterInactiveTimeout
1211 : (idleAfterInactiveTimeout / 10));
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001212 IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_PENDING_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001213 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001214 MAX_IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_PENDING_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001215 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
1216 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
1217 2f);
Kweku Adamsb396ccf2018-09-17 16:37:15 -07001218 QUICK_DOZE_DELAY_TIMEOUT = mParser.getDurationMillis(
1219 KEY_QUICK_DOZE_DELAY_TIMEOUT, !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001220 IDLE_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001221 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001222 MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_TIMEOUT,
Adam Lesinski31c05d12015-06-09 17:34:04 -07001223 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
1224 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
1225 2f);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001226 MIN_TIME_TO_ALARM = mParser.getDurationMillis(KEY_MIN_TIME_TO_ALARM,
Kweku Adams9a3c5002020-04-14 12:06:35 -04001227 !COMPRESS_TIME ? 30 * 60 * 1000L : 6 * 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001228 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001229 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001230 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
Dianne Hackborn0b6134b2015-07-14 18:48:07 -07001231 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001232 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
Dianne Hackborn451c3462015-07-21 17:39:46 -07001233 KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
Amith Yamasani761d3ff2017-12-14 17:50:03 -08001234 NOTIFICATION_WHITELIST_DURATION = mParser.getDurationMillis(
Felipe Lemea1b79bf2016-05-24 13:06:54 -07001235 KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L);
Kweku Adams43fabba2019-03-07 15:47:37 -08001236 WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, true);
Denny cy Leec5a7c292019-01-01 17:37:55 +08001237 PRE_IDLE_FACTOR_LONG = mParser.getFloat(KEY_PRE_IDLE_FACTOR_LONG, 1.67f);
1238 PRE_IDLE_FACTOR_SHORT = mParser.getFloat(KEY_PRE_IDLE_FACTOR_SHORT, 0.33f);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001239 }
1240 }
1241
1242 void dump(PrintWriter pw) {
1243 pw.println(" Settings:");
1244
Dianne Hackborn953fc942016-03-29 15:36:24 -07001245 pw.print(" "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
1246 TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw);
1247 pw.println();
1248
Dianne Hackborn945c9c92016-03-30 14:55:00 -07001249 pw.print(" "); pw.print(KEY_LIGHT_PRE_IDLE_TIMEOUT); pw.print("=");
1250 TimeUtils.formatDuration(LIGHT_PRE_IDLE_TIMEOUT, pw);
1251 pw.println();
1252
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001253 pw.print(" "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
1254 TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
1255 pw.println();
1256
Dianne Hackborn953fc942016-03-29 15:36:24 -07001257 pw.print(" "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("=");
1258 pw.print(LIGHT_IDLE_FACTOR);
1259 pw.println();
1260
1261 pw.print(" "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT); pw.print("=");
1262 TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT, pw);
1263 pw.println();
1264
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08001265 pw.print(" "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); pw.print("=");
1266 TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, pw);
1267 pw.println();
1268
1269 pw.print(" "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET); pw.print("=");
1270 TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, pw);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001271 pw.println();
1272
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07001273 pw.print(" "); pw.print(KEY_MIN_LIGHT_MAINTENANCE_TIME); pw.print("=");
1274 TimeUtils.formatDuration(MIN_LIGHT_MAINTENANCE_TIME, pw);
1275 pw.println();
1276
1277 pw.print(" "); pw.print(KEY_MIN_DEEP_MAINTENANCE_TIME); pw.print("=");
1278 TimeUtils.formatDuration(MIN_DEEP_MAINTENANCE_TIME, pw);
1279 pw.println();
1280
Dianne Hackborna750a632015-06-16 17:18:23 -07001281 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001282 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
1283 pw.println();
1284
Dianne Hackborna750a632015-06-16 17:18:23 -07001285 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001286 TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
1287 pw.println();
1288
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001289 pw.print(" "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
1290 TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
1291 pw.println();
1292
1293 pw.print(" "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
1294 pw.print(LOCATION_ACCURACY); pw.print("m");
1295 pw.println();
1296
Dianne Hackborna750a632015-06-16 17:18:23 -07001297 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001298 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
1299 pw.println();
1300
Dianne Hackborna750a632015-06-16 17:18:23 -07001301 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001302 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
1303 pw.println();
1304
Dianne Hackborna750a632015-06-16 17:18:23 -07001305 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001306 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
1307 pw.println();
1308
Dianne Hackborna750a632015-06-16 17:18:23 -07001309 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001310 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
1311 pw.println();
1312
Dianne Hackborna750a632015-06-16 17:18:23 -07001313 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001314 pw.println(IDLE_PENDING_FACTOR);
1315
Kweku Adamsb396ccf2018-09-17 16:37:15 -07001316 pw.print(" "); pw.print(KEY_QUICK_DOZE_DELAY_TIMEOUT); pw.print("=");
1317 TimeUtils.formatDuration(QUICK_DOZE_DELAY_TIMEOUT, pw);
1318 pw.println();
1319
Dianne Hackborna750a632015-06-16 17:18:23 -07001320 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001321 TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
1322 pw.println();
1323
Dianne Hackborna750a632015-06-16 17:18:23 -07001324 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001325 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
1326 pw.println();
1327
Dianne Hackborna750a632015-06-16 17:18:23 -07001328 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001329 pw.println(IDLE_FACTOR);
1330
Dianne Hackborna750a632015-06-16 17:18:23 -07001331 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001332 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
1333 pw.println();
1334
Dianne Hackborna750a632015-06-16 17:18:23 -07001335 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001336 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
1337 pw.println();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001338
1339 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
1340 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
1341 pw.println();
Dianne Hackborn451c3462015-07-21 17:39:46 -07001342
1343 pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
1344 TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
1345 pw.println();
Felipe Lemea1b79bf2016-05-24 13:06:54 -07001346
1347 pw.print(" "); pw.print(KEY_NOTIFICATION_WHITELIST_DURATION); pw.print("=");
1348 TimeUtils.formatDuration(NOTIFICATION_WHITELIST_DURATION, pw);
1349 pw.println();
Amith Yamasani396a10c2018-01-19 10:58:07 -08001350
1351 pw.print(" "); pw.print(KEY_WAIT_FOR_UNLOCK); pw.print("=");
1352 pw.println(WAIT_FOR_UNLOCK);
Denny cy Leec5a7c292019-01-01 17:37:55 +08001353
1354 pw.print(" "); pw.print(KEY_PRE_IDLE_FACTOR_LONG); pw.print("=");
1355 pw.println(PRE_IDLE_FACTOR_LONG);
1356
1357 pw.print(" "); pw.print(KEY_PRE_IDLE_FACTOR_SHORT); pw.print("=");
1358 pw.println(PRE_IDLE_FACTOR_SHORT);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001359 }
1360 }
1361
1362 private Constants mConstants;
1363
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001364 @Override
1365 public void onAnyMotionResult(int result) {
1366 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
Kevin Gabayan92f15e62016-04-04 17:52:22 -07001367 if (result != AnyMotionDetector.RESULT_UNKNOWN) {
1368 synchronized (this) {
1369 cancelSensingTimeoutAlarmLocked();
1370 }
1371 }
Kevin Gabayandcf47012016-07-08 10:41:24 -07001372 if ((result == AnyMotionDetector.RESULT_MOVED) ||
1373 (result == AnyMotionDetector.RESULT_UNKNOWN)) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001374 synchronized (this) {
Kevin Gabayandcf47012016-07-08 10:41:24 -07001375 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001376 }
1377 } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001378 if (mState == STATE_SENSING) {
1379 // If we are currently sensing, it is time to move to locating.
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001380 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001381 mNotMoving = true;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001382 stepIdleStateLocked("s:stationary");
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001383 }
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001384 } else if (mState == STATE_LOCATING) {
1385 // If we are currently locating, note that we are not moving and step
1386 // if we have located the position.
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001387 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001388 mNotMoving = true;
1389 if (mLocated) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001390 stepIdleStateLocked("s:stationary");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001391 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001392 }
1393 }
1394 }
1395 }
1396
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001397 private static final int MSG_WRITE_CONFIG = 1;
1398 private static final int MSG_REPORT_IDLE_ON = 2;
1399 private static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
1400 private static final int MSG_REPORT_IDLE_OFF = 4;
1401 private static final int MSG_REPORT_ACTIVE = 5;
1402 private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
Kweku Adams810c77d2019-08-28 07:45:00 -07001403 @VisibleForTesting
1404 static final int MSG_REPORT_STATIONARY_STATUS = 7;
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001405 private static final int MSG_FINISH_IDLE_OP = 8;
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07001406 private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 9;
Robin Lee876b88542018-11-13 17:22:24 +01001407 private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
Denny cy Lee990ca332019-10-22 16:21:20 +08001408 @VisibleForTesting
1409 static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
1410 @VisibleForTesting
1411 static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001412
1413 final class MyHandler extends Handler {
1414 MyHandler(Looper looper) {
1415 super(looper);
1416 }
1417
1418 @Override public void handleMessage(Message msg) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001419 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001420 switch (msg.what) {
1421 case MSG_WRITE_CONFIG: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001422 // Does not hold a wakelock. Just let this happen whenever.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001423 handleWriteConfigFile();
1424 } break;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001425 case MSG_REPORT_IDLE_ON:
1426 case MSG_REPORT_IDLE_ON_LIGHT: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001427 // mGoingIdleWakeLock is held at this point
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001428 EventLogTags.writeDeviceIdleOnStart();
Dianne Hackbornb6843652016-02-22 12:20:13 -08001429 final boolean deepChanged;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001430 final boolean lightChanged;
1431 if (msg.what == MSG_REPORT_IDLE_ON) {
Dianne Hackbornb6843652016-02-22 12:20:13 -08001432 deepChanged = mLocalPowerManager.setDeviceIdleMode(true);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001433 lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1434 } else {
Dianne Hackbornb6843652016-02-22 12:20:13 -08001435 deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001436 lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
1437 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001438 try {
1439 mNetworkPolicyManager.setDeviceIdleMode(true);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001440 mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07001441 ? BatteryStats.DEVICE_IDLE_MODE_DEEP
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001442 : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001443 } catch (RemoteException e) {
1444 }
Dianne Hackbornb6843652016-02-22 12:20:13 -08001445 if (deepChanged) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001446 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1447 }
1448 if (lightChanged) {
1449 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1450 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001451 EventLogTags.writeDeviceIdleOnComplete();
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001452 mGoingIdleWakeLock.release();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001453 } break;
1454 case MSG_REPORT_IDLE_OFF: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001455 // mActiveIdleWakeLock is held at this point
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001456 EventLogTags.writeDeviceIdleOffStart("unknown");
Dianne Hackbornb6843652016-02-22 12:20:13 -08001457 final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001458 final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001459 try {
1460 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001461 mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1462 null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001463 } catch (RemoteException e) {
1464 }
Dianne Hackbornb6843652016-02-22 12:20:13 -08001465 if (deepChanged) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001466 incActiveIdleOps();
1467 getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL,
1468 null, mIdleStartedDoneReceiver, null, 0, null, null);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001469 }
1470 if (lightChanged) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001471 incActiveIdleOps();
1472 getContext().sendOrderedBroadcastAsUser(mLightIdleIntent, UserHandle.ALL,
1473 null, mIdleStartedDoneReceiver, null, 0, null, null);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001474 }
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001475 // Always start with one active op for the message being sent here.
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001476 // Now we are done!
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001477 decActiveIdleOps();
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001478 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001479 } break;
1480 case MSG_REPORT_ACTIVE: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001481 // The device is awake at this point, so no wakelock necessary.
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001482 String activeReason = (String)msg.obj;
1483 int activeUid = msg.arg1;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001484 EventLogTags.writeDeviceIdleOffStart(
1485 activeReason != null ? activeReason : "unknown");
Dianne Hackbornb6843652016-02-22 12:20:13 -08001486 final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001487 final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001488 try {
1489 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001490 mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1491 activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001492 } catch (RemoteException e) {
1493 }
Dianne Hackbornb6843652016-02-22 12:20:13 -08001494 if (deepChanged) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001495 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1496 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001497 if (lightChanged) {
1498 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1499 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001500 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001501 } break;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001502 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001503 // TODO: What is keeping the device awake at this point? Does it need to be?
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07001504 int appId = msg.arg1;
1505 checkTempAppWhitelistTimeout(appId);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001506 } break;
Dianne Hackborn945c9c92016-03-30 14:55:00 -07001507 case MSG_FINISH_IDLE_OP: {
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08001508 // mActiveIdleWakeLock is held at this point
Dianne Hackborn945c9c92016-03-30 14:55:00 -07001509 decActiveIdleOps();
1510 } break;
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07001511 case MSG_REPORT_TEMP_APP_WHITELIST_CHANGED: {
1512 final int appId = msg.arg1;
1513 final boolean added = (msg.arg2 == 1);
1514 mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, added);
1515 } break;
Robin Lee876b88542018-11-13 17:22:24 +01001516 case MSG_SEND_CONSTRAINT_MONITORING: {
1517 final IDeviceIdleConstraint constraint = (IDeviceIdleConstraint) msg.obj;
1518 final boolean monitoring = (msg.arg1 == 1);
1519 if (monitoring) {
1520 constraint.startMonitoring();
1521 } else {
1522 constraint.stopMonitoring();
1523 }
1524 } break;
Denny cy Leec5a7c292019-01-01 17:37:55 +08001525 case MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR: {
1526 updatePreIdleFactor();
1527 } break;
1528 case MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR: {
1529 updatePreIdleFactor();
1530 maybeDoImmediateMaintenance();
1531 } break;
Kweku Adams810c77d2019-08-28 07:45:00 -07001532 case MSG_REPORT_STATIONARY_STATUS: {
1533 final DeviceIdleInternal.StationaryListener newListener =
1534 (DeviceIdleInternal.StationaryListener) msg.obj;
1535 final DeviceIdleInternal.StationaryListener[] listeners;
1536 final boolean isStationary;
1537 synchronized (DeviceIdleController.this) {
1538 isStationary = isStationaryLocked();
1539 if (newListener == null) {
1540 // Only notify all listeners if we aren't directing to one listener.
1541 listeners = mStationaryListeners.toArray(
1542 new DeviceIdleInternal.StationaryListener[
1543 mStationaryListeners.size()]);
1544 } else {
1545 listeners = null;
1546 }
1547 }
1548 if (listeners != null) {
1549 for (DeviceIdleInternal.StationaryListener listener : listeners) {
1550 listener.onDeviceStationaryChanged(isStationary);
1551 }
1552 }
1553 if (newListener != null) {
1554 newListener.onDeviceStationaryChanged(isStationary);
1555 }
1556 }
1557 break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001558 }
1559 }
1560 }
1561
1562 final MyHandler mHandler;
1563
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001564 BinderService mBinderService;
1565
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001566 private final class BinderService extends IDeviceIdleController.Stub {
1567 @Override public void addPowerSaveWhitelistApp(String name) {
Eugene Susla6a7006a2017-03-13 12:57:58 -07001568 if (DEBUG) {
1569 Slog.i(TAG, "addPowerSaveWhitelistApp(name = " + name + ")");
1570 }
Kweku Adamsc2400c82019-10-09 15:56:04 -07001571 addPowerSaveWhitelistApps(Collections.singletonList(name));
1572 }
1573
1574 @Override
1575 public int addPowerSaveWhitelistApps(List<String> packageNames) {
1576 if (DEBUG) {
1577 Slog.i(TAG,
1578 "addPowerSaveWhitelistApps(name = " + packageNames + ")");
1579 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001580 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1581 null);
Dianne Hackbornc9b2cd12016-01-20 10:54:29 -08001582 long ident = Binder.clearCallingIdentity();
1583 try {
Kweku Adamsc2400c82019-10-09 15:56:04 -07001584 return addPowerSaveWhitelistAppsInternal(packageNames);
Dianne Hackbornc9b2cd12016-01-20 10:54:29 -08001585 } finally {
1586 Binder.restoreCallingIdentity(ident);
1587 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001588 }
1589
1590 @Override public void removePowerSaveWhitelistApp(String name) {
Eugene Susla6a7006a2017-03-13 12:57:58 -07001591 if (DEBUG) {
1592 Slog.i(TAG, "removePowerSaveWhitelistApp(name = " + name + ")");
1593 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001594 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1595 null);
Dianne Hackbornc9b2cd12016-01-20 10:54:29 -08001596 long ident = Binder.clearCallingIdentity();
1597 try {
1598 removePowerSaveWhitelistAppInternal(name);
1599 } finally {
1600 Binder.restoreCallingIdentity(ident);
1601 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001602 }
1603
Suprabh Shukla08105642017-09-26 14:45:30 -07001604 @Override public void removeSystemPowerWhitelistApp(String name) {
1605 if (DEBUG) {
1606 Slog.d(TAG, "removeAppFromSystemWhitelist(name = " + name + ")");
1607 }
1608 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1609 null);
1610 long ident = Binder.clearCallingIdentity();
1611 try {
1612 removeSystemPowerWhitelistAppInternal(name);
1613 } finally {
1614 Binder.restoreCallingIdentity(ident);
1615 }
1616 }
1617
1618 @Override public void restoreSystemPowerWhitelistApp(String name) {
1619 if (DEBUG) {
1620 Slog.d(TAG, "restoreAppToSystemWhitelist(name = " + name + ")");
1621 }
1622 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1623 null);
1624 long ident = Binder.clearCallingIdentity();
1625 try {
1626 restoreSystemPowerWhitelistAppInternal(name);
1627 } finally {
1628 Binder.restoreCallingIdentity(ident);
1629 }
1630 }
1631
1632 public String[] getRemovedSystemPowerWhitelistApps() {
1633 return getRemovedSystemPowerWhitelistAppsInternal();
1634 }
1635
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001636 @Override public String[] getSystemPowerWhitelistExceptIdle() {
1637 return getSystemPowerWhitelistExceptIdleInternal();
1638 }
1639
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001640 @Override public String[] getSystemPowerWhitelist() {
1641 return getSystemPowerWhitelistInternal();
1642 }
1643
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001644 @Override public String[] getUserPowerWhitelist() {
1645 return getUserPowerWhitelistInternal();
1646 }
1647
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001648 @Override public String[] getFullPowerWhitelistExceptIdle() {
1649 return getFullPowerWhitelistExceptIdleInternal();
1650 }
1651
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001652 @Override public String[] getFullPowerWhitelist() {
1653 return getFullPowerWhitelistInternal();
1654 }
1655
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001656 @Override public int[] getAppIdWhitelistExceptIdle() {
1657 return getAppIdWhitelistExceptIdleInternal();
1658 }
1659
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001660 @Override public int[] getAppIdWhitelist() {
1661 return getAppIdWhitelistInternal();
1662 }
1663
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001664 @Override public int[] getAppIdUserWhitelist() {
1665 return getAppIdUserWhitelistInternal();
1666 }
1667
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001668 @Override public int[] getAppIdTempWhitelist() {
1669 return getAppIdTempWhitelistInternal();
1670 }
1671
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001672 @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
1673 return isPowerSaveWhitelistExceptIdleAppInternal(name);
1674 }
1675
Amith Yamasani06bf8242015-05-08 16:36:21 -07001676 @Override public boolean isPowerSaveWhitelistApp(String name) {
1677 return isPowerSaveWhitelistAppInternal(name);
1678 }
1679
Kweku Adams835283f2019-11-20 14:41:22 -08001680 @Override
1681 public long whitelistAppTemporarily(String packageName, int userId, String reason)
1682 throws RemoteException {
1683 // At least 10 seconds.
1684 long duration = Math.max(10_000L, mConstants.MAX_TEMP_APP_WHITELIST_DURATION / 2);
1685 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1686 return duration;
1687 }
1688
1689 @Override
1690 public void addPowerSaveTempWhitelistApp(String packageName, long duration,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001691 int userId, String reason) throws RemoteException {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001692 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001693 }
1694
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001695 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
1696 int userId, String reason) throws RemoteException {
1697 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001698 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001699 return duration;
1700 }
1701
Dianne Hackborn451c3462015-07-21 17:39:46 -07001702 @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
1703 int userId, String reason) throws RemoteException {
1704 long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001705 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Dianne Hackborn451c3462015-07-21 17:39:46 -07001706 return duration;
1707 }
1708
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001709 @Override public void exitIdle(String reason) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001710 getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001711 null);
Dianne Hackbornc9b2cd12016-01-20 10:54:29 -08001712 long ident = Binder.clearCallingIdentity();
1713 try {
1714 exitIdleInternal(reason);
1715 } finally {
1716 Binder.restoreCallingIdentity(ident);
1717 }
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001718 }
1719
Denny cy Leec5a7c292019-01-01 17:37:55 +08001720 @Override public int setPreIdleTimeoutMode(int mode) {
1721 getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1722 null);
1723 long ident = Binder.clearCallingIdentity();
1724 try {
1725 return DeviceIdleController.this.setPreIdleTimeoutMode(mode);
1726 } finally {
1727 Binder.restoreCallingIdentity(ident);
1728 }
1729 }
1730
1731 @Override public void resetPreIdleTimeoutMode() {
1732 getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1733 null);
1734 long ident = Binder.clearCallingIdentity();
1735 try {
1736 DeviceIdleController.this.resetPreIdleTimeoutMode();
1737 } finally {
1738 Binder.restoreCallingIdentity(ident);
1739 }
1740 }
1741
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001742 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1743 DeviceIdleController.this.dump(fd, pw, args);
1744 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001745
1746 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
Dianne Hackborn354736e2016-08-22 17:00:05 -07001747 FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
1748 (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001749 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001750 }
1751
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001752 private class LocalService implements DeviceIdleInternal {
1753 @Override
Robin Lee876b88542018-11-13 17:22:24 +01001754 public void onConstraintStateChanged(IDeviceIdleConstraint constraint, boolean active) {
1755 synchronized (DeviceIdleController.this) {
1756 onConstraintStateChangedLocked(constraint, active);
1757 }
1758 }
1759
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001760 @Override
Robin Lee876b88542018-11-13 17:22:24 +01001761 public void registerDeviceIdleConstraint(IDeviceIdleConstraint constraint, String name,
1762 @IDeviceIdleConstraint.MinimumState int minState) {
1763 registerDeviceIdleConstraintInternal(constraint, name, minState);
1764 }
1765
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001766 @Override
Robin Lee876b88542018-11-13 17:22:24 +01001767 public void unregisterDeviceIdleConstraint(IDeviceIdleConstraint constraint) {
1768 unregisterDeviceIdleConstraintInternal(constraint);
1769 }
1770
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001771 @Override
Robin Lee876b88542018-11-13 17:22:24 +01001772 public void exitIdle(String reason) {
1773 exitIdleInternal(reason);
1774 }
1775
Christopher Tatee0be7e82017-02-08 17:38:20 -08001776 // duration in milliseconds
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001777 @Override
Christopher Tatee0be7e82017-02-08 17:38:20 -08001778 public void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
1779 long duration, int userId, boolean sync, String reason) {
1780 addPowerSaveTempWhitelistAppInternal(callingUid, packageName, duration,
1781 userId, sync, reason);
1782 }
1783
1784 // duration in milliseconds
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001785 @Override
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07001786 public void addPowerSaveTempWhitelistAppDirect(int uid, long duration, boolean sync,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001787 String reason) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07001788 addPowerSaveTempWhitelistAppDirectInternal(0, uid, duration, sync, reason);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001789 }
1790
Christopher Tatee0be7e82017-02-08 17:38:20 -08001791 // duration in milliseconds
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001792 @Override
Felipe Lemea1b79bf2016-05-24 13:06:54 -07001793 public long getNotificationWhitelistDuration() {
1794 return mConstants.NOTIFICATION_WHITELIST_DURATION;
1795 }
1796
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001797 @Override
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001798 public void setJobsActive(boolean active) {
1799 DeviceIdleController.this.setJobsActive(active);
1800 }
1801
1802 // Up-call from alarm manager.
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001803 @Override
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001804 public void setAlarmsActive(boolean active) {
1805 DeviceIdleController.this.setAlarmsActive(active);
1806 }
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001807
Christopher Tate42a386b2016-11-07 12:21:21 -08001808 /** Is the app on any of the power save whitelists, whether system or user? */
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001809 @Override
Christopher Tate42a386b2016-11-07 12:21:21 -08001810 public boolean isAppOnWhitelist(int appid) {
1811 return DeviceIdleController.this.isAppOnWhitelistInternal(appid);
1812 }
1813
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001814 /**
1815 * Returns the array of app ids whitelisted by user. Take care not to
1816 * modify this, as it is a reference to the original copy. But the reference
1817 * can change when the list changes, so it needs to be re-acquired when
1818 * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent.
1819 */
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001820 @Override
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001821 public int[] getPowerSaveWhitelistUserAppIds() {
1822 return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
1823 }
Suprabh Shuklaa78acfd2017-10-13 19:29:36 -07001824
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001825 @Override
Suprabh Shuklaa78acfd2017-10-13 19:29:36 -07001826 public int[] getPowerSaveTempWhitelistAppIds() {
1827 return DeviceIdleController.this.getAppIdTempWhitelistInternal();
1828 }
Kweku Adams810c77d2019-08-28 07:45:00 -07001829
1830 @Override
1831 public void registerStationaryListener(StationaryListener listener) {
1832 DeviceIdleController.this.registerStationaryListener(listener);
1833 }
1834
1835 @Override
1836 public void unregisterStationaryListener(StationaryListener listener) {
1837 DeviceIdleController.this.unregisterStationaryListener(listener);
1838 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001839 }
1840
Kweku Adams00e3a372018-09-28 16:57:09 -07001841 static class Injector {
1842 private final Context mContext;
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07001843 private ConnectivityManager mConnectivityManager;
Kweku Adams9da2bb92018-12-20 06:34:39 -08001844 private Constants mConstants;
Kweku Adams799858b2018-10-08 17:19:08 -07001845 private LocationManager mLocationManager;
Kweku Adams00e3a372018-09-28 16:57:09 -07001846
1847 Injector(Context ctx) {
1848 mContext = ctx;
1849 }
1850
1851 AlarmManager getAlarmManager() {
1852 return mContext.getSystemService(AlarmManager.class);
1853 }
1854
1855 AnyMotionDetector getAnyMotionDetector(Handler handler, SensorManager sm,
1856 AnyMotionDetector.DeviceIdleCallback callback, float angleThreshold) {
1857 return new AnyMotionDetector(getPowerManager(), handler, sm, callback, angleThreshold);
1858 }
1859
1860 AppStateTracker getAppStateTracker(Context ctx, Looper looper) {
1861 return new AppStateTracker(ctx, looper);
1862 }
1863
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07001864 ConnectivityManager getConnectivityManager() {
1865 if (mConnectivityManager == null) {
1866 mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
Kweku Adams799858b2018-10-08 17:19:08 -07001867 }
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07001868 return mConnectivityManager;
Kweku Adams00e3a372018-09-28 16:57:09 -07001869 }
1870
Kweku Adamsa457f4e2018-10-03 15:56:06 -07001871 Constants getConstants(DeviceIdleController controller, Handler handler,
1872 ContentResolver resolver) {
Kweku Adams9da2bb92018-12-20 06:34:39 -08001873 if (mConstants == null) {
1874 mConstants = controller.new Constants(handler, resolver);
1875 }
1876 return mConstants;
Kweku Adamsa457f4e2018-10-03 15:56:06 -07001877 }
1878
Kweku Adamsecf98fb2019-07-22 17:12:41 -07001879
1880 /** Returns the current elapsed realtime in milliseconds. */
1881 long getElapsedRealtime() {
1882 return SystemClock.elapsedRealtime();
1883 }
1884
Kweku Adams00e3a372018-09-28 16:57:09 -07001885 LocationManager getLocationManager() {
Kweku Adams799858b2018-10-08 17:19:08 -07001886 if (mLocationManager == null) {
1887 mLocationManager = mContext.getSystemService(LocationManager.class);
1888 }
1889 return mLocationManager;
Kweku Adams00e3a372018-09-28 16:57:09 -07001890 }
1891
Kweku Adamsa457f4e2018-10-03 15:56:06 -07001892 MyHandler getHandler(DeviceIdleController controller) {
1893 return controller.new MyHandler(BackgroundThread.getHandler().getLooper());
Kweku Adams00e3a372018-09-28 16:57:09 -07001894 }
1895
Kweku Adamsa890d282019-12-19 16:08:43 -08001896 Sensor getMotionSensor() {
1897 final SensorManager sensorManager = getSensorManager();
1898 Sensor motionSensor = null;
1899 int sigMotionSensorId = mContext.getResources().getInteger(
1900 com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
1901 if (sigMotionSensorId > 0) {
1902 motionSensor = sensorManager.getDefaultSensor(sigMotionSensorId, true);
1903 }
1904 if (motionSensor == null && mContext.getResources().getBoolean(
1905 com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
1906 motionSensor = sensorManager.getDefaultSensor(
1907 Sensor.TYPE_WRIST_TILT_GESTURE, true);
1908 }
1909 if (motionSensor == null) {
1910 // As a last ditch, fall back to SMD.
1911 motionSensor = sensorManager.getDefaultSensor(
1912 Sensor.TYPE_SIGNIFICANT_MOTION, true);
1913 }
1914 return motionSensor;
1915 }
1916
Kweku Adams00e3a372018-09-28 16:57:09 -07001917 PowerManager getPowerManager() {
1918 return mContext.getSystemService(PowerManager.class);
1919 }
Robin Lee876b88542018-11-13 17:22:24 +01001920
1921 SensorManager getSensorManager() {
1922 return mContext.getSystemService(SensorManager.class);
1923 }
1924
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001925 ConstraintController getConstraintController(Handler handler,
1926 DeviceIdleInternal localService) {
Robin Lee876b88542018-11-13 17:22:24 +01001927 if (mContext.getPackageManager()
1928 .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
1929 return new TvConstraintController(mContext, handler);
1930 }
1931 return null;
1932 }
1933
1934 boolean useMotionSensor() {
1935 return mContext.getResources().getBoolean(
1936 com.android.internal.R.bool.config_autoPowerModeUseMotionSensor);
1937 }
Kweku Adams00e3a372018-09-28 16:57:09 -07001938 }
1939
1940 private final Injector mInjector;
1941
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001942 private ActivityTaskManagerInternal.ScreenObserver mScreenObserver =
1943 new ActivityTaskManagerInternal.ScreenObserver() {
Amith Yamasani396a10c2018-01-19 10:58:07 -08001944 @Override
1945 public void onAwakeStateChanged(boolean isAwake) { }
1946
1947 @Override
1948 public void onKeyguardStateChanged(boolean isShowing) {
1949 synchronized (DeviceIdleController.this) {
1950 DeviceIdleController.this.keyguardShowingLocked(isShowing);
1951 }
1952 }
1953 };
1954
Kweku Adams00e3a372018-09-28 16:57:09 -07001955 @VisibleForTesting DeviceIdleController(Context context, Injector injector) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001956 super(context);
Kweku Adams00e3a372018-09-28 16:57:09 -07001957 mInjector = injector;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001958 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
Kweku Adams00e3a372018-09-28 16:57:09 -07001959 mHandler = mInjector.getHandler(this);
1960 mAppStateTracker = mInjector.getAppStateTracker(context, FgThread.get().getLooper());
Makoto Onukie4918212018-02-06 11:30:15 -08001961 LocalServices.addService(AppStateTracker.class, mAppStateTracker);
Robin Lee876b88542018-11-13 17:22:24 +01001962 mUseMotionSensor = mInjector.useMotionSensor();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001963 }
1964
Kweku Adams00e3a372018-09-28 16:57:09 -07001965 public DeviceIdleController(Context context) {
1966 this(context, new Injector(context));
1967 }
1968
Christopher Tate42a386b2016-11-07 12:21:21 -08001969 boolean isAppOnWhitelistInternal(int appid) {
1970 synchronized (this) {
1971 return Arrays.binarySearch(mPowerSaveWhitelistAllAppIdArray, appid) >= 0;
1972 }
1973 }
1974
Amith Yamasanicb926fc2016-03-14 17:15:20 -07001975 int[] getPowerSaveWhitelistUserAppIds() {
1976 synchronized (this) {
1977 return mPowerSaveWhitelistUserAppIdArray;
1978 }
1979 }
1980
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001981 private static File getSystemDir() {
1982 return new File(Environment.getDataDirectory(), "system");
1983 }
1984
1985 @Override
1986 public void onStart() {
1987 final PackageManager pm = getContext().getPackageManager();
1988
1989 synchronized (this) {
Dianne Hackbornb6843652016-02-22 12:20:13 -08001990 mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean(
Dianne Hackborn92617032015-06-19 15:32:19 -07001991 com.android.internal.R.bool.config_enableAutoPowerModes);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001992 SystemConfig sysConfig = SystemConfig.getInstance();
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001993 ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
1994 for (int i=0; i<allowPowerExceptIdle.size(); i++) {
1995 String pkg = allowPowerExceptIdle.valueAt(i);
1996 try {
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07001997 ApplicationInfo ai = pm.getApplicationInfo(pkg,
1998 PackageManager.MATCH_SYSTEM_ONLY);
1999 int appid = UserHandle.getAppId(ai.uid);
2000 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
2001 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002002 } catch (PackageManager.NameNotFoundException e) {
2003 }
2004 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002005 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
2006 for (int i=0; i<allowPower.size(); i++) {
2007 String pkg = allowPower.valueAt(i);
2008 try {
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07002009 ApplicationInfo ai = pm.getApplicationInfo(pkg,
2010 PackageManager.MATCH_SYSTEM_ONLY);
2011 int appid = UserHandle.getAppId(ai.uid);
2012 // These apps are on both the whitelist-except-idle as well
2013 // as the full whitelist, so they apply in all cases.
2014 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
2015 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
2016 mPowerSaveWhitelistApps.put(ai.packageName, appid);
2017 mPowerSaveWhitelistSystemAppIds.put(appid, true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002018 } catch (PackageManager.NameNotFoundException e) {
2019 }
2020 }
2021
Kweku Adamsa457f4e2018-10-03 15:56:06 -07002022 mConstants = mInjector.getConstants(this, mHandler, getContext().getContentResolver());
Adam Lesinski31c05d12015-06-09 17:34:04 -07002023
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002024 readConfigFileLocked();
2025 updateWhitelistAppIdsLocked();
2026
Dianne Hackborn88c41352016-04-07 15:18:58 -07002027 mNetworkConnected = true;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002028 mScreenOn = true;
Amith Yamasani396a10c2018-01-19 10:58:07 -08002029 mScreenLocked = false;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002030 // Start out assuming we are charging. If we aren't, we will at least get
2031 // a battery update the next time the level drops.
2032 mCharging = true;
Denny cy Leec5a7c292019-01-01 17:37:55 +08002033 mActiveReason = ACTIVE_REASON_UNKNOWN;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002034 mState = STATE_ACTIVE;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002035 mLightState = LIGHT_STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -07002036 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Denny cy Leec5a7c292019-01-01 17:37:55 +08002037 mPreIdleFactor = 1.0f;
2038 mLastPreIdleFactor = 1.0f;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002039 }
2040
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002041 mBinderService = new BinderService();
2042 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);
Kweku Adams810c77d2019-08-28 07:45:00 -07002043 mLocalService = new LocalService();
2044 publishLocalService(DeviceIdleInternal.class, mLocalService);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002045 }
2046
2047 @Override
2048 public void onBootPhase(int phase) {
2049 if (phase == PHASE_SYSTEM_SERVICES_READY) {
2050 synchronized (this) {
Kweku Adams00e3a372018-09-28 16:57:09 -07002051 mAlarmManager = mInjector.getAlarmManager();
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002052 mLocalAlarmManager = getLocalService(AlarmManagerInternal.class);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002053 mBatteryStats = BatteryStatsService.getService();
Dianne Hackborn85e35642017-01-12 15:10:57 -08002054 mLocalActivityManager = getLocalService(ActivityManagerInternal.class);
Wale Ogunwale6767eae2018-05-03 15:52:51 -07002055 mLocalActivityTaskManager = getLocalService(ActivityTaskManagerInternal.class);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002056 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
Kweku Adams00e3a372018-09-28 16:57:09 -07002057 mPowerManager = mInjector.getPowerManager();
Dianne Hackborn945c9c92016-03-30 14:55:00 -07002058 mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
2059 "deviceidle_maint");
2060 mActiveIdleWakeLock.setReferenceCounted(false);
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08002061 mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
2062 "deviceidle_going_idle");
2063 mGoingIdleWakeLock.setReferenceCounted(true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002064 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002065 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07002066 mNetworkPolicyManagerInternal = getLocalService(NetworkPolicyManagerInternal.class);
Robin Lee876b88542018-11-13 17:22:24 +01002067 mSensorManager = mInjector.getSensorManager();
Robin Leec4d424c2018-12-07 15:09:13 +01002068
2069 if (mUseMotionSensor) {
Kweku Adamsa890d282019-12-19 16:08:43 -08002070 mMotionSensor = mInjector.getMotionSensor();
Joe LaPenna23d681b2015-08-27 15:12:11 -07002071 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -07002072
Joe LaPenna23d681b2015-08-27 15:12:11 -07002073 if (getContext().getResources().getBoolean(
2074 com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07002075 mLocationRequest = LocationRequest.create()
Joe LaPenna23d681b2015-08-27 15:12:11 -07002076 .setQuality(LocationRequest.ACCURACY_FINE)
2077 .setInterval(0)
2078 .setFastestInterval(0)
2079 .setNumUpdates(1);
2080 }
2081
Robin Lee876b88542018-11-13 17:22:24 +01002082 mConstraintController = mInjector.getConstraintController(
2083 mHandler, getLocalService(LocalService.class));
2084 if (mConstraintController != null) {
2085 mConstraintController.start();
2086 }
2087
Joe LaPenna23d681b2015-08-27 15:12:11 -07002088 float angleThreshold = getContext().getResources().getInteger(
2089 com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
Kweku Adams00e3a372018-09-28 16:57:09 -07002090 mAnyMotionDetector = mInjector.getAnyMotionDetector(mHandler, mSensorManager, this,
2091 angleThreshold);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002092
Makoto Onukie4918212018-02-06 11:30:15 -08002093 mAppStateTracker.onSystemServicesReady();
2094
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002095 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002096 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
2097 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002098 mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
2099 mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
2100 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002101
2102 IntentFilter filter = new IntentFilter();
2103 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002104 getContext().registerReceiver(mReceiver, filter);
Amith Yamasaniac59f75e2016-05-05 12:38:17 -07002105
Dianne Hackborn1b79ad72015-10-12 10:59:47 -07002106 filter = new IntentFilter();
2107 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2108 filter.addDataScheme("package");
Amith Yamasaniac59f75e2016-05-05 12:38:17 -07002109 getContext().registerReceiver(mReceiver, filter);
2110
Dianne Hackborn88c41352016-04-07 15:18:58 -07002111 filter = new IntentFilter();
2112 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Dianne Hackborn1b79ad72015-10-12 10:59:47 -07002113 getContext().registerReceiver(mReceiver, filter);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002114
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -07002115 filter = new IntentFilter();
2116 filter.addAction(Intent.ACTION_SCREEN_OFF);
2117 filter.addAction(Intent.ACTION_SCREEN_ON);
2118 getContext().registerReceiver(mInteractivityReceiver, filter);
2119
Makoto Onukiaf8ff4f2018-06-04 14:44:19 -07002120 mLocalActivityManager.setDeviceIdleWhitelist(
2121 mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002122 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -07002123
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002124 mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE,
2125 state -> {
2126 synchronized (DeviceIdleController.this) {
2127 updateQuickDozeFlagLocked(state.batterySaverEnabled);
2128 }
2129 });
2130 updateQuickDozeFlagLocked(
2131 mLocalPowerManager.getLowPowerState(
2132 ServiceType.QUICK_DOZE).batterySaverEnabled);
2133
Wale Ogunwale6767eae2018-05-03 15:52:51 -07002134 mLocalActivityTaskManager.registerScreenObserver(mScreenObserver);
Amith Yamasani396a10c2018-01-19 10:58:07 -08002135
Suprabh Shukla5bf49812018-05-24 18:38:50 -07002136 passWhiteListsToForceAppStandbyTrackerLocked();
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -07002137 updateInteractivityLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002138 }
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -07002139 updateConnectivityState(null);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002140 }
2141 }
2142
Robin Lee876b88542018-11-13 17:22:24 +01002143 @VisibleForTesting
2144 boolean hasMotionSensor() {
2145 return mUseMotionSensor && mMotionSensor != null;
2146 }
2147
2148 private void registerDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint,
2149 final String name, final int type) {
2150 final int minState;
2151 switch (type) {
2152 case IDeviceIdleConstraint.ACTIVE:
2153 minState = STATE_ACTIVE;
2154 break;
2155 case IDeviceIdleConstraint.SENSING_OR_ABOVE:
2156 minState = STATE_SENSING;
2157 break;
2158 default:
2159 Slog.wtf(TAG, "Registering device-idle constraint with invalid type: " + type);
2160 return;
2161 }
2162 synchronized (this) {
2163 if (mConstraints.containsKey(constraint)) {
2164 Slog.e(TAG, "Re-registering device-idle constraint: " + constraint + ".");
2165 return;
2166 }
2167 DeviceIdleConstraintTracker tracker = new DeviceIdleConstraintTracker(name, minState);
2168 mConstraints.put(constraint, tracker);
2169 updateActiveConstraintsLocked();
2170 }
2171 }
2172
2173 private void unregisterDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint) {
2174 synchronized (this) {
Kweku Adamsecf98fb2019-07-22 17:12:41 -07002175 // Artificially force the constraint to inactive to unblock anything waiting for it.
Robin Lee876b88542018-11-13 17:22:24 +01002176 onConstraintStateChangedLocked(constraint, /* active= */ false);
2177
2178 // Let the constraint know that we are not listening to it any more.
2179 setConstraintMonitoringLocked(constraint, /* monitoring= */ false);
2180 mConstraints.remove(constraint);
2181 }
2182 }
2183
2184 @GuardedBy("this")
2185 private void onConstraintStateChangedLocked(IDeviceIdleConstraint constraint, boolean active) {
2186 DeviceIdleConstraintTracker tracker = mConstraints.get(constraint);
2187 if (tracker == null) {
2188 Slog.e(TAG, "device-idle constraint " + constraint + " has not been registered.");
2189 return;
2190 }
2191 if (active != tracker.active && tracker.monitoring) {
2192 tracker.active = active;
2193 mNumBlockingConstraints += (tracker.active ? +1 : -1);
2194 if (mNumBlockingConstraints == 0) {
2195 if (mState == STATE_ACTIVE) {
2196 becomeInactiveIfAppropriateLocked();
2197 } else if (mNextAlarmTime == 0 || mNextAlarmTime < SystemClock.elapsedRealtime()) {
2198 stepIdleStateLocked("s:" + tracker.name);
2199 }
2200 }
2201 }
2202 }
2203
2204 @GuardedBy("this")
2205 private void setConstraintMonitoringLocked(IDeviceIdleConstraint constraint, boolean monitor) {
2206 DeviceIdleConstraintTracker tracker = mConstraints.get(constraint);
2207 if (tracker.monitoring != monitor) {
2208 tracker.monitoring = monitor;
2209 updateActiveConstraintsLocked();
2210 // We send the callback on a separate thread instead of just relying on oneway as
2211 // the client could be in the system server with us and cause re-entry problems.
2212 mHandler.obtainMessage(MSG_SEND_CONSTRAINT_MONITORING,
2213 /* monitoring= */ monitor ? 1 : 0,
2214 /* <not used>= */ -1,
2215 /* constraint= */ constraint).sendToTarget();
2216 }
2217 }
2218
2219 @GuardedBy("this")
2220 private void updateActiveConstraintsLocked() {
2221 mNumBlockingConstraints = 0;
2222 for (int i = 0; i < mConstraints.size(); i++) {
2223 final IDeviceIdleConstraint constraint = mConstraints.keyAt(i);
2224 final DeviceIdleConstraintTracker tracker = mConstraints.valueAt(i);
2225 final boolean monitoring = (tracker.minState == mState);
2226 if (monitoring != tracker.monitoring) {
2227 setConstraintMonitoringLocked(constraint, monitoring);
2228 tracker.active = monitoring;
2229 }
2230 if (tracker.monitoring && tracker.active) {
2231 mNumBlockingConstraints++;
2232 }
2233 }
2234 }
2235
Kweku Adamsc2400c82019-10-09 15:56:04 -07002236 private int addPowerSaveWhitelistAppsInternal(List<String> pkgNames) {
2237 int numAdded = 0;
2238 int numErrors = 0;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002239 synchronized (this) {
Kweku Adamsc2400c82019-10-09 15:56:04 -07002240 for (int i = pkgNames.size() - 1; i >= 0; --i) {
2241 final String name = pkgNames.get(i);
2242 if (name == null) {
2243 numErrors++;
2244 continue;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002245 }
Kweku Adamsc2400c82019-10-09 15:56:04 -07002246 try {
2247 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
2248 PackageManager.MATCH_ANY_USER);
2249 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid))
2250 == null) {
2251 numAdded++;
2252 }
2253 } catch (PackageManager.NameNotFoundException e) {
2254 Slog.e(TAG, "Tried to add unknown package to power save whitelist: " + name);
2255 numErrors++;
2256 }
2257 }
2258 if (numAdded > 0) {
2259 reportPowerSaveWhitelistChangedLocked();
2260 updateWhitelistAppIdsLocked();
2261 writeConfigFileLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002262 }
2263 }
Kweku Adamsc2400c82019-10-09 15:56:04 -07002264 return pkgNames.size() - numErrors;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002265 }
2266
2267 public boolean removePowerSaveWhitelistAppInternal(String name) {
2268 synchronized (this) {
2269 if (mPowerSaveWhitelistUserApps.remove(name) != null) {
2270 reportPowerSaveWhitelistChangedLocked();
2271 updateWhitelistAppIdsLocked();
2272 writeConfigFileLocked();
2273 return true;
2274 }
2275 }
2276 return false;
2277 }
2278
Felipe Lemef8a46232016-02-10 13:51:54 -08002279 public boolean getPowerSaveWhitelistAppInternal(String name) {
2280 synchronized (this) {
2281 return mPowerSaveWhitelistUserApps.containsKey(name);
2282 }
2283 }
2284
Suprabh Shukla08105642017-09-26 14:45:30 -07002285 void resetSystemPowerWhitelistInternal() {
2286 synchronized (this) {
2287 mPowerSaveWhitelistApps.putAll(mRemovedFromSystemWhitelistApps);
2288 mRemovedFromSystemWhitelistApps.clear();
2289 reportPowerSaveWhitelistChangedLocked();
2290 updateWhitelistAppIdsLocked();
2291 writeConfigFileLocked();
2292 }
2293 }
2294
2295 public boolean restoreSystemPowerWhitelistAppInternal(String name) {
2296 synchronized (this) {
2297 if (!mRemovedFromSystemWhitelistApps.containsKey(name)) {
2298 return false;
2299 }
2300 mPowerSaveWhitelistApps.put(name, mRemovedFromSystemWhitelistApps.remove(name));
2301 reportPowerSaveWhitelistChangedLocked();
2302 updateWhitelistAppIdsLocked();
2303 writeConfigFileLocked();
2304 return true;
2305 }
2306 }
2307
2308 public boolean removeSystemPowerWhitelistAppInternal(String name) {
2309 synchronized (this) {
2310 if (!mPowerSaveWhitelistApps.containsKey(name)) {
2311 return false;
2312 }
2313 mRemovedFromSystemWhitelistApps.put(name, mPowerSaveWhitelistApps.remove(name));
2314 reportPowerSaveWhitelistChangedLocked();
2315 updateWhitelistAppIdsLocked();
2316 writeConfigFileLocked();
2317 return true;
2318 }
2319 }
2320
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07002321 public boolean addPowerSaveWhitelistExceptIdleInternal(String name) {
2322 synchronized (this) {
2323 try {
2324 final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
2325 PackageManager.MATCH_ANY_USER);
2326 if (mPowerSaveWhitelistAppsExceptIdle.put(name, UserHandle.getAppId(ai.uid))
2327 == null) {
2328 mPowerSaveWhitelistUserAppsExceptIdle.add(name);
2329 reportPowerSaveWhitelistChangedLocked();
2330 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
2331 mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
2332 mPowerSaveWhitelistExceptIdleAppIds);
Makoto Onuki71755c92018-01-16 14:15:44 -08002333
Suprabh Shukla5bf49812018-05-24 18:38:50 -07002334 passWhiteListsToForceAppStandbyTrackerLocked();
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07002335 }
2336 return true;
2337 } catch (PackageManager.NameNotFoundException e) {
2338 return false;
2339 }
2340 }
2341 }
2342
2343 public void resetPowerSaveWhitelistExceptIdleInternal() {
2344 synchronized (this) {
2345 if (mPowerSaveWhitelistAppsExceptIdle.removeAll(
2346 mPowerSaveWhitelistUserAppsExceptIdle)) {
2347 reportPowerSaveWhitelistChangedLocked();
2348 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
2349 mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
2350 mPowerSaveWhitelistExceptIdleAppIds);
2351 mPowerSaveWhitelistUserAppsExceptIdle.clear();
Makoto Onuki71755c92018-01-16 14:15:44 -08002352
Suprabh Shukla5bf49812018-05-24 18:38:50 -07002353 passWhiteListsToForceAppStandbyTrackerLocked();
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07002354 }
2355 }
2356 }
2357
2358 public boolean getPowerSaveWhitelistExceptIdleInternal(String name) {
2359 synchronized (this) {
2360 return mPowerSaveWhitelistAppsExceptIdle.containsKey(name);
2361 }
2362 }
2363
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002364 public String[] getSystemPowerWhitelistExceptIdleInternal() {
2365 synchronized (this) {
2366 int size = mPowerSaveWhitelistAppsExceptIdle.size();
2367 String[] apps = new String[size];
2368 for (int i = 0; i < size; i++) {
2369 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
2370 }
2371 return apps;
2372 }
2373 }
2374
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002375 public String[] getSystemPowerWhitelistInternal() {
2376 synchronized (this) {
2377 int size = mPowerSaveWhitelistApps.size();
2378 String[] apps = new String[size];
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002379 for (int i = 0; i < size; i++) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002380 apps[i] = mPowerSaveWhitelistApps.keyAt(i);
2381 }
2382 return apps;
2383 }
2384 }
2385
Suprabh Shukla08105642017-09-26 14:45:30 -07002386 public String[] getRemovedSystemPowerWhitelistAppsInternal() {
2387 synchronized (this) {
2388 int size = mRemovedFromSystemWhitelistApps.size();
2389 final String[] apps = new String[size];
2390 for (int i = 0; i < size; i++) {
2391 apps[i] = mRemovedFromSystemWhitelistApps.keyAt(i);
2392 }
2393 return apps;
2394 }
2395 }
2396
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08002397 public String[] getUserPowerWhitelistInternal() {
2398 synchronized (this) {
2399 int size = mPowerSaveWhitelistUserApps.size();
2400 String[] apps = new String[size];
2401 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2402 apps[i] = mPowerSaveWhitelistUserApps.keyAt(i);
2403 }
2404 return apps;
2405 }
2406 }
2407
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002408 public String[] getFullPowerWhitelistExceptIdleInternal() {
2409 synchronized (this) {
2410 int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
2411 String[] apps = new String[size];
2412 int cur = 0;
2413 for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
2414 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
2415 cur++;
2416 }
2417 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2418 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
2419 cur++;
2420 }
2421 return apps;
2422 }
2423 }
2424
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002425 public String[] getFullPowerWhitelistInternal() {
2426 synchronized (this) {
2427 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
2428 String[] apps = new String[size];
2429 int cur = 0;
2430 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
2431 apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
2432 cur++;
2433 }
2434 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2435 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
2436 cur++;
2437 }
2438 return apps;
2439 }
2440 }
2441
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002442 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
2443 synchronized (this) {
2444 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
2445 || mPowerSaveWhitelistUserApps.containsKey(packageName);
2446 }
2447 }
2448
Amith Yamasani06bf8242015-05-08 16:36:21 -07002449 public boolean isPowerSaveWhitelistAppInternal(String packageName) {
2450 synchronized (this) {
2451 return mPowerSaveWhitelistApps.containsKey(packageName)
2452 || mPowerSaveWhitelistUserApps.containsKey(packageName);
2453 }
2454 }
2455
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002456 public int[] getAppIdWhitelistExceptIdleInternal() {
2457 synchronized (this) {
2458 return mPowerSaveWhitelistExceptIdleAppIdArray;
2459 }
2460 }
2461
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002462 public int[] getAppIdWhitelistInternal() {
2463 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002464 return mPowerSaveWhitelistAllAppIdArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002465 }
2466 }
2467
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08002468 public int[] getAppIdUserWhitelistInternal() {
2469 synchronized (this) {
2470 return mPowerSaveWhitelistUserAppIdArray;
2471 }
2472 }
2473
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002474 public int[] getAppIdTempWhitelistInternal() {
2475 synchronized (this) {
2476 return mTempWhitelistAppIdArray;
2477 }
2478 }
2479
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002480 void addPowerSaveTempWhitelistAppChecked(String packageName, long duration,
2481 int userId, String reason) throws RemoteException {
2482 getContext().enforceCallingPermission(
2483 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
2484 "No permission to change device idle whitelist");
2485 final int callingUid = Binder.getCallingUid();
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002486 userId = ActivityManager.getService().handleIncomingUser(
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002487 Binder.getCallingPid(),
2488 callingUid,
2489 userId,
2490 /*allowAll=*/ false,
2491 /*requireFull=*/ false,
2492 "addPowerSaveTempWhitelistApp", null);
2493 final long token = Binder.clearCallingIdentity();
2494 try {
2495 addPowerSaveTempWhitelistAppInternal(callingUid,
2496 packageName, duration, userId, true, reason);
2497 } finally {
2498 Binder.restoreCallingIdentity(token);
2499 }
2500 }
2501
Sudheer Shanka326b3112017-11-27 14:40:57 -08002502 void removePowerSaveTempWhitelistAppChecked(String packageName, int userId)
2503 throws RemoteException {
2504 getContext().enforceCallingPermission(
2505 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
2506 "No permission to change device idle whitelist");
2507 final int callingUid = Binder.getCallingUid();
2508 userId = ActivityManager.getService().handleIncomingUser(
2509 Binder.getCallingPid(),
2510 callingUid,
2511 userId,
2512 /*allowAll=*/ false,
2513 /*requireFull=*/ false,
2514 "removePowerSaveTempWhitelistApp", null);
2515 final long token = Binder.clearCallingIdentity();
2516 try {
2517 removePowerSaveTempWhitelistAppInternal(packageName, userId);
2518 } finally {
2519 Binder.restoreCallingIdentity(token);
2520 }
2521 }
2522
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002523 /**
2524 * Adds an app to the temporary whitelist and resets the endTime for granting the
2525 * app an exemption to access network and acquire wakelocks.
2526 */
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002527 void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002528 long duration, int userId, boolean sync, String reason) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002529 try {
Jeff Sharkeye06b4d12016-01-06 14:51:50 -07002530 int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId);
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002531 addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, duration, sync, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002532 } catch (NameNotFoundException e) {
2533 }
2534 }
2535
Dianne Hackborna750a632015-06-16 17:18:23 -07002536 /**
2537 * Adds an app to the temporary whitelist and resets the endTime for granting the
2538 * app an exemption to access network and acquire wakelocks.
2539 */
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002540 void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int uid,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002541 long duration, boolean sync, String reason) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002542 final long timeNow = SystemClock.elapsedRealtime();
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07002543 boolean informWhitelistChanged = false;
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002544 int appId = UserHandle.getAppId(uid);
Dianne Hackborna750a632015-06-16 17:18:23 -07002545 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002546 int callingAppId = UserHandle.getAppId(callingUid);
2547 if (callingAppId >= Process.FIRST_APPLICATION_UID) {
2548 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
2549 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
2550 + " is not on whitelist");
2551 }
2552 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002553 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002554 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
2555 final boolean newEntry = entry == null;
Dianne Hackborna750a632015-06-16 17:18:23 -07002556 // Set the new end time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002557 if (newEntry) {
2558 entry = new Pair<>(new MutableLong(0), reason);
2559 mTempWhitelistAppIdEndTimes.put(appId, entry);
2560 }
2561 entry.first.value = timeNow + duration;
Dianne Hackborna750a632015-06-16 17:18:23 -07002562 if (DEBUG) {
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002563 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist. New entry: " + newEntry);
Dianne Hackborna750a632015-06-16 17:18:23 -07002564 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002565 if (newEntry) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002566 // No pending timeout for the app id, post a delayed message
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002567 try {
2568 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002569 reason, uid);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002570 } catch (RemoteException e) {
2571 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002572 postTempActiveTimeoutMessage(appId, duration);
Dianne Hackborn85e35642017-01-12 15:10:57 -08002573 updateTempWhitelistAppIdsLocked(appId, true);
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07002574 if (sync) {
2575 informWhitelistChanged = true;
2576 } else {
2577 mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED, appId, 1)
2578 .sendToTarget();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002579 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002580 reportTempWhitelistChangedLocked();
2581 }
2582 }
Sudheer Shankaf34f3ec2017-08-03 11:02:56 -07002583 if (informWhitelistChanged) {
2584 mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002585 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002586 }
2587
Sudheer Shanka326b3112017-11-27 14:40:57 -08002588 /**
2589 * Removes an app from the temporary whitelist and notifies the observers.
2590 */
2591 private void removePowerSaveTempWhitelistAppInternal(String packageName, int userId) {
2592 try {
2593 final int uid = getContext().getPackageManager().getPackageUidAsUser(
2594 packageName, userId);
2595 final int appId = UserHandle.getAppId(uid);
2596 removePowerSaveTempWhitelistAppDirectInternal(appId);
2597 } catch (NameNotFoundException e) {
2598 }
2599 }
2600
2601 private void removePowerSaveTempWhitelistAppDirectInternal(int appId) {
2602 synchronized (this) {
2603 final int idx = mTempWhitelistAppIdEndTimes.indexOfKey(appId);
2604 if (idx < 0) {
2605 // Nothing else to do
2606 return;
2607 }
2608 final String reason = mTempWhitelistAppIdEndTimes.valueAt(idx).second;
2609 mTempWhitelistAppIdEndTimes.removeAt(idx);
2610 onAppRemovedFromTempWhitelistLocked(appId, reason);
2611 }
2612 }
2613
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002614 private void postTempActiveTimeoutMessage(int appId, long delay) {
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002615 if (DEBUG) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002616 Slog.d(TAG, "postTempActiveTimeoutMessage: appId=" + appId + ", delay=" + delay);
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002617 }
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002618 mHandler.sendMessageDelayed(
2619 mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, appId, 0), delay);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002620 }
2621
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002622 void checkTempAppWhitelistTimeout(int appId) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002623 final long timeNow = SystemClock.elapsedRealtime();
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002624 if (DEBUG) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002625 Slog.d(TAG, "checkTempAppWhitelistTimeout: appId=" + appId + ", timeNow=" + timeNow);
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002626 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002627 synchronized (this) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002628 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002629 if (entry == null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002630 // Nothing to do
2631 return;
2632 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002633 if (timeNow >= entry.first.value) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002634 mTempWhitelistAppIdEndTimes.delete(appId);
2635 onAppRemovedFromTempWhitelistLocked(appId, entry.second);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002636 } else {
2637 // Need more time
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002638 if (DEBUG) {
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002639 Slog.d(TAG, "Time to remove AppId " + appId + ": " + entry.first.value);
Felipe Lemea1b79bf2016-05-24 13:06:54 -07002640 }
Nicholas Sauer7d2287b2019-04-11 11:16:34 -07002641 postTempActiveTimeoutMessage(appId, entry.first.value - timeNow);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002642 }
2643 }
2644 }
2645
Sudheer Shanka326b3112017-11-27 14:40:57 -08002646 @GuardedBy("this")
2647 private void onAppRemovedFromTempWhitelistLocked(int appId, String reason) {
2648 if (DEBUG) {
2649 Slog.d(TAG, "Removing appId " + appId + " from temp whitelist");
2650 }
2651 updateTempWhitelistAppIdsLocked(appId, false);
2652 mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED, appId, 0)
2653 .sendToTarget();
2654 reportTempWhitelistChangedLocked();
2655 try {
2656 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
2657 reason, appId);
2658 } catch (RemoteException e) {
2659 }
2660 }
2661
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002662 public void exitIdleInternal(String reason) {
2663 synchronized (this) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002664 mActiveReason = ACTIVE_REASON_FROM_BINDER_CALL;
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002665 becomeActiveLocked(reason, Binder.getCallingUid());
2666 }
2667 }
2668
Kweku Adams799858b2018-10-08 17:19:08 -07002669 @VisibleForTesting
2670 boolean isNetworkConnected() {
2671 synchronized (this) {
2672 return mNetworkConnected;
2673 }
2674 }
2675
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -07002676 void updateConnectivityState(Intent connIntent) {
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07002677 ConnectivityManager cm;
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -07002678 synchronized (this) {
Makoto Onukifa8b0ba2019-10-07 16:49:04 -07002679 cm = mInjector.getConnectivityManager();
Dianne Hackborn4cb96ca2016-05-17 13:55:29 -07002680 }
2681 if (cm == null) {
2682 return;
2683 }
2684 // Note: can't call out to ConnectivityService with our lock held.
2685 NetworkInfo ni = cm.getActiveNetworkInfo();
2686 synchronized (this) {
Dianne Hackborn88c41352016-04-07 15:18:58 -07002687 boolean conn;
2688 if (ni == null) {
2689 conn = false;
2690 } else {
2691 if (connIntent == null) {
2692 conn = ni.isConnected();
2693 } else {
2694 final int networkType =
2695 connIntent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
2696 ConnectivityManager.TYPE_NONE);
2697 if (ni.getType() != networkType) {
2698 return;
2699 }
2700 conn = !connIntent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
2701 false);
2702 }
2703 }
2704 if (conn != mNetworkConnected) {
2705 mNetworkConnected = conn;
2706 if (conn && mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
2707 stepLightIdleStateLocked("network");
2708 }
2709 }
2710 }
2711 }
2712
Kweku Adams00e3a372018-09-28 16:57:09 -07002713 @VisibleForTesting
2714 boolean isScreenOn() {
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002715 synchronized (this) {
2716 return mScreenOn;
2717 }
Kweku Adams00e3a372018-09-28 16:57:09 -07002718 }
2719
Dianne Hackborn3dba8ce2017-09-01 17:07:04 -07002720 void updateInteractivityLocked() {
2721 // The interactivity state from the power manager tells us whether the display is
2722 // in a state that we need to keep things running so they will update at a normal
2723 // frequency.
2724 boolean screenOn = mPowerManager.isInteractive();
2725 if (DEBUG) Slog.d(TAG, "updateInteractivityLocked: screenOn=" + screenOn);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002726 if (!screenOn && mScreenOn) {
2727 mScreenOn = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002728 if (!mForceIdle) {
2729 becomeInactiveIfAppropriateLocked();
2730 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002731 } else if (screenOn) {
2732 mScreenOn = true;
Amith Yamasani396a10c2018-01-19 10:58:07 -08002733 if (!mForceIdle && (!mScreenLocked || !mConstants.WAIT_FOR_UNLOCK)) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002734 mActiveReason = ACTIVE_REASON_SCREEN;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002735 becomeActiveLocked("screen", Process.myUid());
2736 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002737 }
2738 }
2739
Kweku Adams00e3a372018-09-28 16:57:09 -07002740 @VisibleForTesting
2741 boolean isCharging() {
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002742 synchronized (this) {
2743 return mCharging;
2744 }
Kweku Adams00e3a372018-09-28 16:57:09 -07002745 }
2746
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002747 void updateChargingLocked(boolean charging) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07002748 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002749 if (!charging && mCharging) {
2750 mCharging = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002751 if (!mForceIdle) {
2752 becomeInactiveIfAppropriateLocked();
2753 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002754 } else if (charging) {
2755 mCharging = charging;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002756 if (!mForceIdle) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002757 mActiveReason = ACTIVE_REASON_CHARGING;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002758 becomeActiveLocked("charging", Process.myUid());
2759 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002760 }
2761 }
2762
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002763 @VisibleForTesting
2764 boolean isQuickDozeEnabled() {
2765 synchronized (this) {
2766 return mQuickDozeActivated;
2767 }
2768 }
2769
2770 /** Updates the quick doze flag and enters deep doze if appropriate. */
2771 @VisibleForTesting
2772 void updateQuickDozeFlagLocked(boolean enabled) {
2773 if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
2774 mQuickDozeActivated = enabled;
Kweku Adams810c77d2019-08-28 07:45:00 -07002775 mQuickDozeActivatedWhileIdling =
2776 mQuickDozeActivated && (mState == STATE_IDLE || mState == STATE_IDLE_MAINTENANCE);
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002777 if (enabled) {
2778 // If Quick Doze is enabled, see if we should go straight into it.
2779 becomeInactiveIfAppropriateLocked();
2780 }
2781 // Going from Deep Doze to Light Idle (if quick doze becomes disabled) is tricky and
2782 // probably not worth the overhead, so leave in deep doze if that's the case until the
2783 // next natural time to come out of it.
2784 }
2785
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002786
2787 /** Returns true if the screen is locked. */
2788 @VisibleForTesting
2789 boolean isKeyguardShowing() {
2790 synchronized (this) {
2791 return mScreenLocked;
2792 }
2793 }
2794
2795 @VisibleForTesting
Amith Yamasani396a10c2018-01-19 10:58:07 -08002796 void keyguardShowingLocked(boolean showing) {
2797 if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing);
2798 if (mScreenLocked != showing) {
2799 mScreenLocked = showing;
2800 if (mScreenOn && !mForceIdle && !mScreenLocked) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002801 mActiveReason = ACTIVE_REASON_UNLOCKED;
Amith Yamasani396a10c2018-01-19 10:58:07 -08002802 becomeActiveLocked("unlocked", Process.myUid());
2803 }
2804 }
2805 }
2806
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002807 @VisibleForTesting
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002808 void scheduleReportActiveLocked(String activeReason, int activeUid) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002809 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002810 mHandler.sendMessage(msg);
2811 }
2812
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002813 void becomeActiveLocked(String activeReason, int activeUid) {
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002814 becomeActiveLocked(activeReason, activeUid, mConstants.INACTIVE_TIMEOUT, true);
2815 }
2816
2817 private void becomeActiveLocked(String activeReason, int activeUid,
2818 long newInactiveTimeout, boolean changeLightIdle) {
2819 if (DEBUG) {
2820 Slog.i(TAG, "becomeActiveLocked, reason=" + activeReason
2821 + ", changeLightIdle=" + changeLightIdle);
2822 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002823 if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07002824 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002825 mState = STATE_ACTIVE;
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002826 mInactiveTimeout = newInactiveTimeout;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002827 resetIdleManagementLocked();
Kweku Adams7c96f5182019-06-04 16:32:49 -07002828 // Don't reset maintenance window start time if we're in a light idle maintenance window
2829 // because its used in the light idle budget calculation.
2830 if (mLightState != LIGHT_STATE_IDLE_MAINTENANCE) {
2831 mMaintenanceStartTime = 0;
2832 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002833
2834 if (changeLightIdle) {
2835 EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
2836 mLightState = LIGHT_STATE_ACTIVE;
2837 resetLightIdleManagementLocked();
2838 // Only report active if light is also ACTIVE.
2839 scheduleReportActiveLocked(activeReason, activeUid);
2840 addEvent(EVENT_NORMAL, activeReason);
2841 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002842 }
2843 }
2844
Kweku Adams00e3a372018-09-28 16:57:09 -07002845 /** Must only be used in tests. */
2846 @VisibleForTesting
2847 void setDeepEnabledForTest(boolean enabled) {
Kweku Adams799858b2018-10-08 17:19:08 -07002848 synchronized (this) {
2849 mDeepEnabled = enabled;
2850 }
Kweku Adams00e3a372018-09-28 16:57:09 -07002851 }
2852
2853 /** Must only be used in tests. */
2854 @VisibleForTesting
2855 void setLightEnabledForTest(boolean enabled) {
Kweku Adams799858b2018-10-08 17:19:08 -07002856 synchronized (this) {
2857 mLightEnabled = enabled;
2858 }
Kweku Adams00e3a372018-09-28 16:57:09 -07002859 }
2860
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002861 /** Sanity check to make sure DeviceIdleController and AlarmManager are on the same page. */
2862 private void verifyAlarmStateLocked() {
2863 if (mState == STATE_ACTIVE && mNextAlarmTime != 0) {
2864 Slog.wtf(TAG, "mState=ACTIVE but mNextAlarmTime=" + mNextAlarmTime);
2865 }
2866 if (mState != STATE_IDLE && mLocalAlarmManager.isIdling()) {
2867 Slog.wtf(TAG, "mState=" + stateToString(mState) + " but AlarmManager is idling");
2868 }
2869 if (mState == STATE_IDLE && !mLocalAlarmManager.isIdling()) {
2870 Slog.wtf(TAG, "mState=IDLE but AlarmManager is not idling");
2871 }
2872 if (mLightState == LIGHT_STATE_ACTIVE && mNextLightAlarmTime != 0) {
2873 Slog.wtf(TAG, "mLightState=ACTIVE but mNextLightAlarmTime is "
2874 + TimeUtils.formatDuration(mNextLightAlarmTime - SystemClock.elapsedRealtime())
2875 + " from now");
2876 }
2877 }
2878
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002879 void becomeInactiveIfAppropriateLocked() {
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002880 verifyAlarmStateLocked();
2881
2882 final boolean isScreenBlockingInactive =
2883 mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked);
2884 if (DEBUG) {
2885 Slog.d(TAG, "becomeInactiveIfAppropriateLocked():"
2886 + " isScreenBlockingInactive=" + isScreenBlockingInactive
2887 + " (mScreenOn=" + mScreenOn
2888 + ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK
2889 + ", mScreenLocked=" + mScreenLocked + ")"
2890 + " mCharging=" + mCharging
2891 + " mForceIdle=" + mForceIdle
2892 );
2893 }
2894 if (!mForceIdle && (mCharging || isScreenBlockingInactive)) {
2895 return;
2896 }
2897 // Become inactive and determine if we will ultimately go idle.
2898 if (mDeepEnabled) {
2899 if (mQuickDozeActivated) {
2900 if (mState == STATE_QUICK_DOZE_DELAY || mState == STATE_IDLE
2901 || mState == STATE_IDLE_MAINTENANCE) {
2902 // Already "idling". Don't want to restart the process.
2903 // mLightState can't be LIGHT_STATE_ACTIVE if mState is any of these 3
2904 // values, so returning here is safe.
2905 return;
Kweku Adamsb396ccf2018-09-17 16:37:15 -07002906 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002907 if (DEBUG) {
2908 Slog.d(TAG, "Moved from "
2909 + stateToString(mState) + " to STATE_QUICK_DOZE_DELAY");
2910 }
2911 mState = STATE_QUICK_DOZE_DELAY;
2912 // Make sure any motion sensing or locating is stopped.
2913 resetIdleManagementLocked();
Kweku Adamsecf98fb2019-07-22 17:12:41 -07002914 if (isUpcomingAlarmClock()) {
2915 // If there's an upcoming AlarmClock alarm, we won't go into idle, so
2916 // setting a wakeup alarm before the upcoming alarm is futile. Set the quick
2917 // doze alarm to after the upcoming AlarmClock alarm.
2918 scheduleAlarmLocked(
2919 mAlarmManager.getNextWakeFromIdleTime() - mInjector.getElapsedRealtime()
2920 + mConstants.QUICK_DOZE_DELAY_TIMEOUT, false);
2921 } else {
2922 // Wait a small amount of time in case something (eg: background service from
2923 // recently closed app) needs to finish running.
2924 scheduleAlarmLocked(mConstants.QUICK_DOZE_DELAY_TIMEOUT, false);
2925 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002926 EventLogTags.writeDeviceIdle(mState, "no activity");
2927 } else if (mState == STATE_ACTIVE) {
2928 mState = STATE_INACTIVE;
2929 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
2930 resetIdleManagementLocked();
2931 long delay = mInactiveTimeout;
2932 if (shouldUseIdleTimeoutFactorLocked()) {
2933 delay = (long) (mPreIdleFactor * delay);
2934 }
Kweku Adamsecf98fb2019-07-22 17:12:41 -07002935 if (isUpcomingAlarmClock()) {
2936 // If there's an upcoming AlarmClock alarm, we won't go into idle, so
2937 // setting a wakeup alarm before the upcoming alarm is futile. Set the idle
2938 // alarm to after the upcoming AlarmClock alarm.
2939 scheduleAlarmLocked(
2940 mAlarmManager.getNextWakeFromIdleTime() - mInjector.getElapsedRealtime()
2941 + delay, false);
2942 } else {
2943 scheduleAlarmLocked(delay, false);
2944 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002945 EventLogTags.writeDeviceIdle(mState, "no activity");
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002946 }
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002947 }
2948 if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
2949 mLightState = LIGHT_STATE_INACTIVE;
2950 if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
2951 resetLightIdleManagementLocked();
2952 scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
2953 EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002954 }
2955 }
2956
Kweku Adams00e3a372018-09-28 16:57:09 -07002957 private void resetIdleManagementLocked() {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002958 mNextIdlePendingDelay = 0;
2959 mNextIdleDelay = 0;
Denny cy Leec5a7c292019-01-01 17:37:55 +08002960 mIdleStartTime = 0;
Kweku Adams810c77d2019-08-28 07:45:00 -07002961 mQuickDozeActivatedWhileIdling = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002962 cancelAlarmLocked();
Kevin Gabayan92f15e62016-04-04 17:52:22 -07002963 cancelSensingTimeoutAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002964 cancelLocatingLocked();
Kweku Adams810c77d2019-08-28 07:45:00 -07002965 maybeStopMonitoringMotionLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002966 mAnyMotionDetector.stop();
Robin Lee876b88542018-11-13 17:22:24 +01002967 updateActiveConstraintsLocked();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07002968 }
2969
Kweku Adams00e3a372018-09-28 16:57:09 -07002970 private void resetLightIdleManagementLocked() {
Kweku Adams7c96f5182019-06-04 16:32:49 -07002971 mNextLightIdleDelay = 0;
2972 mCurLightIdleBudget = 0;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002973 cancelLightAlarmLocked();
2974 }
2975
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002976 void exitForceIdleLocked() {
2977 if (mForceIdle) {
2978 mForceIdle = false;
2979 if (mScreenOn || mCharging) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08002980 mActiveReason = ACTIVE_REASON_FORCED;
Dianne Hackborn88c41352016-04-07 15:18:58 -07002981 becomeActiveLocked("exit-force", Process.myUid());
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002982 }
2983 }
2984 }
2985
Kweku Adamsa457f4e2018-10-03 15:56:06 -07002986 /**
2987 * Must only be used in tests.
2988 *
2989 * This sets the state value directly and thus doesn't trigger any behavioral changes.
2990 */
2991 @VisibleForTesting
2992 void setLightStateForTest(int lightState) {
Kweku Adams799858b2018-10-08 17:19:08 -07002993 synchronized (this) {
2994 mLightState = lightState;
2995 }
Kweku Adamsa457f4e2018-10-03 15:56:06 -07002996 }
2997
Kweku Adams00e3a372018-09-28 16:57:09 -07002998 @VisibleForTesting
2999 int getLightState() {
3000 return mLightState;
3001 }
3002
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003003 void stepLightIdleStateLocked(String reason) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003004 if (mLightState == LIGHT_STATE_OVERRIDE) {
Dianne Hackbornb6843652016-02-22 12:20:13 -08003005 // If we are already in deep device idle mode, then
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003006 // there is nothing left to do for light mode.
3007 return;
3008 }
3009
3010 if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState);
3011 EventLogTags.writeDeviceIdleLightStep();
3012
3013 switch (mLightState) {
3014 case LIGHT_STATE_INACTIVE:
Kweku Adams7c96f5182019-06-04 16:32:49 -07003015 mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
Dianne Hackborn953fc942016-03-29 15:36:24 -07003016 // Reset the upcoming idle delays.
3017 mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003018 mMaintenanceStartTime = 0;
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003019 if (!isOpsInactiveLocked()) {
3020 // We have some active ops going on... give them a chance to finish
3021 // before going in to our first idle.
3022 mLightState = LIGHT_STATE_PRE_IDLE;
3023 EventLogTags.writeDeviceIdleLight(mLightState, reason);
3024 scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT);
3025 break;
3026 }
3027 // Nothing active, fall through to immediately idle.
3028 case LIGHT_STATE_PRE_IDLE:
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003029 case LIGHT_STATE_IDLE_MAINTENANCE:
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003030 if (mMaintenanceStartTime != 0) {
3031 long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime;
3032 if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
3033 // We didn't use up all of our minimum budget; add this to the reserve.
Kweku Adams7c96f5182019-06-04 16:32:49 -07003034 mCurLightIdleBudget +=
3035 (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET - duration);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003036 } else {
3037 // We used more than our minimum budget; this comes out of the reserve.
Kweku Adams7c96f5182019-06-04 16:32:49 -07003038 mCurLightIdleBudget -=
3039 (duration - mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003040 }
3041 }
3042 mMaintenanceStartTime = 0;
Dianne Hackborn953fc942016-03-29 15:36:24 -07003043 scheduleLightAlarmLocked(mNextLightIdleDelay);
3044 mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
3045 (long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
3046 if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {
3047 mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
3048 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003049 if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
3050 mLightState = LIGHT_STATE_IDLE;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003051 EventLogTags.writeDeviceIdleLight(mLightState, reason);
Amith Yamasaniac6517a2018-04-23 12:19:34 -07003052 addEvent(EVENT_LIGHT_IDLE, null);
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08003053 mGoingIdleWakeLock.acquire();
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003054 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
3055 break;
3056 case LIGHT_STATE_IDLE:
Dianne Hackborn88c41352016-04-07 15:18:58 -07003057 case LIGHT_STATE_WAITING_FOR_NETWORK:
3058 if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
3059 // We have been idling long enough, now it is time to do some work.
3060 mActiveIdleOpCount = 1;
3061 mActiveIdleWakeLock.acquire();
3062 mMaintenanceStartTime = SystemClock.elapsedRealtime();
Kweku Adams7c96f5182019-06-04 16:32:49 -07003063 if (mCurLightIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
3064 mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
3065 } else if (mCurLightIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
3066 mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
Dianne Hackborn88c41352016-04-07 15:18:58 -07003067 }
Kweku Adams7c96f5182019-06-04 16:32:49 -07003068 scheduleLightAlarmLocked(mCurLightIdleBudget);
Dianne Hackborn88c41352016-04-07 15:18:58 -07003069 if (DEBUG) Slog.d(TAG,
3070 "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
3071 mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
3072 EventLogTags.writeDeviceIdleLight(mLightState, reason);
Amith Yamasaniac6517a2018-04-23 12:19:34 -07003073 addEvent(EVENT_LIGHT_MAINTENANCE, null);
Dianne Hackborn88c41352016-04-07 15:18:58 -07003074 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
3075 } else {
3076 // We'd like to do maintenance, but currently don't have network
3077 // connectivity... let's try to wait until the network comes back.
3078 // We'll only wait for another full idle period, however, and then give up.
3079 scheduleLightAlarmLocked(mNextLightIdleDelay);
3080 if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK.");
3081 mLightState = LIGHT_STATE_WAITING_FOR_NETWORK;
3082 EventLogTags.writeDeviceIdleLight(mLightState, reason);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08003083 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003084 break;
3085 }
3086 }
3087
Kweku Adams00e3a372018-09-28 16:57:09 -07003088 @VisibleForTesting
3089 int getState() {
3090 return mState;
3091 }
3092
Kweku Adamsecf98fb2019-07-22 17:12:41 -07003093 /**
3094 * Returns true if there's an upcoming AlarmClock alarm that is soon enough to prevent the
3095 * device from going into idle.
3096 */
3097 private boolean isUpcomingAlarmClock() {
3098 return mInjector.getElapsedRealtime() + mConstants.MIN_TIME_TO_ALARM
3099 >= mAlarmManager.getNextWakeFromIdleTime();
3100 }
3101
Kweku Adams00e3a372018-09-28 16:57:09 -07003102 @VisibleForTesting
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003103 void stepIdleStateLocked(String reason) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003104 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003105 EventLogTags.writeDeviceIdleStep();
3106
Kweku Adamsecf98fb2019-07-22 17:12:41 -07003107 if (isUpcomingAlarmClock()) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003108 // Whoops, there is an upcoming alarm. We don't actually want to go idle.
3109 if (mState != STATE_ACTIVE) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08003110 mActiveReason = ACTIVE_REASON_ALARM;
Dianne Hackbornb6683c42015-06-18 17:40:33 -07003111 becomeActiveLocked("alarm", Process.myUid());
Koji Fukui27b33302015-12-16 19:43:01 +09003112 becomeInactiveIfAppropriateLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003113 }
3114 return;
3115 }
3116
Robin Lee876b88542018-11-13 17:22:24 +01003117 if (mNumBlockingConstraints != 0 && !mForceIdle) {
3118 // We have some constraints from other parts of the system server preventing
3119 // us from moving to the next state.
3120 if (DEBUG) {
3121 Slog.i(TAG, "Cannot step idle state. Blocked by: " + mConstraints.values().stream()
3122 .filter(x -> x.active)
3123 .map(x -> x.name)
3124 .collect(Collectors.joining(",")));
3125 }
3126 return;
3127 }
3128
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003129 switch (mState) {
3130 case STATE_INACTIVE:
3131 // We have now been inactive long enough, it is time to start looking
Nick Vaccaro20feaea2015-09-17 17:22:44 -07003132 // for motion and sleep some more while doing so.
3133 startMonitoringMotionLocked();
Denny cy Leec5a7c292019-01-01 17:37:55 +08003134 long delay = mConstants.IDLE_AFTER_INACTIVE_TIMEOUT;
3135 if (shouldUseIdleTimeoutFactorLocked()) {
3136 delay = (long) (mPreIdleFactor * delay);
3137 }
3138 scheduleAlarmLocked(delay, false);
Robin Lee876b88542018-11-13 17:22:24 +01003139 moveToStateLocked(STATE_IDLE_PENDING, reason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003140 break;
3141 case STATE_IDLE_PENDING:
Robin Lee876b88542018-11-13 17:22:24 +01003142 moveToStateLocked(STATE_SENSING, reason);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003143 cancelLocatingLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003144 mLocated = false;
3145 mLastGenericLocation = null;
3146 mLastGpsLocation = null;
Robin Lee876b88542018-11-13 17:22:24 +01003147 updateActiveConstraintsLocked();
Robin Leec4d424c2018-12-07 15:09:13 +01003148
Robin Lee876b88542018-11-13 17:22:24 +01003149 // Wait for open constraints and an accelerometer reading before moving on.
Robin Leec4d424c2018-12-07 15:09:13 +01003150 if (mUseMotionSensor && mAnyMotionDetector.hasSensor()) {
3151 scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
3152 mNotMoving = false;
3153 mAnyMotionDetector.checkForAnyMotion();
3154 break;
Robin Lee876b88542018-11-13 17:22:24 +01003155 } else if (mNumBlockingConstraints != 0) {
3156 cancelAlarmLocked();
3157 break;
Robin Leec4d424c2018-12-07 15:09:13 +01003158 }
3159
3160 mNotMoving = true;
3161 // Otherwise, fall through and check this off the list of requirements.
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003162 case STATE_SENSING:
Kevin Gabayan92f15e62016-04-04 17:52:22 -07003163 cancelSensingTimeoutAlarmLocked();
Robin Lee876b88542018-11-13 17:22:24 +01003164 moveToStateLocked(STATE_LOCATING, reason);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003165 scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
Kweku Adams799858b2018-10-08 17:19:08 -07003166 LocationManager locationManager = mInjector.getLocationManager();
3167 if (locationManager != null
3168 && locationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
3169 locationManager.requestLocationUpdates(mLocationRequest,
Joe LaPenna23d681b2015-08-27 15:12:11 -07003170 mGenericLocationListener, mHandler.getLooper());
3171 mLocating = true;
3172 } else {
3173 mHasNetworkLocation = false;
3174 }
Kweku Adams799858b2018-10-08 17:19:08 -07003175 if (locationManager != null
3176 && locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
Joe LaPenna23d681b2015-08-27 15:12:11 -07003177 mHasGps = true;
Kweku Adams799858b2018-10-08 17:19:08 -07003178 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003179 mGpsLocationListener, mHandler.getLooper());
Joe LaPenna23d681b2015-08-27 15:12:11 -07003180 mLocating = true;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003181 } else {
Joe LaPenna23d681b2015-08-27 15:12:11 -07003182 mHasGps = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003183 }
Joe LaPenna23d681b2015-08-27 15:12:11 -07003184 // If we have a location provider, we're all set, the listeners will move state
3185 // forward.
3186 if (mLocating) {
3187 break;
3188 }
3189
3190 // Otherwise, we have to move from locating into idle maintenance.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003191 case STATE_LOCATING:
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003192 cancelAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003193 cancelLocatingLocked();
3194 mAnyMotionDetector.stop();
Dianne Hackborn953fc942016-03-29 15:36:24 -07003195
Kweku Adamsb396ccf2018-09-17 16:37:15 -07003196 // Intentional fallthrough -- time to go into IDLE state.
3197 case STATE_QUICK_DOZE_DELAY:
3198 // Reset the upcoming idle delays.
3199 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
3200 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
3201
3202 // Everything is in place to go into IDLE state.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003203 case STATE_IDLE_MAINTENANCE:
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003204 scheduleAlarmLocked(mNextIdleDelay, true);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003205 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
3206 " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07003207 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003208 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
Denny cy Leec5a7c292019-01-01 17:37:55 +08003209 mIdleStartTime = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -07003210 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
Dianne Hackborn953fc942016-03-29 15:36:24 -07003211 if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
3212 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
3213 }
Robin Lee876b88542018-11-13 17:22:24 +01003214 moveToStateLocked(STATE_IDLE, reason);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003215 if (mLightState != LIGHT_STATE_OVERRIDE) {
3216 mLightState = LIGHT_STATE_OVERRIDE;
3217 cancelLightAlarmLocked();
3218 }
Amith Yamasaniac6517a2018-04-23 12:19:34 -07003219 addEvent(EVENT_DEEP_IDLE, null);
Joe Onorato8f0e9ced2016-12-08 17:48:49 -08003220 mGoingIdleWakeLock.acquire();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003221 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
3222 break;
3223 case STATE_IDLE:
3224 // We have been idling long enough, now it is time to do some work.
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003225 mActiveIdleOpCount = 1;
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003226 mActiveIdleWakeLock.acquire();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003227 scheduleAlarmLocked(mNextIdlePendingDelay, false);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003228 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
3229 "Next alarm in " + mNextIdlePendingDelay + " ms.");
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003230 mMaintenanceStartTime = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -07003231 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
3232 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
Dianne Hackborn953fc942016-03-29 15:36:24 -07003233 if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
3234 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
3235 }
Robin Lee876b88542018-11-13 17:22:24 +01003236 moveToStateLocked(STATE_IDLE_MAINTENANCE, reason);
Amith Yamasaniac6517a2018-04-23 12:19:34 -07003237 addEvent(EVENT_DEEP_MAINTENANCE, null);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003238 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
3239 break;
3240 }
3241 }
3242
Robin Lee876b88542018-11-13 17:22:24 +01003243 private void moveToStateLocked(int state, String reason) {
3244 final int oldState = mState;
3245 mState = state;
3246 if (DEBUG) {
3247 Slog.d(TAG, String.format("Moved from STATE_%s to STATE_%s.",
3248 stateToString(oldState), stateToString(mState)));
3249 }
3250 EventLogTags.writeDeviceIdle(mState, reason);
3251 updateActiveConstraintsLocked();
3252 }
3253
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003254 void incActiveIdleOps() {
3255 synchronized (this) {
3256 mActiveIdleOpCount++;
3257 }
3258 }
3259
3260 void decActiveIdleOps() {
3261 synchronized (this) {
3262 mActiveIdleOpCount--;
3263 if (mActiveIdleOpCount <= 0) {
3264 exitMaintenanceEarlyIfNeededLocked();
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003265 mActiveIdleWakeLock.release();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003266 }
3267 }
3268 }
3269
Kweku Adamsa457f4e2018-10-03 15:56:06 -07003270 /** Must only be used in tests. */
3271 @VisibleForTesting
3272 void setActiveIdleOpsForTest(int count) {
Kweku Adams799858b2018-10-08 17:19:08 -07003273 synchronized (this) {
3274 mActiveIdleOpCount = count;
3275 }
Kweku Adamsa457f4e2018-10-03 15:56:06 -07003276 }
3277
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003278 void setJobsActive(boolean active) {
3279 synchronized (this) {
3280 mJobsActive = active;
3281 if (!active) {
3282 exitMaintenanceEarlyIfNeededLocked();
3283 }
3284 }
3285 }
3286
3287 void setAlarmsActive(boolean active) {
3288 synchronized (this) {
3289 mAlarmsActive = active;
3290 if (!active) {
3291 exitMaintenanceEarlyIfNeededLocked();
3292 }
3293 }
3294 }
3295
Denny cy Leec5a7c292019-01-01 17:37:55 +08003296 @VisibleForTesting
3297 int setPreIdleTimeoutMode(int mode) {
3298 return setPreIdleTimeoutFactor(getPreIdleTimeoutByMode(mode));
3299 }
3300
3301 @VisibleForTesting
3302 float getPreIdleTimeoutByMode(int mode) {
3303 switch (mode) {
3304 case PowerManager.PRE_IDLE_TIMEOUT_MODE_LONG: {
3305 return mConstants.PRE_IDLE_FACTOR_LONG;
3306 }
3307 case PowerManager.PRE_IDLE_TIMEOUT_MODE_SHORT: {
3308 return mConstants.PRE_IDLE_FACTOR_SHORT;
3309 }
3310 case PowerManager.PRE_IDLE_TIMEOUT_MODE_NORMAL: {
3311 return 1.0f;
3312 }
3313 default: {
3314 Slog.w(TAG, "Invalid time out factor mode: " + mode);
3315 return 1.0f;
3316 }
3317 }
3318 }
3319
3320 @VisibleForTesting
3321 float getPreIdleTimeoutFactor() {
3322 return mPreIdleFactor;
3323 }
3324
3325 @VisibleForTesting
3326 int setPreIdleTimeoutFactor(float ratio) {
3327 if (!mDeepEnabled) {
3328 if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Deep Idle disable");
3329 return SET_IDLE_FACTOR_RESULT_NOT_SUPPORT;
3330 } else if (ratio <= MIN_PRE_IDLE_FACTOR_CHANGE) {
3331 if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Invalid input");
3332 return SET_IDLE_FACTOR_RESULT_INVALID;
3333 } else if (Math.abs(ratio - mPreIdleFactor) < MIN_PRE_IDLE_FACTOR_CHANGE) {
3334 if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: New factor same as previous factor");
3335 return SET_IDLE_FACTOR_RESULT_IGNORED;
3336 }
3337 synchronized (this) {
3338 mLastPreIdleFactor = mPreIdleFactor;
3339 mPreIdleFactor = ratio;
3340 }
3341 if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: " + ratio);
3342 postUpdatePreIdleFactor();
3343 return SET_IDLE_FACTOR_RESULT_OK;
3344 }
3345
3346 @VisibleForTesting
3347 void resetPreIdleTimeoutMode() {
3348 synchronized (this) {
3349 mLastPreIdleFactor = mPreIdleFactor;
3350 mPreIdleFactor = 1.0f;
3351 }
3352 if (DEBUG) Slog.d(TAG, "resetPreIdleTimeoutMode to 1.0");
3353 postResetPreIdleTimeoutFactor();
3354 }
3355
3356 private void postUpdatePreIdleFactor() {
3357 mHandler.sendEmptyMessage(MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR);
3358 }
3359
3360 private void postResetPreIdleTimeoutFactor() {
3361 mHandler.sendEmptyMessage(MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR);
3362 }
3363
Denny cy Lee990ca332019-10-22 16:21:20 +08003364 private void updatePreIdleFactor() {
Denny cy Leec5a7c292019-01-01 17:37:55 +08003365 synchronized (this) {
3366 if (!shouldUseIdleTimeoutFactorLocked()) {
3367 return;
3368 }
3369 if (mState == STATE_INACTIVE || mState == STATE_IDLE_PENDING) {
3370 if (mNextAlarmTime == 0) {
3371 return;
3372 }
3373 long delay = mNextAlarmTime - SystemClock.elapsedRealtime();
3374 if (delay < MIN_STATE_STEP_ALARM_CHANGE) {
3375 return;
3376 }
3377 long newDelay = (long) (delay / mLastPreIdleFactor * mPreIdleFactor);
3378 if (Math.abs(delay - newDelay) < MIN_STATE_STEP_ALARM_CHANGE) {
3379 return;
3380 }
3381 scheduleAlarmLocked(newDelay, false);
3382 }
3383 }
3384 }
3385
Denny cy Lee990ca332019-10-22 16:21:20 +08003386 private void maybeDoImmediateMaintenance() {
Denny cy Leec5a7c292019-01-01 17:37:55 +08003387 synchronized (this) {
3388 if (mState == STATE_IDLE) {
3389 long duration = SystemClock.elapsedRealtime() - mIdleStartTime;
3390 /* Let's trgger a immediate maintenance,
3391 * if it has been idle for a long time */
3392 if (duration > mConstants.IDLE_TIMEOUT) {
3393 scheduleAlarmLocked(0, false);
3394 }
3395 }
3396 }
3397 }
3398
3399 private boolean shouldUseIdleTimeoutFactorLocked() {
3400 // exclude ACTIVE_REASON_MOTION, for exclude device in pocket case
3401 if (mActiveReason == ACTIVE_REASON_MOTION) {
3402 return false;
3403 }
3404 return true;
3405 }
3406
3407 /** Must only be used in tests. */
3408 @VisibleForTesting
3409 void setIdleStartTimeForTest(long idleStartTime) {
3410 synchronized (this) {
3411 mIdleStartTime = idleStartTime;
Denny cy Lee990ca332019-10-22 16:21:20 +08003412 maybeDoImmediateMaintenance();
Denny cy Leec5a7c292019-01-01 17:37:55 +08003413 }
3414 }
3415
Denny cy Leec5a7c292019-01-01 17:37:55 +08003416 @VisibleForTesting
3417 long getNextAlarmTime() {
3418 return mNextAlarmTime;
3419 }
3420
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003421 boolean isOpsInactiveLocked() {
Dianne Hackborn7ab40252016-06-15 17:30:24 -07003422 return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003423 }
3424
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003425 void exitMaintenanceEarlyIfNeededLocked() {
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003426 if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE
3427 || mLightState == LIGHT_STATE_PRE_IDLE) {
3428 if (isOpsInactiveLocked()) {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003429 final long now = SystemClock.elapsedRealtime();
3430 if (DEBUG) {
3431 StringBuilder sb = new StringBuilder();
3432 sb.append("Exit: start=");
3433 TimeUtils.formatDuration(mMaintenanceStartTime, sb);
3434 sb.append(" now=");
3435 TimeUtils.formatDuration(now, sb);
3436 Slog.d(TAG, sb.toString());
3437 }
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003438 if (mState == STATE_IDLE_MAINTENANCE) {
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003439 stepIdleStateLocked("s:early");
3440 } else if (mLightState == LIGHT_STATE_PRE_IDLE) {
3441 stepLightIdleStateLocked("s:predone");
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003442 } else {
Dianne Hackborn945c9c92016-03-30 14:55:00 -07003443 stepLightIdleStateLocked("s:early");
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003444 }
3445 }
3446 }
3447 }
3448
Nick Vaccaro20feaea2015-09-17 17:22:44 -07003449 void motionLocked() {
3450 if (DEBUG) Slog.d(TAG, "motionLocked()");
Kweku Adams810c77d2019-08-28 07:45:00 -07003451 mLastMotionEventElapsed = mInjector.getElapsedRealtime();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003452 handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
3453 }
3454
3455 void handleMotionDetectedLocked(long timeout, String type) {
Kweku Adams810c77d2019-08-28 07:45:00 -07003456 if (mStationaryListeners.size() > 0) {
3457 postStationaryStatusUpdated();
3458 scheduleMotionTimeoutAlarmLocked();
Kweku Adamsa890d282019-12-19 16:08:43 -08003459 // We need to re-register the motion listener, but we don't want the sensors to be
3460 // constantly active or to churn the CPU by registering too early, register after some
3461 // delay.
3462 scheduleMotionRegistrationAlarmLocked();
Kweku Adams810c77d2019-08-28 07:45:00 -07003463 }
3464 if (mQuickDozeActivated && !mQuickDozeActivatedWhileIdling) {
3465 // Don't exit idle due to motion if quick doze is enabled.
3466 // However, if the device started idling due to the normal progression (going through
3467 // all the states) and then had quick doze activated, come out briefly on motion so the
3468 // user can get slightly fresher content.
3469 return;
3470 }
3471 maybeStopMonitoringMotionLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003472 // The device is not yet active, so we want to go back to the pending idle
Nick Vaccaro20feaea2015-09-17 17:22:44 -07003473 // state to wait again for no motion. Note that we only monitor for motion
3474 // after moving out of the inactive state, so no need to worry about that.
Kweku Adamsb7ce1902019-01-30 10:55:34 -08003475 final boolean becomeInactive = mState != STATE_ACTIVE
3476 || mLightState == LIGHT_STATE_OVERRIDE;
3477 // We only want to change the IDLE state if it's OVERRIDE.
3478 becomeActiveLocked(type, Process.myUid(), timeout, mLightState == LIGHT_STATE_OVERRIDE);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003479 if (becomeInactive) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003480 becomeInactiveIfAppropriateLocked();
3481 }
3482 }
3483
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003484 void receivedGenericLocationLocked(Location location) {
3485 if (mState != STATE_LOCATING) {
3486 cancelLocatingLocked();
3487 return;
3488 }
3489 if (DEBUG) Slog.d(TAG, "Generic location: " + location);
3490 mLastGenericLocation = new Location(location);
Joe LaPenna23d681b2015-08-27 15:12:11 -07003491 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003492 return;
3493 }
3494 mLocated = true;
3495 if (mNotMoving) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003496 stepIdleStateLocked("s:location");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003497 }
3498 }
3499
3500 void receivedGpsLocationLocked(Location location) {
3501 if (mState != STATE_LOCATING) {
3502 cancelLocatingLocked();
3503 return;
3504 }
3505 if (DEBUG) Slog.d(TAG, "GPS location: " + location);
3506 mLastGpsLocation = new Location(location);
3507 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
3508 return;
3509 }
3510 mLocated = true;
3511 if (mNotMoving) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003512 stepIdleStateLocked("s:gps");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003513 }
3514 }
3515
Nick Vaccaro20feaea2015-09-17 17:22:44 -07003516 void startMonitoringMotionLocked() {
3517 if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()");
3518 if (mMotionSensor != null && !mMotionListener.active) {
3519 mMotionListener.registerLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003520 }
3521 }
3522
Kweku Adams810c77d2019-08-28 07:45:00 -07003523 /**
3524 * Stops motion monitoring. Will not stop monitoring if there are registered stationary
3525 * listeners.
3526 */
3527 private void maybeStopMonitoringMotionLocked() {
3528 if (DEBUG) Slog.d(TAG, "maybeStopMonitoringMotionLocked()");
Kweku Adamsa890d282019-12-19 16:08:43 -08003529 if (mMotionSensor != null && mStationaryListeners.size() == 0) {
3530 if (mMotionListener.active) {
3531 mMotionListener.unregisterLocked();
3532 cancelMotionTimeoutAlarmLocked();
3533 }
3534 cancelMotionRegistrationAlarmLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003535 }
3536 }
3537
3538 void cancelAlarmLocked() {
3539 if (mNextAlarmTime != 0) {
3540 mNextAlarmTime = 0;
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003541 mAlarmManager.cancel(mDeepAlarmListener);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003542 }
3543 }
3544
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003545 void cancelLightAlarmLocked() {
3546 if (mNextLightAlarmTime != 0) {
3547 mNextLightAlarmTime = 0;
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003548 mAlarmManager.cancel(mLightAlarmListener);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003549 }
3550 }
3551
3552 void cancelLocatingLocked() {
3553 if (mLocating) {
Kweku Adams799858b2018-10-08 17:19:08 -07003554 LocationManager locationManager = mInjector.getLocationManager();
3555 locationManager.removeUpdates(mGenericLocationListener);
3556 locationManager.removeUpdates(mGpsLocationListener);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003557 mLocating = false;
3558 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003559 }
3560
Kweku Adams810c77d2019-08-28 07:45:00 -07003561 private void cancelMotionTimeoutAlarmLocked() {
3562 mAlarmManager.cancel(mMotionTimeoutAlarmListener);
3563 }
3564
Kweku Adamsa890d282019-12-19 16:08:43 -08003565 private void cancelMotionRegistrationAlarmLocked() {
3566 mAlarmManager.cancel(mMotionRegistrationAlarmListener);
3567 }
3568
Kevin Gabayan92f15e62016-04-04 17:52:22 -07003569 void cancelSensingTimeoutAlarmLocked() {
3570 if (mNextSensingTimeoutAlarmTime != 0) {
3571 mNextSensingTimeoutAlarmTime = 0;
3572 mAlarmManager.cancel(mSensingTimeoutAlarmListener);
3573 }
3574 }
3575
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003576 void scheduleAlarmLocked(long delay, boolean idleUntil) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003577 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
Robin Leec4d424c2018-12-07 15:09:13 +01003578
3579 if (mUseMotionSensor && mMotionSensor == null
3580 && mState != STATE_QUICK_DOZE_DELAY
3581 && mState != STATE_IDLE
3582 && mState != STATE_IDLE_MAINTENANCE) {
3583 // 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 -07003584 // alarms, because we can't determine if the device is not moving. This effectively
Joe LaPenna23d681b2015-08-27 15:12:11 -07003585 // turns off normal execution of device idling, although it is still possible to
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003586 // manually poke it by pretending like the alarm is going off.
Kweku Adamsb396ccf2018-09-17 16:37:15 -07003587 // STATE_QUICK_DOZE_DELAY skips the motion sensing so if the state is past the motion
3588 // sensing stage (ie, is QUICK_DOZE_DELAY, IDLE, or IDLE_MAINTENANCE), then idling
3589 // can continue until the user interacts with the device.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003590 return;
3591 }
3592 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
3593 if (idleUntil) {
3594 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003595 mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003596 } else {
3597 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003598 mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003599 }
3600 }
3601
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003602 void scheduleLightAlarmLocked(long delay) {
3603 if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
Dianne Hackborn08c47a52015-10-15 12:38:14 -07003604 mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07003605 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003606 mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07003607 }
3608
Kweku Adamsa890d282019-12-19 16:08:43 -08003609 private void scheduleMotionRegistrationAlarmLocked() {
3610 if (DEBUG) Slog.d(TAG, "scheduleMotionRegistrationAlarmLocked");
3611 long nextMotionRegistrationAlarmTime =
3612 mInjector.getElapsedRealtime() + mConstants.MOTION_INACTIVE_TIMEOUT / 2;
3613 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionRegistrationAlarmTime,
3614 "DeviceIdleController.motion_registration", mMotionRegistrationAlarmListener,
3615 mHandler);
3616 }
3617
Kweku Adams810c77d2019-08-28 07:45:00 -07003618 private void scheduleMotionTimeoutAlarmLocked() {
3619 if (DEBUG) Slog.d(TAG, "scheduleMotionAlarmLocked");
3620 long nextMotionTimeoutAlarmTime =
3621 mInjector.getElapsedRealtime() + mConstants.MOTION_INACTIVE_TIMEOUT;
3622 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionTimeoutAlarmTime,
3623 "DeviceIdleController.motion", mMotionTimeoutAlarmListener, mHandler);
3624 }
3625
Kevin Gabayan92f15e62016-04-04 17:52:22 -07003626 void scheduleSensingTimeoutAlarmLocked(long delay) {
3627 if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
3628 mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
3629 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
3630 "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
3631 }
3632
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003633 private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
3634 ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
3635 outAppIds.clear();
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08003636 if (systemApps != null) {
3637 for (int i = 0; i < systemApps.size(); i++) {
3638 outAppIds.put(systemApps.valueAt(i), true);
3639 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003640 }
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08003641 if (userApps != null) {
3642 for (int i = 0; i < userApps.size(); i++) {
3643 outAppIds.put(userApps.valueAt(i), true);
3644 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003645 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003646 int size = outAppIds.size();
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003647 int[] appids = new int[size];
3648 for (int i = 0; i < size; i++) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003649 appids[i] = outAppIds.keyAt(i);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003650 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003651 return appids;
3652 }
3653
3654 private void updateWhitelistAppIdsLocked() {
3655 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
3656 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
3657 mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
3658 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08003659 mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
3660 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
Dianne Hackborn85e35642017-01-12 15:10:57 -08003661 if (mLocalActivityManager != null) {
Makoto Onukiaf8ff4f2018-06-04 14:44:19 -07003662 mLocalActivityManager.setDeviceIdleWhitelist(
3663 mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
Dianne Hackborn85e35642017-01-12 15:10:57 -08003664 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003665 if (mLocalPowerManager != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003666 if (DEBUG) {
3667 Slog.d(TAG, "Setting wakelock whitelist to "
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07003668 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003669 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07003670 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003671 }
Suprabh Shukla5bf49812018-05-24 18:38:50 -07003672 passWhiteListsToForceAppStandbyTrackerLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003673 }
3674
Dianne Hackborn85e35642017-01-12 15:10:57 -08003675 private void updateTempWhitelistAppIdsLocked(int appId, boolean adding) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003676 final int size = mTempWhitelistAppIdEndTimes.size();
3677 if (mTempWhitelistAppIdArray.length != size) {
3678 mTempWhitelistAppIdArray = new int[size];
3679 }
3680 for (int i = 0; i < size; i++) {
3681 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
3682 }
Dianne Hackborn85e35642017-01-12 15:10:57 -08003683 if (mLocalActivityManager != null) {
3684 if (DEBUG) {
3685 Slog.d(TAG, "Setting activity manager temp whitelist to "
3686 + Arrays.toString(mTempWhitelistAppIdArray));
3687 }
3688 mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, appId,
3689 adding);
3690 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003691 if (mLocalPowerManager != null) {
3692 if (DEBUG) {
3693 Slog.d(TAG, "Setting wakelock temp whitelist to "
3694 + Arrays.toString(mTempWhitelistAppIdArray));
3695 }
3696 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
3697 }
Suprabh Shukla5bf49812018-05-24 18:38:50 -07003698 passWhiteListsToForceAppStandbyTrackerLocked();
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003699 }
3700
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003701 private void reportPowerSaveWhitelistChangedLocked() {
3702 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
3703 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003704 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07003705 }
3706
3707 private void reportTempWhitelistChangedLocked() {
3708 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
3709 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003710 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003711 }
3712
Suprabh Shukla5bf49812018-05-24 18:38:50 -07003713 private void passWhiteListsToForceAppStandbyTrackerLocked() {
Makoto Onukie4918212018-02-06 11:30:15 -08003714 mAppStateTracker.setPowerSaveWhitelistAppIds(
Makoto Onuki71755c92018-01-16 14:15:44 -08003715 mPowerSaveWhitelistExceptIdleAppIdArray,
Suprabh Shukla5bf49812018-05-24 18:38:50 -07003716 mPowerSaveWhitelistUserAppIdArray,
Makoto Onuki2206af32017-11-21 16:25:35 -08003717 mTempWhitelistAppIdArray);
3718 }
3719
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003720 void readConfigFileLocked() {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07003721 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003722 mPowerSaveWhitelistUserApps.clear();
3723 FileInputStream stream;
3724 try {
3725 stream = mConfigFile.openRead();
3726 } catch (FileNotFoundException e) {
3727 return;
3728 }
3729 try {
3730 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01003731 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003732 readConfigFileLocked(parser);
3733 } catch (XmlPullParserException e) {
3734 } finally {
3735 try {
3736 stream.close();
3737 } catch (IOException e) {
3738 }
3739 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003740 }
3741
3742 private void readConfigFileLocked(XmlPullParser parser) {
3743 final PackageManager pm = getContext().getPackageManager();
3744
3745 try {
3746 int type;
3747 while ((type = parser.next()) != XmlPullParser.START_TAG
3748 && type != XmlPullParser.END_DOCUMENT) {
3749 ;
3750 }
3751
3752 if (type != XmlPullParser.START_TAG) {
3753 throw new IllegalStateException("no start tag found");
3754 }
3755
3756 int outerDepth = parser.getDepth();
3757 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3758 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3759 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3760 continue;
3761 }
3762
3763 String tagName = parser.getName();
Suprabh Shukla08105642017-09-26 14:45:30 -07003764 switch (tagName) {
3765 case "wl":
3766 String name = parser.getAttributeValue(null, "n");
3767 if (name != null) {
3768 try {
3769 ApplicationInfo ai = pm.getApplicationInfo(name,
3770 PackageManager.MATCH_ANY_USER);
3771 mPowerSaveWhitelistUserApps.put(ai.packageName,
3772 UserHandle.getAppId(ai.uid));
3773 } catch (PackageManager.NameNotFoundException e) {
3774 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003775 }
Suprabh Shukla08105642017-09-26 14:45:30 -07003776 break;
3777 case "un-wl":
3778 final String packageName = parser.getAttributeValue(null, "n");
3779 if (mPowerSaveWhitelistApps.containsKey(packageName)) {
3780 mRemovedFromSystemWhitelistApps.put(packageName,
3781 mPowerSaveWhitelistApps.remove(packageName));
3782 }
3783 break;
3784 default:
3785 Slog.w(TAG, "Unknown element under <config>: "
3786 + parser.getName());
3787 XmlUtils.skipCurrentTag(parser);
3788 break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003789 }
3790 }
3791
3792 } catch (IllegalStateException e) {
3793 Slog.w(TAG, "Failed parsing config " + e);
3794 } catch (NullPointerException e) {
3795 Slog.w(TAG, "Failed parsing config " + e);
3796 } catch (NumberFormatException e) {
3797 Slog.w(TAG, "Failed parsing config " + e);
3798 } catch (XmlPullParserException e) {
3799 Slog.w(TAG, "Failed parsing config " + e);
3800 } catch (IOException e) {
3801 Slog.w(TAG, "Failed parsing config " + e);
3802 } catch (IndexOutOfBoundsException e) {
3803 Slog.w(TAG, "Failed parsing config " + e);
3804 }
3805 }
3806
3807 void writeConfigFileLocked() {
3808 mHandler.removeMessages(MSG_WRITE_CONFIG);
3809 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
3810 }
3811
3812 void handleWriteConfigFile() {
3813 final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
3814
3815 try {
3816 synchronized (this) {
3817 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01003818 out.setOutput(memStream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003819 writeConfigFileLocked(out);
3820 }
3821 } catch (IOException e) {
3822 }
3823
3824 synchronized (mConfigFile) {
3825 FileOutputStream stream = null;
3826 try {
3827 stream = mConfigFile.startWrite();
3828 memStream.writeTo(stream);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003829 mConfigFile.finishWrite(stream);
3830 } catch (IOException e) {
3831 Slog.w(TAG, "Error writing config file", e);
3832 mConfigFile.failWrite(stream);
3833 }
3834 }
3835 }
3836
3837 void writeConfigFileLocked(XmlSerializer out) throws IOException {
3838 out.startDocument(null, true);
3839 out.startTag(null, "config");
3840 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
3841 String name = mPowerSaveWhitelistUserApps.keyAt(i);
3842 out.startTag(null, "wl");
3843 out.attribute(null, "n", name);
3844 out.endTag(null, "wl");
3845 }
Suprabh Shukla08105642017-09-26 14:45:30 -07003846 for (int i = 0; i < mRemovedFromSystemWhitelistApps.size(); i++) {
3847 out.startTag(null, "un-wl");
3848 out.attribute(null, "n", mRemovedFromSystemWhitelistApps.keyAt(i));
3849 out.endTag(null, "un-wl");
3850 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003851 out.endTag(null, "config");
3852 out.endDocument();
3853 }
3854
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003855 static void dumpHelp(PrintWriter pw) {
3856 pw.println("Device idle controller (deviceidle) commands:");
3857 pw.println(" help");
3858 pw.println(" Print this help text.");
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003859 pw.println(" step [light|deep]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003860 pw.println(" Immediately step to next state, without waiting for alarm.");
Dianne Hackborn88c41352016-04-07 15:18:58 -07003861 pw.println(" force-idle [light|deep]");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07003862 pw.println(" Force directly into idle mode, regardless of other device state.");
Dianne Hackborn88c41352016-04-07 15:18:58 -07003863 pw.println(" force-inactive");
3864 pw.println(" Force to be inactive, ready to freely step idle states.");
3865 pw.println(" unforce");
3866 pw.println(" Resume normal functioning after force-idle or force-inactive.");
3867 pw.println(" get [light|deep|force|screen|charging|network]");
3868 pw.println(" Retrieve the current given state.");
Dianne Hackbornb6843652016-02-22 12:20:13 -08003869 pw.println(" disable [light|deep|all]");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003870 pw.println(" Completely disable device idle mode.");
Dianne Hackbornb6843652016-02-22 12:20:13 -08003871 pw.println(" enable [light|deep|all]");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07003872 pw.println(" Re-enable device idle mode after it had previously been disabled.");
Dianne Hackbornb6843652016-02-22 12:20:13 -08003873 pw.println(" enabled [light|deep|all]");
Dianne Hackborn92617032015-06-19 15:32:19 -07003874 pw.println(" Print 1 if device idle mode is currently enabled, else 0.");
Dianne Hackborn1b139682015-07-06 15:13:37 -07003875 pw.println(" whitelist");
3876 pw.println(" Print currently whitelisted apps.");
Dianne Hackborn92617032015-06-19 15:32:19 -07003877 pw.println(" whitelist [package ...]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003878 pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
Suprabh Shukla08105642017-09-26 14:45:30 -07003879 pw.println(" sys-whitelist [package ...|reset]");
3880 pw.println(" Prefix the package with '-' to remove it from the system whitelist or '+'"
3881 + " to put it back in the system whitelist.");
3882 pw.println(" Note that only packages that were"
3883 + " earlier removed from the system whitelist can be added back.");
3884 pw.println(" reset will reset the whitelist to the original state");
3885 pw.println(" Prints the system whitelist if no arguments are specified");
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07003886 pw.println(" except-idle-whitelist [package ...|reset]");
3887 pw.println(" Prefix the package with '+' to add it to whitelist or "
3888 + "'=' to check if it is already whitelisted");
3889 pw.println(" [reset] will reset the whitelist to it's original state");
3890 pw.println(" Note that unlike <whitelist> cmd, "
3891 + "changes made using this won't be persisted across boots");
Felipe Lemea1b79bf2016-05-24 13:06:54 -07003892 pw.println(" tempwhitelist");
3893 pw.println(" Print packages that are temporarily whitelisted.");
Sudheer Shanka326b3112017-11-27 14:40:57 -08003894 pw.println(" tempwhitelist [-u USER] [-d DURATION] [-r] [package]");
3895 pw.println(" Temporarily place package in whitelist for DURATION milliseconds.");
Dianne Hackborn85e35642017-01-12 15:10:57 -08003896 pw.println(" If no DURATION is specified, 10 seconds is used");
Sudheer Shanka326b3112017-11-27 14:40:57 -08003897 pw.println(" If [-r] option is used, then the package is removed from temp whitelist "
3898 + "and any [-d] is ignored");
Amith Yamasani4cb42572018-04-27 10:02:57 -07003899 pw.println(" motion");
3900 pw.println(" Simulate a motion event to bring the device out of deep doze");
Denny cy Leec5a7c292019-01-01 17:37:55 +08003901 pw.println(" pre-idle-factor [0|1|2]");
3902 pw.println(" Set a new factor to idle time before step to idle"
3903 + "(inactive_to and idle_after_inactive_to)");
3904 pw.println(" reset-pre-idle-factor");
3905 pw.println(" Reset factor to idle time to default");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07003906 }
3907
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003908 class Shell extends ShellCommand {
3909 int userId = UserHandle.USER_SYSTEM;
3910
3911 @Override
3912 public int onCommand(String cmd) {
3913 return onShellCommand(this, cmd);
3914 }
3915
3916 @Override
3917 public void onHelp() {
3918 PrintWriter pw = getOutPrintWriter();
3919 dumpHelp(pw);
3920 }
3921 }
3922
3923 int onShellCommand(Shell shell, String cmd) {
3924 PrintWriter pw = shell.getOutPrintWriter();
3925 if ("step".equals(cmd)) {
3926 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3927 null);
3928 synchronized (this) {
3929 long token = Binder.clearCallingIdentity();
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003930 String arg = shell.getNextArg();
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003931 try {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003932 if (arg == null || "deep".equals(arg)) {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003933 stepIdleStateLocked("s:shell");
3934 pw.print("Stepped to deep: ");
3935 pw.println(stateToString(mState));
3936 } else if ("light".equals(arg)) {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07003937 stepLightIdleStateLocked("s:shell");
3938 pw.print("Stepped to light: "); pw.println(lightStateToString(mLightState));
3939 } else {
3940 pw.println("Unknown idle mode: " + arg);
3941 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003942 } finally {
3943 Binder.restoreCallingIdentity(token);
3944 }
3945 }
3946 } else if ("force-idle".equals(cmd)) {
3947 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3948 null);
3949 synchronized (this) {
3950 long token = Binder.clearCallingIdentity();
Dianne Hackborn88c41352016-04-07 15:18:58 -07003951 String arg = shell.getNextArg();
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003952 try {
Dianne Hackborn88c41352016-04-07 15:18:58 -07003953 if (arg == null || "deep".equals(arg)) {
3954 if (!mDeepEnabled) {
3955 pw.println("Unable to go deep idle; not enabled");
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003956 return -1;
3957 }
Dianne Hackborn88c41352016-04-07 15:18:58 -07003958 mForceIdle = true;
3959 becomeInactiveIfAppropriateLocked();
3960 int curState = mState;
3961 while (curState != STATE_IDLE) {
3962 stepIdleStateLocked("s:shell");
3963 if (curState == mState) {
3964 pw.print("Unable to go deep idle; stopped at ");
3965 pw.println(stateToString(mState));
3966 exitForceIdleLocked();
3967 return -1;
3968 }
3969 curState = mState;
3970 }
3971 pw.println("Now forced in to deep idle mode");
3972 } else if ("light".equals(arg)) {
3973 mForceIdle = true;
3974 becomeInactiveIfAppropriateLocked();
3975 int curLightState = mLightState;
3976 while (curLightState != LIGHT_STATE_IDLE) {
Tej Singh93cf3e32017-12-07 13:05:38 -08003977 stepLightIdleStateLocked("s:shell");
Dianne Hackborn88c41352016-04-07 15:18:58 -07003978 if (curLightState == mLightState) {
3979 pw.print("Unable to go light idle; stopped at ");
3980 pw.println(lightStateToString(mLightState));
3981 exitForceIdleLocked();
3982 return -1;
3983 }
3984 curLightState = mLightState;
3985 }
3986 pw.println("Now forced in to light idle mode");
3987 } else {
3988 pw.println("Unknown idle mode: " + arg);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003989 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07003990 } finally {
3991 Binder.restoreCallingIdentity(token);
3992 }
3993 }
Dianne Hackborn88c41352016-04-07 15:18:58 -07003994 } else if ("force-inactive".equals(cmd)) {
3995 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3996 null);
3997 synchronized (this) {
3998 long token = Binder.clearCallingIdentity();
3999 try {
4000 mForceIdle = true;
4001 becomeInactiveIfAppropriateLocked();
4002 pw.print("Light state: ");
4003 pw.print(lightStateToString(mLightState));
4004 pw.print(", deep state: ");
4005 pw.println(stateToString(mState));
4006 } finally {
4007 Binder.restoreCallingIdentity(token);
4008 }
4009 }
4010 } else if ("unforce".equals(cmd)) {
4011 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4012 null);
4013 synchronized (this) {
4014 long token = Binder.clearCallingIdentity();
4015 try {
4016 exitForceIdleLocked();
4017 pw.print("Light state: ");
4018 pw.print(lightStateToString(mLightState));
4019 pw.print(", deep state: ");
4020 pw.println(stateToString(mState));
4021 } finally {
4022 Binder.restoreCallingIdentity(token);
4023 }
4024 }
4025 } else if ("get".equals(cmd)) {
4026 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4027 null);
4028 synchronized (this) {
4029 String arg = shell.getNextArg();
4030 if (arg != null) {
4031 long token = Binder.clearCallingIdentity();
4032 try {
4033 switch (arg) {
4034 case "light": pw.println(lightStateToString(mLightState)); break;
4035 case "deep": pw.println(stateToString(mState)); break;
4036 case "force": pw.println(mForceIdle); break;
Kweku Adamsb396ccf2018-09-17 16:37:15 -07004037 case "quick": pw.println(mQuickDozeActivated); break;
Dianne Hackborn88c41352016-04-07 15:18:58 -07004038 case "screen": pw.println(mScreenOn); break;
4039 case "charging": pw.println(mCharging); break;
4040 case "network": pw.println(mNetworkConnected); break;
4041 default: pw.println("Unknown get option: " + arg); break;
4042 }
4043 } finally {
4044 Binder.restoreCallingIdentity(token);
4045 }
4046 } else {
4047 pw.println("Argument required");
4048 }
4049 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004050 } else if ("disable".equals(cmd)) {
4051 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4052 null);
4053 synchronized (this) {
4054 long token = Binder.clearCallingIdentity();
Dianne Hackbornb6843652016-02-22 12:20:13 -08004055 String arg = shell.getNextArg();
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004056 try {
Dianne Hackbornb6843652016-02-22 12:20:13 -08004057 boolean becomeActive = false;
4058 boolean valid = false;
4059 if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
4060 valid = true;
4061 if (mDeepEnabled) {
4062 mDeepEnabled = false;
4063 becomeActive = true;
4064 pw.println("Deep idle mode disabled");
4065 }
4066 }
4067 if (arg == null || "light".equals(arg) || "all".equals(arg)) {
4068 valid = true;
4069 if (mLightEnabled) {
4070 mLightEnabled = false;
4071 becomeActive = true;
4072 pw.println("Light idle mode disabled");
4073 }
4074 }
4075 if (becomeActive) {
Denny cy Leec5a7c292019-01-01 17:37:55 +08004076 mActiveReason = ACTIVE_REASON_FORCED;
Dianne Hackbornb6843652016-02-22 12:20:13 -08004077 becomeActiveLocked((arg == null ? "all" : arg) + "-disabled",
4078 Process.myUid());
4079 }
4080 if (!valid) {
4081 pw.println("Unknown idle mode: " + arg);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004082 }
4083 } finally {
4084 Binder.restoreCallingIdentity(token);
4085 }
4086 }
4087 } else if ("enable".equals(cmd)) {
4088 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4089 null);
4090 synchronized (this) {
4091 long token = Binder.clearCallingIdentity();
Dianne Hackbornb6843652016-02-22 12:20:13 -08004092 String arg = shell.getNextArg();
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004093 try {
Dianne Hackbornb6843652016-02-22 12:20:13 -08004094 boolean becomeInactive = false;
4095 boolean valid = false;
4096 if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
4097 valid = true;
4098 if (!mDeepEnabled) {
4099 mDeepEnabled = true;
4100 becomeInactive = true;
4101 pw.println("Deep idle mode enabled");
4102 }
4103 }
4104 if (arg == null || "light".equals(arg) || "all".equals(arg)) {
4105 valid = true;
4106 if (!mLightEnabled) {
4107 mLightEnabled = true;
4108 becomeInactive = true;
4109 pw.println("Light idle mode enable");
4110 }
4111 }
4112 if (becomeInactive) {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004113 becomeInactiveIfAppropriateLocked();
Dianne Hackbornb6843652016-02-22 12:20:13 -08004114 }
4115 if (!valid) {
4116 pw.println("Unknown idle mode: " + arg);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004117 }
4118 } finally {
4119 Binder.restoreCallingIdentity(token);
4120 }
4121 }
4122 } else if ("enabled".equals(cmd)) {
4123 synchronized (this) {
Dianne Hackbornb6843652016-02-22 12:20:13 -08004124 String arg = shell.getNextArg();
4125 if (arg == null || "all".equals(arg)) {
4126 pw.println(mDeepEnabled && mLightEnabled ? "1" : 0);
4127 } else if ("deep".equals(arg)) {
4128 pw.println(mDeepEnabled ? "1" : 0);
4129 } else if ("light".equals(arg)) {
4130 pw.println(mLightEnabled ? "1" : 0);
4131 } else {
4132 pw.println("Unknown idle mode: " + arg);
4133 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004134 }
4135 } else if ("whitelist".equals(cmd)) {
Dianne Hackborneb909e32016-09-29 14:35:15 -07004136 String arg = shell.getNextArg();
4137 if (arg != null) {
4138 getContext().enforceCallingOrSelfPermission(
4139 android.Manifest.permission.DEVICE_POWER, null);
4140 long token = Binder.clearCallingIdentity();
4141 try {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004142 do {
4143 if (arg.length() < 1 || (arg.charAt(0) != '-'
Felipe Lemef8a46232016-02-10 13:51:54 -08004144 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
4145 pw.println("Package must be prefixed with +, -, or =: " + arg);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004146 return -1;
4147 }
4148 char op = arg.charAt(0);
4149 String pkg = arg.substring(1);
4150 if (op == '+') {
Kweku Adamsc2400c82019-10-09 15:56:04 -07004151 if (addPowerSaveWhitelistAppsInternal(Collections.singletonList(pkg))
4152 == 1) {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004153 pw.println("Added: " + pkg);
4154 } else {
4155 pw.println("Unknown package: " + pkg);
4156 }
Felipe Lemef8a46232016-02-10 13:51:54 -08004157 } else if (op == '-') {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004158 if (removePowerSaveWhitelistAppInternal(pkg)) {
4159 pw.println("Removed: " + pkg);
4160 }
Felipe Lemef8a46232016-02-10 13:51:54 -08004161 } else {
4162 pw.println(getPowerSaveWhitelistAppInternal(pkg));
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004163 }
4164 } while ((arg=shell.getNextArg()) != null);
Dianne Hackborneb909e32016-09-29 14:35:15 -07004165 } finally {
4166 Binder.restoreCallingIdentity(token);
4167 }
4168 } else {
4169 synchronized (this) {
4170 for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
4171 pw.print("system-excidle,");
4172 pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
4173 pw.print(",");
4174 pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
4175 }
4176 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
4177 pw.print("system,");
4178 pw.print(mPowerSaveWhitelistApps.keyAt(j));
4179 pw.print(",");
4180 pw.println(mPowerSaveWhitelistApps.valueAt(j));
4181 }
4182 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
4183 pw.print("user,");
4184 pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
4185 pw.print(",");
4186 pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004187 }
4188 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004189 }
4190 } else if ("tempwhitelist".equals(cmd)) {
Dianne Hackborn85e35642017-01-12 15:10:57 -08004191 long duration = 10000;
Sudheer Shanka326b3112017-11-27 14:40:57 -08004192 boolean removePkg = false;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004193 String opt;
4194 while ((opt=shell.getNextOption()) != null) {
4195 if ("-u".equals(opt)) {
4196 opt = shell.getNextArg();
4197 if (opt == null) {
4198 pw.println("-u requires a user number");
4199 return -1;
4200 }
4201 shell.userId = Integer.parseInt(opt);
Dianne Hackborn85e35642017-01-12 15:10:57 -08004202 } else if ("-d".equals(opt)) {
4203 opt = shell.getNextArg();
4204 if (opt == null) {
4205 pw.println("-d requires a duration");
4206 return -1;
4207 }
4208 duration = Long.parseLong(opt);
Sudheer Shanka326b3112017-11-27 14:40:57 -08004209 } else if ("-r".equals(opt)) {
4210 removePkg = true;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004211 }
4212 }
4213 String arg = shell.getNextArg();
4214 if (arg != null) {
4215 try {
Sudheer Shanka326b3112017-11-27 14:40:57 -08004216 if (removePkg) {
4217 removePowerSaveTempWhitelistAppChecked(arg, shell.userId);
4218 } else {
4219 addPowerSaveTempWhitelistAppChecked(arg, duration, shell.userId, "shell");
4220 }
Christopher Tateec3a9f32017-03-21 17:43:47 -07004221 } catch (Exception e) {
4222 pw.println("Failed: " + e);
4223 return -1;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004224 }
Sudheer Shanka326b3112017-11-27 14:40:57 -08004225 } else if (removePkg) {
4226 pw.println("[-r] requires a package name");
4227 return -1;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004228 } else {
Felipe Lemea1b79bf2016-05-24 13:06:54 -07004229 dumpTempWhitelistSchedule(pw, false);
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004230 }
Sudheer Shanka3f4d7702017-04-28 17:38:03 -07004231 } else if ("except-idle-whitelist".equals(cmd)) {
4232 getContext().enforceCallingOrSelfPermission(
4233 android.Manifest.permission.DEVICE_POWER, null);
4234 final long token = Binder.clearCallingIdentity();
4235 try {
4236 String arg = shell.getNextArg();
4237 if (arg == null) {
4238 pw.println("No arguments given");
4239 return -1;
4240 } else if ("reset".equals(arg)) {
4241 resetPowerSaveWhitelistExceptIdleInternal();
4242 } else {
4243 do {
4244 if (arg.length() < 1 || (arg.charAt(0) != '-'
4245 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
4246 pw.println("Package must be prefixed with +, -, or =: " + arg);
4247 return -1;
4248 }
4249 char op = arg.charAt(0);
4250 String pkg = arg.substring(1);
4251 if (op == '+') {
4252 if (addPowerSaveWhitelistExceptIdleInternal(pkg)) {
4253 pw.println("Added: " + pkg);
4254 } else {
4255 pw.println("Unknown package: " + pkg);
4256 }
4257 } else if (op == '=') {
4258 pw.println(getPowerSaveWhitelistExceptIdleInternal(pkg));
4259 } else {
4260 pw.println("Unknown argument: " + arg);
4261 return -1;
4262 }
4263 } while ((arg = shell.getNextArg()) != null);
4264 }
4265 } finally {
4266 Binder.restoreCallingIdentity(token);
4267 }
Suprabh Shukla08105642017-09-26 14:45:30 -07004268 } else if ("sys-whitelist".equals(cmd)) {
4269 String arg = shell.getNextArg();
4270 if (arg != null) {
4271 getContext().enforceCallingOrSelfPermission(
4272 android.Manifest.permission.DEVICE_POWER, null);
4273 final long token = Binder.clearCallingIdentity();
4274 try {
4275 if ("reset".equals(arg)) {
4276 resetSystemPowerWhitelistInternal();
4277 } else {
4278 do {
4279 if (arg.length() < 1
4280 || (arg.charAt(0) != '-' && arg.charAt(0) != '+')) {
4281 pw.println("Package must be prefixed with + or - " + arg);
4282 return -1;
4283 }
4284 final char op = arg.charAt(0);
4285 final String pkg = arg.substring(1);
4286 switch (op) {
4287 case '+':
4288 if (restoreSystemPowerWhitelistAppInternal(pkg)) {
4289 pw.println("Restored " + pkg);
4290 }
4291 break;
4292 case '-':
4293 if (removeSystemPowerWhitelistAppInternal(pkg)) {
4294 pw.println("Removed " + pkg);
4295 }
4296 break;
4297 }
4298 } while ((arg = shell.getNextArg()) != null);
4299 }
4300 } finally {
4301 Binder.restoreCallingIdentity(token);
4302 }
4303 } else {
4304 synchronized (this) {
Amith Yamasani4cb42572018-04-27 10:02:57 -07004305 for (int j = 0; j < mPowerSaveWhitelistApps.size(); j++) {
Suprabh Shukla08105642017-09-26 14:45:30 -07004306 pw.print(mPowerSaveWhitelistApps.keyAt(j));
4307 pw.print(",");
4308 pw.println(mPowerSaveWhitelistApps.valueAt(j));
4309 }
4310 }
4311 }
Amith Yamasani4cb42572018-04-27 10:02:57 -07004312 } else if ("motion".equals(cmd)) {
4313 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4314 null);
4315 synchronized (this) {
4316 long token = Binder.clearCallingIdentity();
4317 try {
4318 motionLocked();
4319 pw.print("Light state: ");
4320 pw.print(lightStateToString(mLightState));
4321 pw.print(", deep state: ");
4322 pw.println(stateToString(mState));
4323 } finally {
4324 Binder.restoreCallingIdentity(token);
4325 }
4326 }
Denny cy Leec5a7c292019-01-01 17:37:55 +08004327 } else if ("pre-idle-factor".equals(cmd)) {
4328 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4329 null);
4330 synchronized (this) {
4331 long token = Binder.clearCallingIdentity();
4332 int ret = SET_IDLE_FACTOR_RESULT_UNINIT;
4333 try {
4334 String arg = shell.getNextArg();
4335 boolean valid = false;
4336 int mode = 0;
4337 if (arg != null) {
4338 mode = Integer.parseInt(arg);
4339 ret = setPreIdleTimeoutMode(mode);
4340 if (ret == SET_IDLE_FACTOR_RESULT_OK) {
4341 pw.println("pre-idle-factor: " + mode);
4342 valid = true;
4343 } else if (ret == SET_IDLE_FACTOR_RESULT_NOT_SUPPORT) {
4344 valid = true;
4345 pw.println("Deep idle not supported");
4346 } else if (ret == SET_IDLE_FACTOR_RESULT_IGNORED) {
4347 valid = true;
4348 pw.println("Idle timeout factor not changed");
4349 }
4350 }
4351 if (!valid) {
4352 pw.println("Unknown idle timeout factor: " + arg
4353 + ",(error code: " + ret + ")");
4354 }
4355 } catch (NumberFormatException e) {
4356 pw.println("Unknown idle timeout factor"
4357 + ",(error code: " + ret + ")");
4358 } finally {
4359 Binder.restoreCallingIdentity(token);
4360 }
4361 }
4362 } else if ("reset-pre-idle-factor".equals(cmd)) {
4363 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4364 null);
4365 synchronized (this) {
4366 long token = Binder.clearCallingIdentity();
4367 try {
4368 resetPreIdleTimeoutMode();
4369 } finally {
4370 Binder.restoreCallingIdentity(token);
4371 }
4372 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004373 } else {
4374 return shell.handleDefaultCommands(cmd);
4375 }
4376 return 0;
4377 }
4378
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004379 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06004380 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004381
4382 if (args != null) {
Xiaohui Chen7c696362015-09-16 09:56:14 -07004383 int userId = UserHandle.USER_SYSTEM;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004384 for (int i=0; i<args.length; i++) {
4385 String arg = args[i];
4386 if ("-h".equals(arg)) {
4387 dumpHelp(pw);
4388 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07004389 } else if ("-u".equals(arg)) {
4390 i++;
4391 if (i < args.length) {
4392 arg = args[i];
4393 userId = Integer.parseInt(arg);
4394 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07004395 } else if ("-a".equals(arg)) {
4396 // Ignore, we always dump all.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004397 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
4398 pw.println("Unknown option: " + arg);
4399 return;
4400 } else {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07004401 Shell shell = new Shell();
4402 shell.userId = userId;
4403 String[] newArgs = new String[args.length-i];
4404 System.arraycopy(args, i, newArgs, 0, args.length-i);
Dianne Hackborn354736e2016-08-22 17:00:05 -07004405 shell.exec(mBinderService, null, fd, null, newArgs, null,
4406 new ResultReceiver(null));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004407 return;
4408 }
4409 }
4410 }
4411
4412 synchronized (this) {
Dianne Hackborna750a632015-06-16 17:18:23 -07004413 mConstants.dump(pw);
4414
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004415 if (mEventCmds[0] != EVENT_NULL) {
4416 pw.println(" Idling history:");
4417 long now = SystemClock.elapsedRealtime();
4418 for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) {
4419 int cmd = mEventCmds[i];
4420 if (cmd == EVENT_NULL) {
4421 continue;
4422 }
4423 String label;
4424 switch (mEventCmds[i]) {
4425 case EVENT_NORMAL: label = " normal"; break;
4426 case EVENT_LIGHT_IDLE: label = " light-idle"; break;
4427 case EVENT_LIGHT_MAINTENANCE: label = "light-maint"; break;
Dianne Hackbornb6843652016-02-22 12:20:13 -08004428 case EVENT_DEEP_IDLE: label = " deep-idle"; break;
4429 case EVENT_DEEP_MAINTENANCE: label = " deep-maint"; break;
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004430 default: label = " ??"; break;
4431 }
4432 pw.print(" ");
4433 pw.print(label);
4434 pw.print(": ");
Amith Yamasaniac6517a2018-04-23 12:19:34 -07004435 TimeUtils.formatDuration(mEventTimes[i], now, pw);
4436 if (mEventReasons[i] != null) {
4437 pw.print(" (");
4438 pw.print(mEventReasons[i]);
4439 pw.print(")");
4440 }
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004441 pw.println();
Amith Yamasaniac6517a2018-04-23 12:19:34 -07004442
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004443 }
4444 }
4445
Dianne Hackborn4a503b12015-08-06 22:19:06 -07004446 int size = mPowerSaveWhitelistAppsExceptIdle.size();
4447 if (size > 0) {
4448 pw.println(" Whitelist (except idle) system apps:");
4449 for (int i = 0; i < size; i++) {
4450 pw.print(" ");
4451 pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
4452 }
4453 }
4454 size = mPowerSaveWhitelistApps.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004455 if (size > 0) {
4456 pw.println(" Whitelist system apps:");
4457 for (int i = 0; i < size; i++) {
4458 pw.print(" ");
4459 pw.println(mPowerSaveWhitelistApps.keyAt(i));
4460 }
4461 }
Suprabh Shukla08105642017-09-26 14:45:30 -07004462 size = mRemovedFromSystemWhitelistApps.size();
4463 if (size > 0) {
4464 pw.println(" Removed from whitelist system apps:");
4465 for (int i = 0; i < size; i++) {
4466 pw.print(" ");
4467 pw.println(mRemovedFromSystemWhitelistApps.keyAt(i));
4468 }
4469 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004470 size = mPowerSaveWhitelistUserApps.size();
4471 if (size > 0) {
4472 pw.println(" Whitelist user apps:");
4473 for (int i = 0; i < size; i++) {
4474 pw.print(" ");
4475 pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
4476 }
4477 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07004478 size = mPowerSaveWhitelistExceptIdleAppIds.size();
4479 if (size > 0) {
4480 pw.println(" Whitelist (except idle) all app ids:");
4481 for (int i = 0; i < size; i++) {
4482 pw.print(" ");
4483 pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
4484 pw.println();
4485 }
4486 }
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08004487 size = mPowerSaveWhitelistUserAppIds.size();
4488 if (size > 0) {
4489 pw.println(" Whitelist user app ids:");
4490 for (int i = 0; i < size; i++) {
4491 pw.print(" ");
4492 pw.print(mPowerSaveWhitelistUserAppIds.keyAt(i));
4493 pw.println();
4494 }
4495 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07004496 size = mPowerSaveWhitelistAllAppIds.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004497 if (size > 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07004498 pw.println(" Whitelist all app ids:");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004499 for (int i = 0; i < size; i++) {
Dianne Hackborna750a632015-06-16 17:18:23 -07004500 pw.print(" ");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07004501 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004502 pw.println();
4503 }
4504 }
Felipe Lemea1b79bf2016-05-24 13:06:54 -07004505 dumpTempWhitelistSchedule(pw, true);
4506
Dianne Hackborna750a632015-06-16 17:18:23 -07004507 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
4508 if (size > 0) {
4509 pw.println(" Temp whitelist app ids:");
4510 for (int i = 0; i < size; i++) {
4511 pw.print(" ");
4512 pw.print(mTempWhitelistAppIdArray[i]);
4513 pw.println();
4514 }
4515 }
Adam Lesinski31c05d12015-06-09 17:34:04 -07004516
Dianne Hackbornb6843652016-02-22 12:20:13 -08004517 pw.print(" mLightEnabled="); pw.print(mLightEnabled);
Felipe Lemea1b79bf2016-05-24 13:06:54 -07004518 pw.print(" mDeepEnabled="); pw.println(mDeepEnabled);
Dianne Hackborn4a503b12015-08-06 22:19:06 -07004519 pw.print(" mForceIdle="); pw.println(mForceIdle);
Robin Leec4d424c2018-12-07 15:09:13 +01004520 pw.print(" mUseMotionSensor="); pw.print(mUseMotionSensor);
4521 if (mUseMotionSensor) {
4522 pw.print(" mMotionSensor="); pw.println(mMotionSensor);
4523 } else {
4524 pw.println();
4525 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004526 pw.print(" mScreenOn="); pw.println(mScreenOn);
Amith Yamasani396a10c2018-01-19 10:58:07 -08004527 pw.print(" mScreenLocked="); pw.println(mScreenLocked);
Dianne Hackborn88c41352016-04-07 15:18:58 -07004528 pw.print(" mNetworkConnected="); pw.println(mNetworkConnected);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004529 pw.print(" mCharging="); pw.println(mCharging);
Robin Lee876b88542018-11-13 17:22:24 +01004530 if (mConstraints.size() != 0) {
4531 pw.println(" mConstraints={");
4532 for (int i = 0; i < mConstraints.size(); i++) {
4533 final DeviceIdleConstraintTracker tracker = mConstraints.valueAt(i);
4534 pw.print(" \""); pw.print(tracker.name); pw.print("\"=");
4535 if (tracker.minState == mState) {
4536 pw.println(tracker.active);
4537 } else {
4538 pw.print("ignored <mMinState="); pw.print(stateToString(tracker.minState));
4539 pw.println(">");
4540 }
4541 }
4542 pw.println(" }");
4543 }
Kweku Adams810c77d2019-08-28 07:45:00 -07004544 if (mUseMotionSensor || mStationaryListeners.size() > 0) {
Robin Lee876b88542018-11-13 17:22:24 +01004545 pw.print(" mMotionActive="); pw.println(mMotionListener.active);
Robin Leec4d424c2018-12-07 15:09:13 +01004546 pw.print(" mNotMoving="); pw.println(mNotMoving);
Kweku Adams810c77d2019-08-28 07:45:00 -07004547 pw.print(" mMotionListener.activatedTimeElapsed=");
4548 pw.println(mMotionListener.activatedTimeElapsed);
4549 pw.print(" mLastMotionEventElapsed="); pw.println(mLastMotionEventElapsed);
4550 pw.print(" "); pw.print(mStationaryListeners.size());
4551 pw.println(" stationary listeners registered");
Robin Leec4d424c2018-12-07 15:09:13 +01004552 }
Joe LaPenna23d681b2015-08-27 15:12:11 -07004553 pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
4554 pw.print(mHasGps); pw.print(" mHasNetwork=");
4555 pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07004556 if (mLastGenericLocation != null) {
4557 pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation);
4558 }
4559 if (mLastGpsLocation != null) {
4560 pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation);
4561 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07004562 pw.print(" mState="); pw.print(stateToString(mState));
4563 pw.print(" mLightState=");
4564 pw.println(lightStateToString(mLightState));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004565 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
4566 pw.println();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004567 if (mActiveIdleOpCount != 0) {
4568 pw.print(" mActiveIdleOpCount="); pw.println(mActiveIdleOpCount);
4569 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004570 if (mNextAlarmTime != 0) {
4571 pw.print(" mNextAlarmTime=");
4572 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
4573 pw.println();
4574 }
4575 if (mNextIdlePendingDelay != 0) {
4576 pw.print(" mNextIdlePendingDelay=");
4577 TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
4578 pw.println();
4579 }
4580 if (mNextIdleDelay != 0) {
4581 pw.print(" mNextIdleDelay=");
4582 TimeUtils.formatDuration(mNextIdleDelay, pw);
4583 pw.println();
4584 }
Dianne Hackborn953fc942016-03-29 15:36:24 -07004585 if (mNextLightIdleDelay != 0) {
4586 pw.print(" mNextIdleDelay=");
4587 TimeUtils.formatDuration(mNextLightIdleDelay, pw);
4588 pw.println();
4589 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07004590 if (mNextLightAlarmTime != 0) {
4591 pw.print(" mNextLightAlarmTime=");
4592 TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
4593 pw.println();
4594 }
Kweku Adams7c96f5182019-06-04 16:32:49 -07004595 if (mCurLightIdleBudget != 0) {
4596 pw.print(" mCurLightIdleBudget=");
4597 TimeUtils.formatDuration(mCurLightIdleBudget, pw);
Dianne Hackborn8ed2b972015-11-18 14:52:04 -08004598 pw.println();
4599 }
4600 if (mMaintenanceStartTime != 0) {
4601 pw.print(" mMaintenanceStartTime=");
4602 TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw);
4603 pw.println();
4604 }
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004605 if (mJobsActive) {
4606 pw.print(" mJobsActive="); pw.println(mJobsActive);
4607 }
4608 if (mAlarmsActive) {
4609 pw.print(" mAlarmsActive="); pw.println(mAlarmsActive);
4610 }
Denny cy Leec5a7c292019-01-01 17:37:55 +08004611 if (Math.abs(mPreIdleFactor - 1.0f) > MIN_PRE_IDLE_FACTOR_CHANGE) {
4612 pw.print(" mPreIdleFactor="); pw.println(mPreIdleFactor);
4613 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07004614 }
4615 }
Felipe Lemea1b79bf2016-05-24 13:06:54 -07004616
4617 void dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle) {
4618 final int size = mTempWhitelistAppIdEndTimes.size();
4619 if (size > 0) {
4620 String prefix = "";
4621 if (printTitle) {
4622 pw.println(" Temp whitelist schedule:");
4623 prefix = " ";
4624 }
4625 final long timeNow = SystemClock.elapsedRealtime();
4626 for (int i = 0; i < size; i++) {
4627 pw.print(prefix);
4628 pw.print("UID=");
4629 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
4630 pw.print(": ");
4631 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
4632 TimeUtils.formatDuration(entry.first.value, timeNow, pw);
4633 pw.print(" - ");
4634 pw.println(entry.second);
4635 }
4636 }
4637 }
4638 }