blob: ebcdf7c3190149f55bc15d28a4eb6c1a52a8e82a [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;
20import android.app.ActivityManagerNative;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070021import android.app.AlarmManager;
22import android.app.PendingIntent;
23import 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;
33import android.hardware.SensorManager;
Nick Vaccaro20feaea2015-09-17 17:22:44 -070034import android.hardware.SensorEvent;
35import android.hardware.SensorEventListener;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070036import android.hardware.TriggerEvent;
37import android.hardware.TriggerEventListener;
38import android.hardware.display.DisplayManager;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -070039import android.location.LocationRequest;
40import android.location.Location;
41import android.location.LocationListener;
42import android.location.LocationManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070043import android.net.INetworkPolicyManager;
Adam Lesinski31c05d12015-06-09 17:34:04 -070044import android.net.Uri;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070045import android.os.BatteryStats;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070046import android.os.Binder;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -070047import android.os.Bundle;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070048import android.os.Environment;
49import android.os.FileUtils;
50import android.os.Handler;
51import android.os.IDeviceIdleController;
52import android.os.Looper;
53import android.os.Message;
54import android.os.PowerManager;
55import android.os.PowerManagerInternal;
Dianne Hackbornb6683c42015-06-18 17:40:33 -070056import android.os.Process;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070057import android.os.RemoteException;
58import android.os.ServiceManager;
59import android.os.SystemClock;
60import android.os.UserHandle;
Adam Lesinski31c05d12015-06-09 17:34:04 -070061import android.provider.Settings;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070062import android.util.ArrayMap;
63import android.util.ArraySet;
Adam Lesinski31c05d12015-06-09 17:34:04 -070064import android.util.KeyValueListParser;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070065import android.util.MutableLong;
66import android.util.Pair;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070067import android.util.Slog;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070068import android.util.SparseArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070069import android.util.SparseBooleanArray;
70import android.util.TimeUtils;
71import android.util.Xml;
72import android.view.Display;
Amith Yamasani520d8f22015-05-08 16:36:21 -070073
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070074import com.android.internal.app.IBatteryStats;
75import com.android.internal.os.AtomicFile;
76import com.android.internal.os.BackgroundThread;
77import com.android.internal.util.FastXmlSerializer;
78import com.android.internal.util.XmlUtils;
79import com.android.server.am.BatteryStatsService;
Amith Yamasani520d8f22015-05-08 16:36:21 -070080
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070081import org.xmlpull.v1.XmlPullParser;
82import org.xmlpull.v1.XmlPullParserException;
83import org.xmlpull.v1.XmlSerializer;
84
85import java.io.ByteArrayOutputStream;
86import java.io.File;
87import java.io.FileDescriptor;
88import java.io.FileInputStream;
89import java.io.FileNotFoundException;
90import java.io.FileOutputStream;
91import java.io.IOException;
92import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +010093import java.nio.charset.StandardCharsets;
Amith Yamasaniaf575b92015-05-29 15:35:26 -070094import java.util.Arrays;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070095
96/**
97 * Keeps track of device idleness and drives low power mode based on that.
98 */
Kevin Gabayan89ecf822015-05-18 12:10:07 -070099public class DeviceIdleController extends SystemService
100 implements AnyMotionDetector.DeviceIdleCallback {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700101 private static final String TAG = "DeviceIdleController";
102
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700103 private static final boolean DEBUG = false;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700104
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700105 private static final boolean COMPRESS_TIME = false;
Amith Yamasani520d8f22015-05-08 16:36:21 -0700106
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700107 private static final String ACTION_STEP_IDLE_STATE =
108 "com.android.server.device_idle.STEP_IDLE_STATE";
109
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700110 private AlarmManager mAlarmManager;
111 private IBatteryStats mBatteryStats;
112 private PowerManagerInternal mLocalPowerManager;
113 private INetworkPolicyManager mNetworkPolicyManager;
114 private DisplayManager mDisplayManager;
115 private SensorManager mSensorManager;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700116 private Sensor mMotionSensor;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700117 private LocationManager mLocationManager;
118 private LocationRequest mLocationRequest;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700119 private PendingIntent mSensingAlarmIntent;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700120 private PendingIntent mAlarmIntent;
121 private Intent mIdleIntent;
122 private Display mCurDisplay;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700123 private AnyMotionDetector mAnyMotionDetector;
Dianne Hackborn92617032015-06-19 15:32:19 -0700124 private boolean mEnabled;
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700125 private boolean mForceIdle;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700126 private boolean mScreenOn;
127 private boolean mCharging;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700128 private boolean mSensing;
129 private boolean mNotMoving;
130 private boolean mLocating;
131 private boolean mLocated;
Joe LaPenna23d681b2015-08-27 15:12:11 -0700132 private boolean mHasGps;
133 private boolean mHasNetworkLocation;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700134 private Location mLastGenericLocation;
135 private Location mLastGpsLocation;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700136
137 /** Device is currently active. */
138 private static final int STATE_ACTIVE = 0;
139 /** Device is inactve (screen off, no motion) and we are waiting to for idle. */
140 private static final int STATE_INACTIVE = 1;
141 /** Device is past the initial inactive period, and waiting for the next idle period. */
142 private static final int STATE_IDLE_PENDING = 2;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700143 /** Device is currently sensing motion. */
144 private static final int STATE_SENSING = 3;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700145 /** Device is currently finding location (and may still be sensing). */
146 private static final int STATE_LOCATING = 4;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700147 /** Device is in the idle state, trying to stay asleep as much as possible. */
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700148 private static final int STATE_IDLE = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700149 /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700150 private static final int STATE_IDLE_MAINTENANCE = 6;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700151 private static String stateToString(int state) {
152 switch (state) {
153 case STATE_ACTIVE: return "ACTIVE";
154 case STATE_INACTIVE: return "INACTIVE";
155 case STATE_IDLE_PENDING: return "IDLE_PENDING";
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700156 case STATE_SENSING: return "SENSING";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700157 case STATE_LOCATING: return "LOCATING";
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700158 case STATE_IDLE: return "IDLE";
159 case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
160 default: return Integer.toString(state);
161 }
162 }
163
164 private int mState;
165
166 private long mInactiveTimeout;
167 private long mNextAlarmTime;
168 private long mNextIdlePendingDelay;
169 private long mNextIdleDelay;
170
171 public final AtomicFile mConfigFile;
172
173 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700174 * Package names the system has white-listed to opt out of power save restrictions,
175 * except for device idle mode.
176 */
177 private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
178
179 /**
180 * Package names the system has white-listed to opt out of power save restrictions for
181 * all modes.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700182 */
183 private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
184
185 /**
186 * Package names the user has white-listed to opt out of power save restrictions.
187 */
188 private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
189
190 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700191 * App IDs of built-in system apps that have been white-listed except for idle modes.
192 */
193 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
194 = new SparseBooleanArray();
195
196 /**
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700197 * App IDs of built-in system apps that have been white-listed.
198 */
199 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
200
201 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700202 * App IDs that have been white-listed to opt out of power save restrictions, except
203 * for device idle modes.
204 */
205 private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
206
207 /**
208 * Current app IDs that are in the complete power save white list, but shouldn't be
209 * excluded from idle modes. This array can be shared with others because it will not be
210 * modified once set.
211 */
212 private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
213
214 /**
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700215 * App IDs that have been white-listed to opt out of power save restrictions.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700216 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700217 private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700218
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700219 /**
220 * Current app IDs that are in the complete power save white list. This array can
221 * be shared with others because it will not be modified once set.
222 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700223 private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700224
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700225 /**
226 * List of end times for UIDs that are temporarily marked as being allowed to access
227 * the network and acquire wakelocks. Times are in milliseconds.
228 */
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700229 private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
230 = new SparseArray<>();
231
232 /**
233 * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
234 */
235 Runnable mNetworkPolicyTempWhitelistCallback;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700236
237 /**
238 * Current app IDs of temporarily whitelist apps for high-priority messages.
239 */
240 private int[] mTempWhitelistAppIdArray = new int[0];
241
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700242 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
243 @Override public void onReceive(Context context, Intent intent) {
244 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
245 int plugged = intent.getIntExtra("plugged", 0);
246 updateChargingLocked(plugged != 0);
247 } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
248 synchronized (DeviceIdleController.this) {
249 stepIdleStateLocked();
250 }
251 }
252 }
253 };
254
255 private final DisplayManager.DisplayListener mDisplayListener
256 = new DisplayManager.DisplayListener() {
257 @Override public void onDisplayAdded(int displayId) {
258 }
259
260 @Override public void onDisplayRemoved(int displayId) {
261 }
262
263 @Override public void onDisplayChanged(int displayId) {
264 if (displayId == Display.DEFAULT_DISPLAY) {
265 synchronized (DeviceIdleController.this) {
266 updateDisplayLocked();
267 }
268 }
269 }
270 };
271
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700272 private final class MotionListener extends TriggerEventListener
273 implements SensorEventListener {
274
275 boolean active = false;
276
277 @Override
278 public void onTrigger(TriggerEvent event) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700279 synchronized (DeviceIdleController.this) {
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700280 active = false;
281 motionLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700282 }
283 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700284
285 @Override
286 public void onSensorChanged(SensorEvent event) {
287 synchronized (DeviceIdleController.this) {
288 mSensorManager.unregisterListener(this, mMotionSensor);
289 active = false;
290 motionLocked();
291 }
292 }
293
294 @Override
295 public void onAccuracyChanged(Sensor sensor, int accuracy) {}
296
297 public boolean registerLocked() {
298 boolean success = false;
299 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
300 success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
301 } else {
302 success = mSensorManager.registerListener(
303 mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL);
304 }
305 if (success) {
306 active = true;
307 } else {
308 Slog.e(TAG, "Unable to register for " + mMotionSensor);
309 }
310 return success;
311 }
312
313 public void unregisterLocked() {
314 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
315 mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor);
316 } else {
317 mSensorManager.unregisterListener(mMotionListener);
318 }
319 active = false;
320 }
321 }
322 private final MotionListener mMotionListener = new MotionListener();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700323
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700324 private final LocationListener mGenericLocationListener = new LocationListener() {
325 @Override
326 public void onLocationChanged(Location location) {
327 synchronized (DeviceIdleController.this) {
328 receivedGenericLocationLocked(location);
329 }
330 }
331
332 @Override
333 public void onStatusChanged(String provider, int status, Bundle extras) {
334 }
335
336 @Override
337 public void onProviderEnabled(String provider) {
338 }
339
340 @Override
341 public void onProviderDisabled(String provider) {
342 }
343 };
344
345 private final LocationListener mGpsLocationListener = new LocationListener() {
346 @Override
347 public void onLocationChanged(Location location) {
348 synchronized (DeviceIdleController.this) {
349 receivedGpsLocationLocked(location);
350 }
351 }
352
353 @Override
354 public void onStatusChanged(String provider, int status, Bundle extras) {
355 }
356
357 @Override
358 public void onProviderEnabled(String provider) {
359 }
360
361 @Override
362 public void onProviderDisabled(String provider) {
363 }
364 };
365
Adam Lesinski31c05d12015-06-09 17:34:04 -0700366 /**
367 * All times are in milliseconds. These constants are kept synchronized with the system
368 * global Settings. Any access to this class or its fields should be done while
369 * holding the DeviceIdleController lock.
370 */
Dianne Hackborna750a632015-06-16 17:18:23 -0700371 private final class Constants extends ContentObserver {
Adam Lesinski31c05d12015-06-09 17:34:04 -0700372 // Key names stored in the settings value.
373 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
374 private static final String KEY_SENSING_TIMEOUT = "sensing_to";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700375 private static final String KEY_LOCATING_TIMEOUT = "locating_to";
376 private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700377 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
378 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
379 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
380 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
381 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
382 private static final String KEY_IDLE_TIMEOUT = "idle_to";
383 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
384 private static final String KEY_IDLE_FACTOR = "idle_factor";
385 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
386 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
387 "max_temp_app_whitelist_duration";
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700388 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
389 "mms_temp_app_whitelist_duration";
Dianne Hackborn451c3462015-07-21 17:39:46 -0700390 private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
391 "sms_temp_app_whitelist_duration";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700392
393 /**
394 * This is the time, after becoming inactive, at which we start looking at the
395 * motion sensor to determine if the device is being left alone. We don't do this
396 * immediately after going inactive just because we don't want to be continually running
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700397 * the motion sensor whenever the screen is off.
Adam Lesinski31c05d12015-06-09 17:34:04 -0700398 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
399 * @see #KEY_INACTIVE_TIMEOUT
400 */
401 public long INACTIVE_TIMEOUT;
402
403 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700404 * If we don't receive a callback from AnyMotion in this amount of time +
405 * {@link #LOCATING_TIMEOUT}, we will change from
Adam Lesinski31c05d12015-06-09 17:34:04 -0700406 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
407 * will be ignored.
408 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
409 * @see #KEY_SENSING_TIMEOUT
410 */
411 public long SENSING_TIMEOUT;
412
413 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700414 * This is how long we will wait to try to get a good location fix before going in to
415 * idle mode.
416 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
417 * @see #KEY_LOCATING_TIMEOUT
418 */
419 public long LOCATING_TIMEOUT;
420
421 /**
422 * The desired maximum accuracy (in meters) we consider the location to be good enough to go
423 * on to idle. We will be trying to get an accuracy fix at least this good or until
424 * {@link #LOCATING_TIMEOUT} expires.
425 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
426 * @see #KEY_LOCATION_ACCURACY
427 */
428 public float LOCATION_ACCURACY;
429
430 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -0700431 * This is the time, after seeing motion, that we wait after becoming inactive from
432 * that until we start looking for motion again.
433 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
434 * @see #KEY_MOTION_INACTIVE_TIMEOUT
435 */
436 public long MOTION_INACTIVE_TIMEOUT;
437
438 /**
439 * This is the time, after the inactive timeout elapses, that we will wait looking
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700440 * for motion until we truly consider the device to be idle.
Adam Lesinski31c05d12015-06-09 17:34:04 -0700441 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
442 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
443 */
444 public long IDLE_AFTER_INACTIVE_TIMEOUT;
445
446 /**
447 * This is the initial time, after being idle, that we will allow ourself to be back
448 * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
449 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
450 * @see #KEY_IDLE_PENDING_TIMEOUT
451 */
452 public long IDLE_PENDING_TIMEOUT;
453
454 /**
455 * Maximum pending idle timeout (time spent running) we will be allowed to use.
456 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
457 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
458 */
459 public long MAX_IDLE_PENDING_TIMEOUT;
460
461 /**
462 * Scaling factor to apply to current pending idle timeout each time we cycle through
463 * that state.
464 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
465 * @see #KEY_IDLE_PENDING_FACTOR
466 */
467 public float IDLE_PENDING_FACTOR;
468
469 /**
470 * This is the initial time that we want to sit in the idle state before waking up
471 * again to return to pending idle and allowing normal work to run.
472 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
473 * @see #KEY_IDLE_TIMEOUT
474 */
475 public long IDLE_TIMEOUT;
476
477 /**
478 * Maximum idle duration we will be allowed to use.
479 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
480 * @see #KEY_MAX_IDLE_TIMEOUT
481 */
482 public long MAX_IDLE_TIMEOUT;
483
484 /**
485 * Scaling factor to apply to current idle timeout each time we cycle through that state.
486 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
487 * @see #KEY_IDLE_FACTOR
488 */
489 public float IDLE_FACTOR;
490
491 /**
492 * This is the minimum time we will allow until the next upcoming alarm for us to
493 * actually go in to idle mode.
494 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
495 * @see #KEY_MIN_TIME_TO_ALARM
496 */
497 public long MIN_TIME_TO_ALARM;
498
499 /**
500 * Max amount of time to temporarily whitelist an app when it receives a high priority
501 * tickle.
502 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
503 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
504 */
505 public long MAX_TEMP_APP_WHITELIST_DURATION;
506
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700507 /**
508 * Amount of time we would like to whitelist an app that is receiving an MMS.
509 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
510 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
511 */
512 public long MMS_TEMP_APP_WHITELIST_DURATION;
513
Dianne Hackborn451c3462015-07-21 17:39:46 -0700514 /**
515 * Amount of time we would like to whitelist an app that is receiving an SMS.
516 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
517 * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
518 */
519 public long SMS_TEMP_APP_WHITELIST_DURATION;
520
Adam Lesinski31c05d12015-06-09 17:34:04 -0700521 private final ContentResolver mResolver;
522 private final KeyValueListParser mParser = new KeyValueListParser(',');
523
524 public Constants(Handler handler, ContentResolver resolver) {
525 super(handler);
526 mResolver = resolver;
527 mResolver.registerContentObserver(
528 Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), false, this);
529 updateConstants();
530 }
531
532 @Override
533 public void onChange(boolean selfChange, Uri uri) {
534 updateConstants();
535 }
536
537 private void updateConstants() {
538 synchronized (DeviceIdleController.this) {
539 try {
540 mParser.setString(Settings.Global.getString(mResolver,
541 Settings.Global.DEVICE_IDLE_CONSTANTS));
542 } catch (IllegalArgumentException e) {
543 // Failed to parse the settings string, log this and move on
544 // with defaults.
545 Slog.e(TAG, "Bad device idle settings", e);
546 }
547
548 INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
549 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
550 SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700551 !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
552 LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
553 !DEBUG ? 30 * 1000L : 15 * 1000L);
554 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700555 MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
556 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
557 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
558 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
559 IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
560 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
561 MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
562 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
563 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
564 2f);
565 IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
566 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
567 MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
568 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
569 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
570 2f);
571 MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
572 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700573 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
574 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
575 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
Dianne Hackborn0b6134b2015-07-14 18:48:07 -0700576 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
Dianne Hackborn451c3462015-07-21 17:39:46 -0700577 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
578 KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700579 }
580 }
581
582 void dump(PrintWriter pw) {
583 pw.println(" Settings:");
584
Dianne Hackborna750a632015-06-16 17:18:23 -0700585 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700586 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
587 pw.println();
588
Dianne Hackborna750a632015-06-16 17:18:23 -0700589 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700590 TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
591 pw.println();
592
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700593 pw.print(" "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
594 TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
595 pw.println();
596
597 pw.print(" "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
598 pw.print(LOCATION_ACCURACY); pw.print("m");
599 pw.println();
600
Dianne Hackborna750a632015-06-16 17:18:23 -0700601 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700602 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
603 pw.println();
604
Dianne Hackborna750a632015-06-16 17:18:23 -0700605 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700606 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
607 pw.println();
608
Dianne Hackborna750a632015-06-16 17:18:23 -0700609 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700610 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
611 pw.println();
612
Dianne Hackborna750a632015-06-16 17:18:23 -0700613 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700614 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
615 pw.println();
616
Dianne Hackborna750a632015-06-16 17:18:23 -0700617 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700618 pw.println(IDLE_PENDING_FACTOR);
619
Dianne Hackborna750a632015-06-16 17:18:23 -0700620 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700621 TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
622 pw.println();
623
Dianne Hackborna750a632015-06-16 17:18:23 -0700624 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700625 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
626 pw.println();
627
Dianne Hackborna750a632015-06-16 17:18:23 -0700628 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700629 pw.println(IDLE_FACTOR);
630
Dianne Hackborna750a632015-06-16 17:18:23 -0700631 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700632 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
633 pw.println();
634
Dianne Hackborna750a632015-06-16 17:18:23 -0700635 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700636 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
637 pw.println();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700638
639 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
640 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
641 pw.println();
Dianne Hackborn451c3462015-07-21 17:39:46 -0700642
643 pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
644 TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
645 pw.println();
Adam Lesinski31c05d12015-06-09 17:34:04 -0700646 }
647 }
648
649 private Constants mConstants;
650
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700651 @Override
652 public void onAnyMotionResult(int result) {
653 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700654 if (result == AnyMotionDetector.RESULT_MOVED) {
655 if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
656 synchronized (this) {
657 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
658 }
659 } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
660 if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
661 if (mState == STATE_SENSING) {
662 // If we are currently sensing, it is time to move to locating.
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700663 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700664 mNotMoving = true;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700665 stepIdleStateLocked();
666 }
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700667 } else if (mState == STATE_LOCATING) {
668 // If we are currently locating, note that we are not moving and step
669 // if we have located the position.
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700670 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700671 mNotMoving = true;
672 if (mLocated) {
673 stepIdleStateLocked();
674 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700675 }
676 }
677 }
678 }
679
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700680 static final int MSG_WRITE_CONFIG = 1;
681 static final int MSG_REPORT_IDLE_ON = 2;
682 static final int MSG_REPORT_IDLE_OFF = 3;
683 static final int MSG_REPORT_ACTIVE = 4;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700684 static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700685
686 final class MyHandler extends Handler {
687 MyHandler(Looper looper) {
688 super(looper);
689 }
690
691 @Override public void handleMessage(Message msg) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700692 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700693 switch (msg.what) {
694 case MSG_WRITE_CONFIG: {
695 handleWriteConfigFile();
696 } break;
697 case MSG_REPORT_IDLE_ON: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700698 EventLogTags.writeDeviceIdleOnStart();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700699 mLocalPowerManager.setDeviceIdleMode(true);
700 try {
701 mNetworkPolicyManager.setDeviceIdleMode(true);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700702 mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700703 } catch (RemoteException e) {
704 }
705 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700706 EventLogTags.writeDeviceIdleOnComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700707 } break;
708 case MSG_REPORT_IDLE_OFF: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700709 EventLogTags.writeDeviceIdleOffStart("unknown");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700710 mLocalPowerManager.setDeviceIdleMode(false);
711 try {
712 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700713 mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700714 } catch (RemoteException e) {
715 }
716 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700717 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700718 } break;
719 case MSG_REPORT_ACTIVE: {
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700720 String activeReason = (String)msg.obj;
721 int activeUid = msg.arg1;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700722 boolean needBroadcast = msg.arg2 != 0;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700723 EventLogTags.writeDeviceIdleOffStart(
724 activeReason != null ? activeReason : "unknown");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700725 mLocalPowerManager.setDeviceIdleMode(false);
726 try {
727 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700728 mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700729 } catch (RemoteException e) {
730 }
731 if (needBroadcast) {
732 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
733 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700734 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700735 } break;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700736 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
737 int uid = msg.arg1;
738 checkTempAppWhitelistTimeout(uid);
739 } break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700740 }
741 }
742 }
743
744 final MyHandler mHandler;
745
746 private final class BinderService extends IDeviceIdleController.Stub {
747 @Override public void addPowerSaveWhitelistApp(String name) {
748 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
749 null);
750 addPowerSaveWhitelistAppInternal(name);
751 }
752
753 @Override public void removePowerSaveWhitelistApp(String name) {
754 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
755 null);
756 removePowerSaveWhitelistAppInternal(name);
757 }
758
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700759 @Override public String[] getSystemPowerWhitelistExceptIdle() {
760 return getSystemPowerWhitelistExceptIdleInternal();
761 }
762
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700763 @Override public String[] getSystemPowerWhitelist() {
764 return getSystemPowerWhitelistInternal();
765 }
766
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700767 @Override public String[] getFullPowerWhitelistExceptIdle() {
768 return getFullPowerWhitelistExceptIdleInternal();
769 }
770
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700771 @Override public String[] getFullPowerWhitelist() {
772 return getFullPowerWhitelistInternal();
773 }
774
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700775 @Override public int[] getAppIdWhitelistExceptIdle() {
776 return getAppIdWhitelistExceptIdleInternal();
777 }
778
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700779 @Override public int[] getAppIdWhitelist() {
780 return getAppIdWhitelistInternal();
781 }
782
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700783 @Override public int[] getAppIdTempWhitelist() {
784 return getAppIdTempWhitelistInternal();
785 }
786
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700787 @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
788 return isPowerSaveWhitelistExceptIdleAppInternal(name);
789 }
790
Amith Yamasani06bf8242015-05-08 16:36:21 -0700791 @Override public boolean isPowerSaveWhitelistApp(String name) {
792 return isPowerSaveWhitelistAppInternal(name);
793 }
794
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700795 @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700796 int userId, String reason) throws RemoteException {
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700797 getContext().enforceCallingPermission(
798 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
799 "No permission to change device idle whitelist");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700800 final int callingUid = Binder.getCallingUid();
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700801 userId = ActivityManagerNative.getDefault().handleIncomingUser(
802 Binder.getCallingPid(),
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700803 callingUid,
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700804 userId,
805 /*allowAll=*/ false,
806 /*requireFull=*/ false,
Dianne Hackborna750a632015-06-16 17:18:23 -0700807 "addPowerSaveTempWhitelistApp", null);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700808 final long token = Binder.clearCallingIdentity();
809 try {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700810 DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700811 packageName, duration, userId, true, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700812 } finally {
813 Binder.restoreCallingIdentity(token);
814 }
815 }
816
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700817 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
818 int userId, String reason) throws RemoteException {
819 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
820 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
821 return duration;
822 }
823
Dianne Hackborn451c3462015-07-21 17:39:46 -0700824 @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
825 int userId, String reason) throws RemoteException {
826 long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
827 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
828 return duration;
829 }
830
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700831 @Override public void exitIdle(String reason) {
832 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
833 null);
834 exitIdleInternal(reason);
835 }
836
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700837 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
838 DeviceIdleController.this.dump(fd, pw, args);
839 }
840 }
841
Dianne Hackborna750a632015-06-16 17:18:23 -0700842 public final class LocalService {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700843 public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
844 String reason) {
845 addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
846 }
847
848 public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
849 setNetworkPolicyTempWhitelistCallbackInternal(callback);
Dianne Hackborna750a632015-06-16 17:18:23 -0700850 }
851 }
852
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700853 public DeviceIdleController(Context context) {
854 super(context);
855 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
856 mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
857 }
858
859 private static File getSystemDir() {
860 return new File(Environment.getDataDirectory(), "system");
861 }
862
863 @Override
864 public void onStart() {
865 final PackageManager pm = getContext().getPackageManager();
866
867 synchronized (this) {
Dianne Hackborn92617032015-06-19 15:32:19 -0700868 mEnabled = getContext().getResources().getBoolean(
869 com.android.internal.R.bool.config_enableAutoPowerModes);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700870 SystemConfig sysConfig = SystemConfig.getInstance();
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700871 ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
872 for (int i=0; i<allowPowerExceptIdle.size(); i++) {
873 String pkg = allowPowerExceptIdle.valueAt(i);
874 try {
875 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
876 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
877 int appid = UserHandle.getAppId(ai.uid);
878 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
879 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
880 }
881 } catch (PackageManager.NameNotFoundException e) {
882 }
883 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700884 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
885 for (int i=0; i<allowPower.size(); i++) {
886 String pkg = allowPower.valueAt(i);
887 try {
888 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
889 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700890 int appid = UserHandle.getAppId(ai.uid);
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700891 // These apps are on both the whitelist-except-idle as well
892 // as the full whitelist, so they apply in all cases.
893 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
894 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700895 mPowerSaveWhitelistApps.put(ai.packageName, appid);
896 mPowerSaveWhitelistSystemAppIds.put(appid, true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700897 }
898 } catch (PackageManager.NameNotFoundException e) {
899 }
900 }
901
Adam Lesinski31c05d12015-06-09 17:34:04 -0700902 mConstants = new Constants(mHandler, getContext().getContentResolver());
903
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700904 readConfigFileLocked();
905 updateWhitelistAppIdsLocked();
906
907 mScreenOn = true;
908 // Start out assuming we are charging. If we aren't, we will at least get
909 // a battery update the next time the level drops.
910 mCharging = true;
911 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -0700912 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700913 }
914
Dianne Hackborn1958e5e2015-06-12 18:11:41 -0700915 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
Dianne Hackborna750a632015-06-16 17:18:23 -0700916 publishLocalService(LocalService.class, new LocalService());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700917 }
918
919 @Override
920 public void onBootPhase(int phase) {
921 if (phase == PHASE_SYSTEM_SERVICES_READY) {
922 synchronized (this) {
923 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
924 mBatteryStats = BatteryStatsService.getService();
925 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
926 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700927 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700928 mDisplayManager = (DisplayManager) getContext().getSystemService(
929 Context.DISPLAY_SERVICE);
930 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
Joe LaPenna23d681b2015-08-27 15:12:11 -0700931 int sigMotionSensorId = getContext().getResources().getInteger(
932 com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
933 if (sigMotionSensorId > 0) {
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700934 mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
Joe LaPenna23d681b2015-08-27 15:12:11 -0700935 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700936 if (mMotionSensor == null && getContext().getResources().getBoolean(
Joe LaPenna23d681b2015-08-27 15:12:11 -0700937 com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700938 mMotionSensor = mSensorManager.getDefaultSensor(
939 Sensor.TYPE_WRIST_TILT_GESTURE, true);
Joe LaPenna23d681b2015-08-27 15:12:11 -0700940 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700941 if (mMotionSensor == null) {
Joe LaPenna23d681b2015-08-27 15:12:11 -0700942 // As a last ditch, fall back to SMD.
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700943 mMotionSensor = mSensorManager.getDefaultSensor(
944 Sensor.TYPE_SIGNIFICANT_MOTION, true);
Joe LaPenna23d681b2015-08-27 15:12:11 -0700945 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700946
Joe LaPenna23d681b2015-08-27 15:12:11 -0700947 if (getContext().getResources().getBoolean(
948 com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
949 mLocationManager = (LocationManager) getContext().getSystemService(
950 Context.LOCATION_SERVICE);
951 mLocationRequest = new LocationRequest()
952 .setQuality(LocationRequest.ACCURACY_FINE)
953 .setInterval(0)
954 .setFastestInterval(0)
955 .setNumUpdates(1);
956 }
957
958 float angleThreshold = getContext().getResources().getInteger(
959 com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700960 mAnyMotionDetector = new AnyMotionDetector(
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700961 (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
Joe LaPenna23d681b2015-08-27 15:12:11 -0700962 mHandler, mSensorManager, this, angleThreshold);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700963
964 Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
965 .setPackage("android")
966 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
967 mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
968
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700969 Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)
970 .setPackage("android")
971 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
972 mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
973
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700974 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700975 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
976 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700977
978 IntentFilter filter = new IntentFilter();
979 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
980 filter.addAction(ACTION_STEP_IDLE_STATE);
981 getContext().registerReceiver(mReceiver, filter);
982
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700983 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700984
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700985 mDisplayManager.registerDisplayListener(mDisplayListener, null);
986 updateDisplayLocked();
987 }
988 }
989 }
990
991 public boolean addPowerSaveWhitelistAppInternal(String name) {
992 synchronized (this) {
993 try {
994 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0);
995 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
996 reportPowerSaveWhitelistChangedLocked();
997 updateWhitelistAppIdsLocked();
998 writeConfigFileLocked();
999 }
1000 return true;
1001 } catch (PackageManager.NameNotFoundException e) {
1002 return false;
1003 }
1004 }
1005 }
1006
1007 public boolean removePowerSaveWhitelistAppInternal(String name) {
1008 synchronized (this) {
1009 if (mPowerSaveWhitelistUserApps.remove(name) != null) {
1010 reportPowerSaveWhitelistChangedLocked();
1011 updateWhitelistAppIdsLocked();
1012 writeConfigFileLocked();
1013 return true;
1014 }
1015 }
1016 return false;
1017 }
1018
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001019 public String[] getSystemPowerWhitelistExceptIdleInternal() {
1020 synchronized (this) {
1021 int size = mPowerSaveWhitelistAppsExceptIdle.size();
1022 String[] apps = new String[size];
1023 for (int i = 0; i < size; i++) {
1024 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1025 }
1026 return apps;
1027 }
1028 }
1029
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001030 public String[] getSystemPowerWhitelistInternal() {
1031 synchronized (this) {
1032 int size = mPowerSaveWhitelistApps.size();
1033 String[] apps = new String[size];
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001034 for (int i = 0; i < size; i++) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001035 apps[i] = mPowerSaveWhitelistApps.keyAt(i);
1036 }
1037 return apps;
1038 }
1039 }
1040
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001041 public String[] getFullPowerWhitelistExceptIdleInternal() {
1042 synchronized (this) {
1043 int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
1044 String[] apps = new String[size];
1045 int cur = 0;
1046 for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
1047 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1048 cur++;
1049 }
1050 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1051 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1052 cur++;
1053 }
1054 return apps;
1055 }
1056 }
1057
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001058 public String[] getFullPowerWhitelistInternal() {
1059 synchronized (this) {
1060 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
1061 String[] apps = new String[size];
1062 int cur = 0;
1063 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
1064 apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
1065 cur++;
1066 }
1067 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1068 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1069 cur++;
1070 }
1071 return apps;
1072 }
1073 }
1074
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001075 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
1076 synchronized (this) {
1077 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
1078 || mPowerSaveWhitelistUserApps.containsKey(packageName);
1079 }
1080 }
1081
Amith Yamasani06bf8242015-05-08 16:36:21 -07001082 public boolean isPowerSaveWhitelistAppInternal(String packageName) {
1083 synchronized (this) {
1084 return mPowerSaveWhitelistApps.containsKey(packageName)
1085 || mPowerSaveWhitelistUserApps.containsKey(packageName);
1086 }
1087 }
1088
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001089 public int[] getAppIdWhitelistExceptIdleInternal() {
1090 synchronized (this) {
1091 return mPowerSaveWhitelistExceptIdleAppIdArray;
1092 }
1093 }
1094
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001095 public int[] getAppIdWhitelistInternal() {
1096 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001097 return mPowerSaveWhitelistAllAppIdArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001098 }
1099 }
1100
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001101 public int[] getAppIdTempWhitelistInternal() {
1102 synchronized (this) {
1103 return mTempWhitelistAppIdArray;
1104 }
1105 }
1106
1107 /**
1108 * Adds an app to the temporary whitelist and resets the endTime for granting the
1109 * app an exemption to access network and acquire wakelocks.
1110 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001111 public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001112 long duration, int userId, boolean sync, String reason) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001113 try {
1114 int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
1115 int appId = UserHandle.getAppId(uid);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001116 addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001117 } catch (NameNotFoundException e) {
1118 }
1119 }
1120
Dianne Hackborna750a632015-06-16 17:18:23 -07001121 /**
1122 * Adds an app to the temporary whitelist and resets the endTime for granting the
1123 * app an exemption to access network and acquire wakelocks.
1124 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001125 public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001126 long duration, boolean sync, String reason) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001127 final long timeNow = SystemClock.elapsedRealtime();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001128 Runnable networkPolicyTempWhitelistCallback = null;
Dianne Hackborna750a632015-06-16 17:18:23 -07001129 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001130 int callingAppId = UserHandle.getAppId(callingUid);
1131 if (callingAppId >= Process.FIRST_APPLICATION_UID) {
1132 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
1133 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
1134 + " is not on whitelist");
1135 }
1136 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001137 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001138 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
1139 final boolean newEntry = entry == null;
Dianne Hackborna750a632015-06-16 17:18:23 -07001140 // Set the new end time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001141 if (newEntry) {
1142 entry = new Pair<>(new MutableLong(0), reason);
1143 mTempWhitelistAppIdEndTimes.put(appId, entry);
1144 }
1145 entry.first.value = timeNow + duration;
Dianne Hackborna750a632015-06-16 17:18:23 -07001146 if (DEBUG) {
1147 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
1148 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001149 if (newEntry) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001150 // No pending timeout for the app id, post a delayed message
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001151 try {
1152 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
1153 reason, appId);
1154 } catch (RemoteException e) {
1155 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001156 postTempActiveTimeoutMessage(appId, duration);
1157 updateTempWhitelistAppIdsLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001158 if (mNetworkPolicyTempWhitelistCallback != null) {
1159 if (!sync) {
1160 mHandler.post(mNetworkPolicyTempWhitelistCallback);
1161 } else {
1162 networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
1163 }
1164 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001165 reportTempWhitelistChangedLocked();
1166 }
1167 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001168 if (networkPolicyTempWhitelistCallback != null) {
1169 networkPolicyTempWhitelistCallback.run();
1170 }
1171 }
1172
1173 public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
1174 synchronized (this) {
1175 mNetworkPolicyTempWhitelistCallback = callback;
1176 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001177 }
1178
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001179 private void postTempActiveTimeoutMessage(int uid, long delay) {
1180 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
1181 delay);
1182 }
1183
1184 void checkTempAppWhitelistTimeout(int uid) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001185 final long timeNow = SystemClock.elapsedRealtime();
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001186 synchronized (this) {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001187 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
1188 if (entry == null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001189 // Nothing to do
1190 return;
1191 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001192 if (timeNow >= entry.first.value) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001193 mTempWhitelistAppIdEndTimes.delete(uid);
1194 if (DEBUG) {
1195 Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
1196 }
1197 updateTempWhitelistAppIdsLocked();
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001198 if (mNetworkPolicyTempWhitelistCallback != null) {
1199 mHandler.post(mNetworkPolicyTempWhitelistCallback);
1200 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001201 reportTempWhitelistChangedLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001202 try {
1203 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
1204 entry.second, uid);
1205 } catch (RemoteException e) {
1206 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001207 } else {
1208 // Need more time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001209 postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001210 }
1211 }
1212 }
1213
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001214 public void exitIdleInternal(String reason) {
1215 synchronized (this) {
1216 becomeActiveLocked(reason, Binder.getCallingUid());
1217 }
1218 }
1219
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001220 void updateDisplayLocked() {
1221 mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
1222 // We consider any situation where the display is showing something to be it on,
1223 // because if there is anything shown we are going to be updating it at some
1224 // frequency so can't be allowed to go into deep sleeps.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001225 boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001226 if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001227 if (!screenOn && mScreenOn) {
1228 mScreenOn = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001229 if (!mForceIdle) {
1230 becomeInactiveIfAppropriateLocked();
1231 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001232 } else if (screenOn) {
1233 mScreenOn = true;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001234 if (!mForceIdle) {
1235 becomeActiveLocked("screen", Process.myUid());
1236 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001237 }
1238 }
1239
1240 void updateChargingLocked(boolean charging) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001241 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001242 if (!charging && mCharging) {
1243 mCharging = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001244 if (!mForceIdle) {
1245 becomeInactiveIfAppropriateLocked();
1246 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001247 } else if (charging) {
1248 mCharging = charging;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001249 if (!mForceIdle) {
1250 becomeActiveLocked("charging", Process.myUid());
1251 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001252 }
1253 }
1254
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001255 void scheduleReportActiveLocked(String activeReason, int activeUid) {
1256 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
1257 mState == STATE_IDLE ? 1 : 0, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001258 mHandler.sendMessage(msg);
1259 }
1260
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001261 void becomeActiveLocked(String activeReason, int activeUid) {
1262 if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001263 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001264 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
1265 scheduleReportActiveLocked(activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001266 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -07001267 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001268 resetIdleManagementLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001269 }
1270 }
1271
1272 void becomeInactiveIfAppropriateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001273 if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001274 if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001275 // Screen has turned off; we are now going to become inactive and start
1276 // waiting to see if we will ultimately go idle.
1277 mState = STATE_INACTIVE;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001278 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001279 resetIdleManagementLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001280 scheduleAlarmLocked(mInactiveTimeout, false);
1281 EventLogTags.writeDeviceIdle(mState, "no activity");
1282 }
1283 }
1284
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001285 void resetIdleManagementLocked() {
1286 mNextIdlePendingDelay = 0;
1287 mNextIdleDelay = 0;
1288 cancelAlarmLocked();
1289 cancelSensingAlarmLocked();
1290 cancelLocatingLocked();
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001291 stopMonitoringMotionLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001292 mAnyMotionDetector.stop();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001293 }
1294
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001295 void exitForceIdleLocked() {
1296 if (mForceIdle) {
1297 mForceIdle = false;
1298 if (mScreenOn || mCharging) {
1299 becomeActiveLocked("exit-force-idle", Process.myUid());
1300 }
1301 }
1302 }
1303
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001304 void stepIdleStateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001305 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001306 EventLogTags.writeDeviceIdleStep();
1307
1308 final long now = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001309 if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001310 // Whoops, there is an upcoming alarm. We don't actually want to go idle.
1311 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001312 becomeActiveLocked("alarm", Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001313 }
1314 return;
1315 }
1316
1317 switch (mState) {
1318 case STATE_INACTIVE:
1319 // We have now been inactive long enough, it is time to start looking
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001320 // for motion and sleep some more while doing so.
1321 startMonitoringMotionLocked();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001322 scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001323 // Reset the upcoming idle delays.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001324 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
1325 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001326 mState = STATE_IDLE_PENDING;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001327 if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001328 EventLogTags.writeDeviceIdle(mState, "step");
1329 break;
1330 case STATE_IDLE_PENDING:
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001331 mState = STATE_SENSING;
1332 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001333 EventLogTags.writeDeviceIdle(mState, "step");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001334 scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001335 cancelSensingAlarmLocked();
1336 cancelLocatingLocked();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001337 mAnyMotionDetector.checkForAnyMotion();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001338 mNotMoving = false;
1339 mLocated = false;
1340 mLastGenericLocation = null;
1341 mLastGpsLocation = null;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001342 break;
1343 case STATE_SENSING:
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001344 mState = STATE_LOCATING;
1345 if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
1346 EventLogTags.writeDeviceIdle(mState, "step");
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001347 cancelSensingAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001348 scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001349 if (mLocationManager != null
1350 && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
1351 mLocationManager.requestLocationUpdates(mLocationRequest,
1352 mGenericLocationListener, mHandler.getLooper());
1353 mLocating = true;
1354 } else {
1355 mHasNetworkLocation = false;
1356 }
1357 if (mLocationManager != null
1358 && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
1359 mHasGps = true;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001360 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
1361 mGpsLocationListener, mHandler.getLooper());
Joe LaPenna23d681b2015-08-27 15:12:11 -07001362 mLocating = true;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001363 } else {
Joe LaPenna23d681b2015-08-27 15:12:11 -07001364 mHasGps = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001365 }
Joe LaPenna23d681b2015-08-27 15:12:11 -07001366 // If we have a location provider, we're all set, the listeners will move state
1367 // forward.
1368 if (mLocating) {
1369 break;
1370 }
1371
1372 // Otherwise, we have to move from locating into idle maintenance.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001373 case STATE_LOCATING:
1374 cancelSensingAlarmLocked();
1375 cancelLocatingLocked();
1376 mAnyMotionDetector.stop();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001377 case STATE_IDLE_MAINTENANCE:
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001378 scheduleAlarmLocked(mNextIdleDelay, true);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001379 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
1380 " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001381 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001382 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001383 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001384 mState = STATE_IDLE;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001385 EventLogTags.writeDeviceIdle(mState, "step");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001386 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
1387 break;
1388 case STATE_IDLE:
1389 // We have been idling long enough, now it is time to do some work.
1390 scheduleAlarmLocked(mNextIdlePendingDelay, false);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001391 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
1392 "Next alarm in " + mNextIdlePendingDelay + " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001393 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
1394 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001395 mState = STATE_IDLE_MAINTENANCE;
1396 EventLogTags.writeDeviceIdle(mState, "step");
1397 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1398 break;
1399 }
1400 }
1401
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001402 void motionLocked() {
1403 if (DEBUG) Slog.d(TAG, "motionLocked()");
1404 // The motion sensor will have been disabled at this point
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001405 handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
1406 }
1407
1408 void handleMotionDetectedLocked(long timeout, String type) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001409 // The device is not yet active, so we want to go back to the pending idle
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001410 // state to wait again for no motion. Note that we only monitor for motion
1411 // after moving out of the inactive state, so no need to worry about that.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001412 if (mState != STATE_ACTIVE) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001413 scheduleReportActiveLocked(type, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001414 mState = STATE_ACTIVE;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001415 mInactiveTimeout = timeout;
1416 EventLogTags.writeDeviceIdle(mState, type);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001417 becomeInactiveIfAppropriateLocked();
1418 }
1419 }
1420
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001421 void receivedGenericLocationLocked(Location location) {
1422 if (mState != STATE_LOCATING) {
1423 cancelLocatingLocked();
1424 return;
1425 }
1426 if (DEBUG) Slog.d(TAG, "Generic location: " + location);
1427 mLastGenericLocation = new Location(location);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001428 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001429 return;
1430 }
1431 mLocated = true;
1432 if (mNotMoving) {
1433 stepIdleStateLocked();
1434 }
1435 }
1436
1437 void receivedGpsLocationLocked(Location location) {
1438 if (mState != STATE_LOCATING) {
1439 cancelLocatingLocked();
1440 return;
1441 }
1442 if (DEBUG) Slog.d(TAG, "GPS location: " + location);
1443 mLastGpsLocation = new Location(location);
1444 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
1445 return;
1446 }
1447 mLocated = true;
1448 if (mNotMoving) {
1449 stepIdleStateLocked();
1450 }
1451 }
1452
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001453 void startMonitoringMotionLocked() {
1454 if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()");
1455 if (mMotionSensor != null && !mMotionListener.active) {
1456 mMotionListener.registerLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001457 }
1458 }
1459
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001460 void stopMonitoringMotionLocked() {
1461 if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()");
1462 if (mMotionSensor != null && mMotionListener.active) {
1463 mMotionListener.unregisterLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001464 }
1465 }
1466
1467 void cancelAlarmLocked() {
1468 if (mNextAlarmTime != 0) {
1469 mNextAlarmTime = 0;
1470 mAlarmManager.cancel(mAlarmIntent);
1471 }
1472 }
1473
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001474 void cancelSensingAlarmLocked() {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001475 if (mSensing) {
1476 if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
1477 mAlarmManager.cancel(mSensingAlarmIntent);
1478 mSensing = false;
1479 }
1480 }
1481
1482 void cancelLocatingLocked() {
1483 if (mLocating) {
1484 mLocationManager.removeUpdates(mGenericLocationListener);
1485 mLocationManager.removeUpdates(mGpsLocationListener);
1486 mLocating = false;
1487 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001488 }
1489
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001490 void scheduleAlarmLocked(long delay, boolean idleUntil) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001491 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001492 if (mMotionSensor == null) {
Joe LaPenna23d681b2015-08-27 15:12:11 -07001493 // If there is no motion sensor on this device, then we won't schedule
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001494 // alarms, because we can't determine if the device is not moving. This effectively
Joe LaPenna23d681b2015-08-27 15:12:11 -07001495 // turns off normal execution of device idling, although it is still possible to
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001496 // manually poke it by pretending like the alarm is going off.
1497 return;
1498 }
1499 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1500 if (idleUntil) {
1501 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1502 mNextAlarmTime, mAlarmIntent);
1503 } else {
1504 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1505 mNextAlarmTime, mAlarmIntent);
1506 }
1507 }
1508
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001509 void scheduleSensingAlarmLocked(long delay) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001510 if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
1511 cancelSensingAlarmLocked();
1512 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1513 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1514 mNextAlarmTime, mSensingAlarmIntent);
1515 mSensing = true;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001516 }
1517
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001518 private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
1519 ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
1520 outAppIds.clear();
1521 for (int i=0; i<systemApps.size(); i++) {
1522 outAppIds.put(systemApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001523 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001524 for (int i=0; i<userApps.size(); i++) {
1525 outAppIds.put(userApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001526 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001527 int size = outAppIds.size();
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001528 int[] appids = new int[size];
1529 for (int i = 0; i < size; i++) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001530 appids[i] = outAppIds.keyAt(i);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001531 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001532 return appids;
1533 }
1534
1535 private void updateWhitelistAppIdsLocked() {
1536 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
1537 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
1538 mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
1539 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001540 if (mLocalPowerManager != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001541 if (DEBUG) {
1542 Slog.d(TAG, "Setting wakelock whitelist to "
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001543 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001544 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001545 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001546 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001547 }
1548
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001549 private void updateTempWhitelistAppIdsLocked() {
1550 final int size = mTempWhitelistAppIdEndTimes.size();
1551 if (mTempWhitelistAppIdArray.length != size) {
1552 mTempWhitelistAppIdArray = new int[size];
1553 }
1554 for (int i = 0; i < size; i++) {
1555 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
1556 }
1557 if (mLocalPowerManager != null) {
1558 if (DEBUG) {
1559 Slog.d(TAG, "Setting wakelock temp whitelist to "
1560 + Arrays.toString(mTempWhitelistAppIdArray));
1561 }
1562 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
1563 }
1564 }
1565
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001566 private void reportPowerSaveWhitelistChangedLocked() {
1567 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
1568 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Xiaohui Chene4de5a02015-09-22 15:33:31 -07001569 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001570 }
1571
1572 private void reportTempWhitelistChangedLocked() {
1573 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
1574 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Xiaohui Chene4de5a02015-09-22 15:33:31 -07001575 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001576 }
1577
1578 void readConfigFileLocked() {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001579 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001580 mPowerSaveWhitelistUserApps.clear();
1581 FileInputStream stream;
1582 try {
1583 stream = mConfigFile.openRead();
1584 } catch (FileNotFoundException e) {
1585 return;
1586 }
1587 try {
1588 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001589 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001590 readConfigFileLocked(parser);
1591 } catch (XmlPullParserException e) {
1592 } finally {
1593 try {
1594 stream.close();
1595 } catch (IOException e) {
1596 }
1597 }
1598
1599 }
1600
1601 private void readConfigFileLocked(XmlPullParser parser) {
1602 final PackageManager pm = getContext().getPackageManager();
1603
1604 try {
1605 int type;
1606 while ((type = parser.next()) != XmlPullParser.START_TAG
1607 && type != XmlPullParser.END_DOCUMENT) {
1608 ;
1609 }
1610
1611 if (type != XmlPullParser.START_TAG) {
1612 throw new IllegalStateException("no start tag found");
1613 }
1614
1615 int outerDepth = parser.getDepth();
1616 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1617 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1618 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1619 continue;
1620 }
1621
1622 String tagName = parser.getName();
1623 if (tagName.equals("wl")) {
1624 String name = parser.getAttributeValue(null, "n");
1625 if (name != null) {
1626 try {
1627 ApplicationInfo ai = pm.getApplicationInfo(name, 0);
1628 mPowerSaveWhitelistUserApps.put(ai.packageName,
1629 UserHandle.getAppId(ai.uid));
1630 } catch (PackageManager.NameNotFoundException e) {
1631 }
1632 }
1633 } else {
1634 Slog.w(TAG, "Unknown element under <config>: "
1635 + parser.getName());
1636 XmlUtils.skipCurrentTag(parser);
1637 }
1638 }
1639
1640 } catch (IllegalStateException e) {
1641 Slog.w(TAG, "Failed parsing config " + e);
1642 } catch (NullPointerException e) {
1643 Slog.w(TAG, "Failed parsing config " + e);
1644 } catch (NumberFormatException e) {
1645 Slog.w(TAG, "Failed parsing config " + e);
1646 } catch (XmlPullParserException e) {
1647 Slog.w(TAG, "Failed parsing config " + e);
1648 } catch (IOException e) {
1649 Slog.w(TAG, "Failed parsing config " + e);
1650 } catch (IndexOutOfBoundsException e) {
1651 Slog.w(TAG, "Failed parsing config " + e);
1652 }
1653 }
1654
1655 void writeConfigFileLocked() {
1656 mHandler.removeMessages(MSG_WRITE_CONFIG);
1657 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
1658 }
1659
1660 void handleWriteConfigFile() {
1661 final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
1662
1663 try {
1664 synchronized (this) {
1665 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001666 out.setOutput(memStream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001667 writeConfigFileLocked(out);
1668 }
1669 } catch (IOException e) {
1670 }
1671
1672 synchronized (mConfigFile) {
1673 FileOutputStream stream = null;
1674 try {
1675 stream = mConfigFile.startWrite();
1676 memStream.writeTo(stream);
1677 stream.flush();
1678 FileUtils.sync(stream);
1679 stream.close();
1680 mConfigFile.finishWrite(stream);
1681 } catch (IOException e) {
1682 Slog.w(TAG, "Error writing config file", e);
1683 mConfigFile.failWrite(stream);
1684 }
1685 }
1686 }
1687
1688 void writeConfigFileLocked(XmlSerializer out) throws IOException {
1689 out.startDocument(null, true);
1690 out.startTag(null, "config");
1691 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
1692 String name = mPowerSaveWhitelistUserApps.keyAt(i);
1693 out.startTag(null, "wl");
1694 out.attribute(null, "n", name);
1695 out.endTag(null, "wl");
1696 }
1697 out.endTag(null, "config");
1698 out.endDocument();
1699 }
1700
1701 private void dumpHelp(PrintWriter pw) {
1702 pw.println("Device idle controller (deviceidle) dump options:");
1703 pw.println(" [-h] [CMD]");
1704 pw.println(" -h: print this help text.");
1705 pw.println("Commands:");
1706 pw.println(" step");
1707 pw.println(" Immediately step to next state, without waiting for alarm.");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001708 pw.println(" force-idle");
1709 pw.println(" Force directly into idle mode, regardless of other device state.");
1710 pw.println(" Use \"step\" to get out.");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001711 pw.println(" disable");
1712 pw.println(" Completely disable device idle mode.");
1713 pw.println(" enable");
1714 pw.println(" Re-enable device idle mode after it had previously been disabled.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001715 pw.println(" enabled");
1716 pw.println(" Print 1 if device idle mode is currently enabled, else 0.");
Dianne Hackborn1b139682015-07-06 15:13:37 -07001717 pw.println(" whitelist");
1718 pw.println(" Print currently whitelisted apps.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001719 pw.println(" whitelist [package ...]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001720 pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001721 pw.println(" tempwhitelist [package ..]");
1722 pw.println(" Temporarily place packages in whitelist for 10 seconds.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001723 }
1724
1725 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1726 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1727 != PackageManager.PERMISSION_GRANTED) {
1728 pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
1729 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1730 + " without permission " + android.Manifest.permission.DUMP);
1731 return;
1732 }
1733
1734 if (args != null) {
Xiaohui Chen7c696362015-09-16 09:56:14 -07001735 int userId = UserHandle.USER_SYSTEM;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001736 for (int i=0; i<args.length; i++) {
1737 String arg = args[i];
1738 if ("-h".equals(arg)) {
1739 dumpHelp(pw);
1740 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001741 } else if ("-u".equals(arg)) {
1742 i++;
1743 if (i < args.length) {
1744 arg = args[i];
1745 userId = Integer.parseInt(arg);
1746 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001747 } else if ("-a".equals(arg)) {
1748 // Ignore, we always dump all.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001749 } else if ("step".equals(arg)) {
1750 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001751 long token = Binder.clearCallingIdentity();
1752 try {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001753 exitForceIdleLocked();
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001754 stepIdleStateLocked();
1755 pw.print("Stepped to: "); pw.println(stateToString(mState));
1756 } finally {
1757 Binder.restoreCallingIdentity(token);
1758 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001759 }
1760 return;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001761 } else if ("force-idle".equals(arg)) {
1762 synchronized (this) {
1763 long token = Binder.clearCallingIdentity();
1764 try {
1765 if (!mEnabled) {
1766 pw.println("Unable to go idle; not enabled");
1767 return;
1768 }
1769 mForceIdle = true;
1770 becomeInactiveIfAppropriateLocked();
1771 int curState = mState;
1772 while (curState != STATE_IDLE) {
1773 stepIdleStateLocked();
1774 if (curState == mState) {
1775 pw.print("Unable to go idle; stopped at ");
1776 pw.println(stateToString(mState));
1777 exitForceIdleLocked();
1778 return;
1779 }
1780 curState = mState;
1781 }
1782 pw.println("Now forced in to idle mode");
1783 } finally {
1784 Binder.restoreCallingIdentity(token);
1785 }
1786 }
1787 return;
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001788 } else if ("disable".equals(arg)) {
1789 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001790 long token = Binder.clearCallingIdentity();
1791 try {
1792 if (mEnabled) {
1793 mEnabled = false;
1794 becomeActiveLocked("disabled", Process.myUid());
1795 pw.println("Idle mode disabled");
1796 }
1797 } finally {
1798 Binder.restoreCallingIdentity(token);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001799 }
1800 }
1801 return;
1802 } else if ("enable".equals(arg)) {
1803 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001804 long token = Binder.clearCallingIdentity();
1805 try {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001806 exitForceIdleLocked();
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001807 if (!mEnabled) {
1808 mEnabled = true;
1809 becomeInactiveIfAppropriateLocked();
1810 pw.println("Idle mode enabled");
1811 }
1812 } finally {
1813 Binder.restoreCallingIdentity(token);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001814 }
1815 }
1816 return;
Dianne Hackborn92617032015-06-19 15:32:19 -07001817 } else if ("enabled".equals(arg)) {
1818 synchronized (this) {
1819 pw.println(mEnabled ? "1" : " 0");
1820 }
1821 return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001822 } else if ("whitelist".equals(arg)) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001823 long token = Binder.clearCallingIdentity();
1824 try {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001825 i++;
Dianne Hackborn1b139682015-07-06 15:13:37 -07001826 if (i < args.length) {
1827 while (i < args.length) {
1828 arg = args[i];
1829 i++;
1830 if (arg.length() < 1 || (arg.charAt(0) != '-'
1831 && arg.charAt(0) != '+')) {
1832 pw.println("Package must be prefixed with + or -: " + arg);
1833 return;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001834 }
Dianne Hackborn1b139682015-07-06 15:13:37 -07001835 char op = arg.charAt(0);
1836 String pkg = arg.substring(1);
1837 if (op == '+') {
1838 if (addPowerSaveWhitelistAppInternal(pkg)) {
1839 pw.println("Added: " + pkg);
1840 } else {
1841 pw.println("Unknown package: " + pkg);
1842 }
1843 } else {
1844 if (removePowerSaveWhitelistAppInternal(pkg)) {
1845 pw.println("Removed: " + pkg);
1846 }
1847 }
1848 }
1849 } else {
1850 synchronized (this) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001851 for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
1852 pw.print("system-excidle,");
1853 pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
1854 pw.print(",");
1855 pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
1856 }
Dianne Hackborn1b139682015-07-06 15:13:37 -07001857 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
1858 pw.print("system,");
1859 pw.print(mPowerSaveWhitelistApps.keyAt(j));
1860 pw.print(",");
1861 pw.println(mPowerSaveWhitelistApps.valueAt(j));
1862 }
1863 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
1864 pw.print("user,");
1865 pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
1866 pw.print(",");
1867 pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001868 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001869 }
1870 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001871 } finally {
1872 Binder.restoreCallingIdentity(token);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001873 }
1874 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001875 } else if ("tempwhitelist".equals(arg)) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001876 long token = Binder.clearCallingIdentity();
1877 try {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001878 i++;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001879 if (i >= args.length) {
1880 pw.println("At least one package name must be specified");
1881 return;
1882 }
1883 while (i < args.length) {
1884 arg = args[i];
1885 i++;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001886 addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId, true,
1887 "shell");
1888 pw.println("Added: " + arg);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001889 }
1890 } finally {
1891 Binder.restoreCallingIdentity(token);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001892 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001893 return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001894 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
1895 pw.println("Unknown option: " + arg);
1896 return;
1897 } else {
1898 pw.println("Unknown command: " + arg);
1899 return;
1900 }
1901 }
1902 }
1903
1904 synchronized (this) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001905 mConstants.dump(pw);
1906
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001907 int size = mPowerSaveWhitelistAppsExceptIdle.size();
1908 if (size > 0) {
1909 pw.println(" Whitelist (except idle) system apps:");
1910 for (int i = 0; i < size; i++) {
1911 pw.print(" ");
1912 pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
1913 }
1914 }
1915 size = mPowerSaveWhitelistApps.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001916 if (size > 0) {
1917 pw.println(" Whitelist system apps:");
1918 for (int i = 0; i < size; i++) {
1919 pw.print(" ");
1920 pw.println(mPowerSaveWhitelistApps.keyAt(i));
1921 }
1922 }
1923 size = mPowerSaveWhitelistUserApps.size();
1924 if (size > 0) {
1925 pw.println(" Whitelist user apps:");
1926 for (int i = 0; i < size; i++) {
1927 pw.print(" ");
1928 pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
1929 }
1930 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001931 size = mPowerSaveWhitelistExceptIdleAppIds.size();
1932 if (size > 0) {
1933 pw.println(" Whitelist (except idle) all app ids:");
1934 for (int i = 0; i < size; i++) {
1935 pw.print(" ");
1936 pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
1937 pw.println();
1938 }
1939 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001940 size = mPowerSaveWhitelistAllAppIds.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001941 if (size > 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001942 pw.println(" Whitelist all app ids:");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001943 for (int i = 0; i < size; i++) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001944 pw.print(" ");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001945 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001946 pw.println();
1947 }
1948 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001949 size = mTempWhitelistAppIdEndTimes.size();
1950 if (size > 0) {
1951 pw.println(" Temp whitelist schedule:");
1952 final long timeNow = SystemClock.elapsedRealtime();
1953 for (int i = 0; i < size; i++) {
1954 pw.print(" UID=");
1955 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
1956 pw.print(": ");
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001957 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
1958 TimeUtils.formatDuration(entry.first.value, timeNow, pw);
1959 pw.print(" - ");
1960 pw.println(entry.second);
Dianne Hackborna750a632015-06-16 17:18:23 -07001961 }
1962 }
1963 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
1964 if (size > 0) {
1965 pw.println(" Temp whitelist app ids:");
1966 for (int i = 0; i < size; i++) {
1967 pw.print(" ");
1968 pw.print(mTempWhitelistAppIdArray[i]);
1969 pw.println();
1970 }
1971 }
Adam Lesinski31c05d12015-06-09 17:34:04 -07001972
Dianne Hackborn92617032015-06-19 15:32:19 -07001973 pw.print(" mEnabled="); pw.println(mEnabled);
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001974 pw.print(" mForceIdle="); pw.println(mForceIdle);
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001975 pw.print(" mMotionSensor="); pw.println(mMotionSensor);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001976 pw.print(" mCurDisplay="); pw.println(mCurDisplay);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001977 pw.print(" mScreenOn="); pw.println(mScreenOn);
1978 pw.print(" mCharging="); pw.println(mCharging);
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001979 pw.print(" mMotionActive="); pw.println(mMotionListener.active);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001980 pw.print(" mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
1981 pw.println(mNotMoving);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001982 pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
1983 pw.print(mHasGps); pw.print(" mHasNetwork=");
1984 pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001985 if (mLastGenericLocation != null) {
1986 pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation);
1987 }
1988 if (mLastGpsLocation != null) {
1989 pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation);
1990 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001991 pw.print(" mState="); pw.println(stateToString(mState));
1992 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
1993 pw.println();
1994 if (mNextAlarmTime != 0) {
1995 pw.print(" mNextAlarmTime=");
1996 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
1997 pw.println();
1998 }
1999 if (mNextIdlePendingDelay != 0) {
2000 pw.print(" mNextIdlePendingDelay=");
2001 TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
2002 pw.println();
2003 }
2004 if (mNextIdleDelay != 0) {
2005 pw.print(" mNextIdleDelay=");
2006 TimeUtils.formatDuration(mNextIdleDelay, pw);
2007 pw.println();
2008 }
2009 }
2010 }
2011}