blob: 80fd4419a821a963ace63a706eb3bd700191b3bc [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;
34import android.hardware.TriggerEvent;
35import android.hardware.TriggerEventListener;
36import android.hardware.display.DisplayManager;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -070037import android.location.LocationRequest;
38import android.location.Location;
39import android.location.LocationListener;
40import android.location.LocationManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070041import android.net.INetworkPolicyManager;
Adam Lesinski31c05d12015-06-09 17:34:04 -070042import android.net.Uri;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070043import android.os.BatteryStats;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070044import android.os.Binder;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -070045import android.os.Bundle;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070046import android.os.Environment;
47import android.os.FileUtils;
48import android.os.Handler;
49import android.os.IDeviceIdleController;
50import android.os.Looper;
51import android.os.Message;
52import android.os.PowerManager;
53import android.os.PowerManagerInternal;
Dianne Hackbornb6683c42015-06-18 17:40:33 -070054import android.os.Process;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070055import android.os.RemoteException;
56import android.os.ServiceManager;
57import android.os.SystemClock;
58import android.os.UserHandle;
Adam Lesinski31c05d12015-06-09 17:34:04 -070059import android.provider.Settings;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070060import android.util.ArrayMap;
61import android.util.ArraySet;
Adam Lesinski31c05d12015-06-09 17:34:04 -070062import android.util.KeyValueListParser;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070063import android.util.MutableLong;
64import android.util.Pair;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070065import android.util.Slog;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070066import android.util.SparseArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070067import android.util.SparseBooleanArray;
68import android.util.TimeUtils;
69import android.util.Xml;
70import android.view.Display;
Amith Yamasani520d8f22015-05-08 16:36:21 -070071
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070072import com.android.internal.app.IBatteryStats;
73import com.android.internal.os.AtomicFile;
74import com.android.internal.os.BackgroundThread;
75import com.android.internal.util.FastXmlSerializer;
76import com.android.internal.util.XmlUtils;
77import com.android.server.am.BatteryStatsService;
Amith Yamasani520d8f22015-05-08 16:36:21 -070078
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070079import org.xmlpull.v1.XmlPullParser;
80import org.xmlpull.v1.XmlPullParserException;
81import org.xmlpull.v1.XmlSerializer;
82
83import java.io.ByteArrayOutputStream;
84import java.io.File;
85import java.io.FileDescriptor;
86import java.io.FileInputStream;
87import java.io.FileNotFoundException;
88import java.io.FileOutputStream;
89import java.io.IOException;
90import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +010091import java.nio.charset.StandardCharsets;
Amith Yamasaniaf575b92015-05-29 15:35:26 -070092import java.util.Arrays;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070093
94/**
95 * Keeps track of device idleness and drives low power mode based on that.
96 */
Kevin Gabayan89ecf822015-05-18 12:10:07 -070097public class DeviceIdleController extends SystemService
98 implements AnyMotionDetector.DeviceIdleCallback {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070099 private static final String TAG = "DeviceIdleController";
100
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700101 private static final boolean DEBUG = false;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700102
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700103 private static final boolean COMPRESS_TIME = false;
Amith Yamasani520d8f22015-05-08 16:36:21 -0700104
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700105 private static final String ACTION_STEP_IDLE_STATE =
106 "com.android.server.device_idle.STEP_IDLE_STATE";
107
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700108 private AlarmManager mAlarmManager;
109 private IBatteryStats mBatteryStats;
110 private PowerManagerInternal mLocalPowerManager;
111 private INetworkPolicyManager mNetworkPolicyManager;
112 private DisplayManager mDisplayManager;
113 private SensorManager mSensorManager;
114 private Sensor mSigMotionSensor;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700115 private LocationManager mLocationManager;
116 private LocationRequest mLocationRequest;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700117 private PendingIntent mSensingAlarmIntent;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700118 private PendingIntent mAlarmIntent;
119 private Intent mIdleIntent;
120 private Display mCurDisplay;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700121 private AnyMotionDetector mAnyMotionDetector;
Dianne Hackborn92617032015-06-19 15:32:19 -0700122 private boolean mEnabled;
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700123 private boolean mForceIdle;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700124 private boolean mScreenOn;
125 private boolean mCharging;
126 private boolean mSigMotionActive;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700127 private boolean mSensing;
128 private boolean mNotMoving;
129 private boolean mLocating;
130 private boolean mLocated;
131 private boolean mHaveGps;
132 private Location mLastGenericLocation;
133 private Location mLastGpsLocation;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700134
135 /** Device is currently active. */
136 private static final int STATE_ACTIVE = 0;
137 /** Device is inactve (screen off, no motion) and we are waiting to for idle. */
138 private static final int STATE_INACTIVE = 1;
139 /** Device is past the initial inactive period, and waiting for the next idle period. */
140 private static final int STATE_IDLE_PENDING = 2;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700141 /** Device is currently sensing motion. */
142 private static final int STATE_SENSING = 3;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700143 /** Device is currently finding location (and may still be sensing). */
144 private static final int STATE_LOCATING = 4;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700145 /** Device is in the idle state, trying to stay asleep as much as possible. */
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700146 private static final int STATE_IDLE = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700147 /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700148 private static final int STATE_IDLE_MAINTENANCE = 6;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700149 private static String stateToString(int state) {
150 switch (state) {
151 case STATE_ACTIVE: return "ACTIVE";
152 case STATE_INACTIVE: return "INACTIVE";
153 case STATE_IDLE_PENDING: return "IDLE_PENDING";
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700154 case STATE_SENSING: return "SENSING";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700155 case STATE_LOCATING: return "LOCATING";
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700156 case STATE_IDLE: return "IDLE";
157 case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
158 default: return Integer.toString(state);
159 }
160 }
161
162 private int mState;
163
164 private long mInactiveTimeout;
165 private long mNextAlarmTime;
166 private long mNextIdlePendingDelay;
167 private long mNextIdleDelay;
168
169 public final AtomicFile mConfigFile;
170
171 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700172 * Package names the system has white-listed to opt out of power save restrictions,
173 * except for device idle mode.
174 */
175 private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
176
177 /**
178 * Package names the system has white-listed to opt out of power save restrictions for
179 * all modes.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700180 */
181 private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
182
183 /**
184 * Package names the user has white-listed to opt out of power save restrictions.
185 */
186 private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
187
188 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700189 * App IDs of built-in system apps that have been white-listed except for idle modes.
190 */
191 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
192 = new SparseBooleanArray();
193
194 /**
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700195 * App IDs of built-in system apps that have been white-listed.
196 */
197 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
198
199 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700200 * App IDs that have been white-listed to opt out of power save restrictions, except
201 * for device idle modes.
202 */
203 private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
204
205 /**
206 * Current app IDs that are in the complete power save white list, but shouldn't be
207 * excluded from idle modes. This array can be shared with others because it will not be
208 * modified once set.
209 */
210 private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
211
212 /**
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700213 * App IDs that have been white-listed to opt out of power save restrictions.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700214 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700215 private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700216
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700217 /**
218 * Current app IDs that are in the complete power save white list. This array can
219 * be shared with others because it will not be modified once set.
220 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700221 private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700222
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700223 /**
224 * List of end times for UIDs that are temporarily marked as being allowed to access
225 * the network and acquire wakelocks. Times are in milliseconds.
226 */
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700227 private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
228 = new SparseArray<>();
229
230 /**
231 * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
232 */
233 Runnable mNetworkPolicyTempWhitelistCallback;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700234
235 /**
236 * Current app IDs of temporarily whitelist apps for high-priority messages.
237 */
238 private int[] mTempWhitelistAppIdArray = new int[0];
239
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700240 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
241 @Override public void onReceive(Context context, Intent intent) {
242 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
243 int plugged = intent.getIntExtra("plugged", 0);
244 updateChargingLocked(plugged != 0);
245 } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
246 synchronized (DeviceIdleController.this) {
247 stepIdleStateLocked();
248 }
249 }
250 }
251 };
252
253 private final DisplayManager.DisplayListener mDisplayListener
254 = new DisplayManager.DisplayListener() {
255 @Override public void onDisplayAdded(int displayId) {
256 }
257
258 @Override public void onDisplayRemoved(int displayId) {
259 }
260
261 @Override public void onDisplayChanged(int displayId) {
262 if (displayId == Display.DEFAULT_DISPLAY) {
263 synchronized (DeviceIdleController.this) {
264 updateDisplayLocked();
265 }
266 }
267 }
268 };
269
270 private final TriggerEventListener mSigMotionListener = new TriggerEventListener() {
271 @Override public void onTrigger(TriggerEvent event) {
272 synchronized (DeviceIdleController.this) {
273 significantMotionLocked();
274 }
275 }
276 };
277
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700278 private final LocationListener mGenericLocationListener = new LocationListener() {
279 @Override
280 public void onLocationChanged(Location location) {
281 synchronized (DeviceIdleController.this) {
282 receivedGenericLocationLocked(location);
283 }
284 }
285
286 @Override
287 public void onStatusChanged(String provider, int status, Bundle extras) {
288 }
289
290 @Override
291 public void onProviderEnabled(String provider) {
292 }
293
294 @Override
295 public void onProviderDisabled(String provider) {
296 }
297 };
298
299 private final LocationListener mGpsLocationListener = new LocationListener() {
300 @Override
301 public void onLocationChanged(Location location) {
302 synchronized (DeviceIdleController.this) {
303 receivedGpsLocationLocked(location);
304 }
305 }
306
307 @Override
308 public void onStatusChanged(String provider, int status, Bundle extras) {
309 }
310
311 @Override
312 public void onProviderEnabled(String provider) {
313 }
314
315 @Override
316 public void onProviderDisabled(String provider) {
317 }
318 };
319
Adam Lesinski31c05d12015-06-09 17:34:04 -0700320 /**
321 * All times are in milliseconds. These constants are kept synchronized with the system
322 * global Settings. Any access to this class or its fields should be done while
323 * holding the DeviceIdleController lock.
324 */
Dianne Hackborna750a632015-06-16 17:18:23 -0700325 private final class Constants extends ContentObserver {
Adam Lesinski31c05d12015-06-09 17:34:04 -0700326 // Key names stored in the settings value.
327 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
328 private static final String KEY_SENSING_TIMEOUT = "sensing_to";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700329 private static final String KEY_LOCATING_TIMEOUT = "locating_to";
330 private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700331 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
332 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
333 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
334 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
335 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
336 private static final String KEY_IDLE_TIMEOUT = "idle_to";
337 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
338 private static final String KEY_IDLE_FACTOR = "idle_factor";
339 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
340 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
341 "max_temp_app_whitelist_duration";
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700342 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
343 "mms_temp_app_whitelist_duration";
Dianne Hackborn451c3462015-07-21 17:39:46 -0700344 private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
345 "sms_temp_app_whitelist_duration";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700346
347 /**
348 * This is the time, after becoming inactive, at which we start looking at the
349 * motion sensor to determine if the device is being left alone. We don't do this
350 * immediately after going inactive just because we don't want to be continually running
351 * the significant motion sensor whenever the screen is off.
352 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
353 * @see #KEY_INACTIVE_TIMEOUT
354 */
355 public long INACTIVE_TIMEOUT;
356
357 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700358 * If we don't receive a callback from AnyMotion in this amount of time +
359 * {@link #LOCATING_TIMEOUT}, we will change from
Adam Lesinski31c05d12015-06-09 17:34:04 -0700360 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
361 * will be ignored.
362 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
363 * @see #KEY_SENSING_TIMEOUT
364 */
365 public long SENSING_TIMEOUT;
366
367 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700368 * This is how long we will wait to try to get a good location fix before going in to
369 * idle mode.
370 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
371 * @see #KEY_LOCATING_TIMEOUT
372 */
373 public long LOCATING_TIMEOUT;
374
375 /**
376 * The desired maximum accuracy (in meters) we consider the location to be good enough to go
377 * on to idle. We will be trying to get an accuracy fix at least this good or until
378 * {@link #LOCATING_TIMEOUT} expires.
379 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
380 * @see #KEY_LOCATION_ACCURACY
381 */
382 public float LOCATION_ACCURACY;
383
384 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -0700385 * This is the time, after seeing motion, that we wait after becoming inactive from
386 * that until we start looking for motion again.
387 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
388 * @see #KEY_MOTION_INACTIVE_TIMEOUT
389 */
390 public long MOTION_INACTIVE_TIMEOUT;
391
392 /**
393 * This is the time, after the inactive timeout elapses, that we will wait looking
394 * for significant motion until we truly consider the device to be idle.
395 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
396 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
397 */
398 public long IDLE_AFTER_INACTIVE_TIMEOUT;
399
400 /**
401 * This is the initial time, after being idle, that we will allow ourself to be back
402 * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
403 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
404 * @see #KEY_IDLE_PENDING_TIMEOUT
405 */
406 public long IDLE_PENDING_TIMEOUT;
407
408 /**
409 * Maximum pending idle timeout (time spent running) we will be allowed to use.
410 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
411 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
412 */
413 public long MAX_IDLE_PENDING_TIMEOUT;
414
415 /**
416 * Scaling factor to apply to current pending idle timeout each time we cycle through
417 * that state.
418 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
419 * @see #KEY_IDLE_PENDING_FACTOR
420 */
421 public float IDLE_PENDING_FACTOR;
422
423 /**
424 * This is the initial time that we want to sit in the idle state before waking up
425 * again to return to pending idle and allowing normal work to run.
426 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
427 * @see #KEY_IDLE_TIMEOUT
428 */
429 public long IDLE_TIMEOUT;
430
431 /**
432 * Maximum idle duration we will be allowed to use.
433 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
434 * @see #KEY_MAX_IDLE_TIMEOUT
435 */
436 public long MAX_IDLE_TIMEOUT;
437
438 /**
439 * Scaling factor to apply to current idle timeout each time we cycle through that state.
440 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
441 * @see #KEY_IDLE_FACTOR
442 */
443 public float IDLE_FACTOR;
444
445 /**
446 * This is the minimum time we will allow until the next upcoming alarm for us to
447 * actually go in to idle mode.
448 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
449 * @see #KEY_MIN_TIME_TO_ALARM
450 */
451 public long MIN_TIME_TO_ALARM;
452
453 /**
454 * Max amount of time to temporarily whitelist an app when it receives a high priority
455 * tickle.
456 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
457 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
458 */
459 public long MAX_TEMP_APP_WHITELIST_DURATION;
460
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700461 /**
462 * Amount of time we would like to whitelist an app that is receiving an MMS.
463 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
464 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
465 */
466 public long MMS_TEMP_APP_WHITELIST_DURATION;
467
Dianne Hackborn451c3462015-07-21 17:39:46 -0700468 /**
469 * Amount of time we would like to whitelist an app that is receiving an SMS.
470 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
471 * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
472 */
473 public long SMS_TEMP_APP_WHITELIST_DURATION;
474
Adam Lesinski31c05d12015-06-09 17:34:04 -0700475 private final ContentResolver mResolver;
476 private final KeyValueListParser mParser = new KeyValueListParser(',');
477
478 public Constants(Handler handler, ContentResolver resolver) {
479 super(handler);
480 mResolver = resolver;
481 mResolver.registerContentObserver(
482 Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), false, this);
483 updateConstants();
484 }
485
486 @Override
487 public void onChange(boolean selfChange, Uri uri) {
488 updateConstants();
489 }
490
491 private void updateConstants() {
492 synchronized (DeviceIdleController.this) {
493 try {
494 mParser.setString(Settings.Global.getString(mResolver,
495 Settings.Global.DEVICE_IDLE_CONSTANTS));
496 } catch (IllegalArgumentException e) {
497 // Failed to parse the settings string, log this and move on
498 // with defaults.
499 Slog.e(TAG, "Bad device idle settings", e);
500 }
501
502 INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
503 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
504 SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700505 !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
506 LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
507 !DEBUG ? 30 * 1000L : 15 * 1000L);
508 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700509 MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
510 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
511 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
512 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
513 IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
514 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
515 MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
516 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
517 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
518 2f);
519 IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
520 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
521 MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
522 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
523 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
524 2f);
525 MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
526 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700527 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
528 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
529 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
Dianne Hackborn0b6134b2015-07-14 18:48:07 -0700530 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
Dianne Hackborn451c3462015-07-21 17:39:46 -0700531 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
532 KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700533 }
534 }
535
536 void dump(PrintWriter pw) {
537 pw.println(" Settings:");
538
Dianne Hackborna750a632015-06-16 17:18:23 -0700539 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700540 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
541 pw.println();
542
Dianne Hackborna750a632015-06-16 17:18:23 -0700543 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700544 TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
545 pw.println();
546
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700547 pw.print(" "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
548 TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
549 pw.println();
550
551 pw.print(" "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
552 pw.print(LOCATION_ACCURACY); pw.print("m");
553 pw.println();
554
Dianne Hackborna750a632015-06-16 17:18:23 -0700555 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700556 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
557 pw.println();
558
Dianne Hackborna750a632015-06-16 17:18:23 -0700559 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700560 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
561 pw.println();
562
Dianne Hackborna750a632015-06-16 17:18:23 -0700563 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700564 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
565 pw.println();
566
Dianne Hackborna750a632015-06-16 17:18:23 -0700567 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700568 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
569 pw.println();
570
Dianne Hackborna750a632015-06-16 17:18:23 -0700571 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700572 pw.println(IDLE_PENDING_FACTOR);
573
Dianne Hackborna750a632015-06-16 17:18:23 -0700574 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700575 TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
576 pw.println();
577
Dianne Hackborna750a632015-06-16 17:18:23 -0700578 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700579 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
580 pw.println();
581
Dianne Hackborna750a632015-06-16 17:18:23 -0700582 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700583 pw.println(IDLE_FACTOR);
584
Dianne Hackborna750a632015-06-16 17:18:23 -0700585 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700586 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
587 pw.println();
588
Dianne Hackborna750a632015-06-16 17:18:23 -0700589 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700590 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
591 pw.println();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700592
593 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
594 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
595 pw.println();
Dianne Hackborn451c3462015-07-21 17:39:46 -0700596
597 pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
598 TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
599 pw.println();
Adam Lesinski31c05d12015-06-09 17:34:04 -0700600 }
601 }
602
603 private Constants mConstants;
604
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700605 @Override
606 public void onAnyMotionResult(int result) {
607 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700608 if (result == AnyMotionDetector.RESULT_MOVED) {
609 if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
610 synchronized (this) {
611 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
612 }
613 } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
614 if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
615 if (mState == STATE_SENSING) {
616 // If we are currently sensing, it is time to move to locating.
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700617 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700618 mNotMoving = true;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700619 stepIdleStateLocked();
620 }
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700621 } else if (mState == STATE_LOCATING) {
622 // If we are currently locating, note that we are not moving and step
623 // if we have located the position.
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700624 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700625 mNotMoving = true;
626 if (mLocated) {
627 stepIdleStateLocked();
628 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700629 }
630 }
631 }
632 }
633
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700634 static final int MSG_WRITE_CONFIG = 1;
635 static final int MSG_REPORT_IDLE_ON = 2;
636 static final int MSG_REPORT_IDLE_OFF = 3;
637 static final int MSG_REPORT_ACTIVE = 4;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700638 static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700639
640 final class MyHandler extends Handler {
641 MyHandler(Looper looper) {
642 super(looper);
643 }
644
645 @Override public void handleMessage(Message msg) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700646 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700647 switch (msg.what) {
648 case MSG_WRITE_CONFIG: {
649 handleWriteConfigFile();
650 } break;
651 case MSG_REPORT_IDLE_ON: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700652 EventLogTags.writeDeviceIdleOnStart();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700653 mLocalPowerManager.setDeviceIdleMode(true);
654 try {
655 mNetworkPolicyManager.setDeviceIdleMode(true);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700656 mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700657 } catch (RemoteException e) {
658 }
659 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700660 EventLogTags.writeDeviceIdleOnComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700661 } break;
662 case MSG_REPORT_IDLE_OFF: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700663 EventLogTags.writeDeviceIdleOffStart("unknown");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700664 mLocalPowerManager.setDeviceIdleMode(false);
665 try {
666 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700667 mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700668 } catch (RemoteException e) {
669 }
670 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700671 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700672 } break;
673 case MSG_REPORT_ACTIVE: {
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700674 String activeReason = (String)msg.obj;
675 int activeUid = msg.arg1;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700676 boolean needBroadcast = msg.arg2 != 0;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700677 EventLogTags.writeDeviceIdleOffStart(
678 activeReason != null ? activeReason : "unknown");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700679 mLocalPowerManager.setDeviceIdleMode(false);
680 try {
681 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700682 mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700683 } catch (RemoteException e) {
684 }
685 if (needBroadcast) {
686 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
687 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700688 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700689 } break;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700690 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
691 int uid = msg.arg1;
692 checkTempAppWhitelistTimeout(uid);
693 } break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700694 }
695 }
696 }
697
698 final MyHandler mHandler;
699
700 private final class BinderService extends IDeviceIdleController.Stub {
701 @Override public void addPowerSaveWhitelistApp(String name) {
702 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
703 null);
704 addPowerSaveWhitelistAppInternal(name);
705 }
706
707 @Override public void removePowerSaveWhitelistApp(String name) {
708 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
709 null);
710 removePowerSaveWhitelistAppInternal(name);
711 }
712
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700713 @Override public String[] getSystemPowerWhitelistExceptIdle() {
714 return getSystemPowerWhitelistExceptIdleInternal();
715 }
716
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700717 @Override public String[] getSystemPowerWhitelist() {
718 return getSystemPowerWhitelistInternal();
719 }
720
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700721 @Override public String[] getFullPowerWhitelistExceptIdle() {
722 return getFullPowerWhitelistExceptIdleInternal();
723 }
724
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700725 @Override public String[] getFullPowerWhitelist() {
726 return getFullPowerWhitelistInternal();
727 }
728
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700729 @Override public int[] getAppIdWhitelistExceptIdle() {
730 return getAppIdWhitelistExceptIdleInternal();
731 }
732
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700733 @Override public int[] getAppIdWhitelist() {
734 return getAppIdWhitelistInternal();
735 }
736
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700737 @Override public int[] getAppIdTempWhitelist() {
738 return getAppIdTempWhitelistInternal();
739 }
740
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700741 @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
742 return isPowerSaveWhitelistExceptIdleAppInternal(name);
743 }
744
Amith Yamasani06bf8242015-05-08 16:36:21 -0700745 @Override public boolean isPowerSaveWhitelistApp(String name) {
746 return isPowerSaveWhitelistAppInternal(name);
747 }
748
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700749 @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700750 int userId, String reason) throws RemoteException {
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700751 getContext().enforceCallingPermission(
752 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
753 "No permission to change device idle whitelist");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700754 final int callingUid = Binder.getCallingUid();
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700755 userId = ActivityManagerNative.getDefault().handleIncomingUser(
756 Binder.getCallingPid(),
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700757 callingUid,
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700758 userId,
759 /*allowAll=*/ false,
760 /*requireFull=*/ false,
Dianne Hackborna750a632015-06-16 17:18:23 -0700761 "addPowerSaveTempWhitelistApp", null);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700762 final long token = Binder.clearCallingIdentity();
763 try {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700764 DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700765 packageName, duration, userId, true, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700766 } finally {
767 Binder.restoreCallingIdentity(token);
768 }
769 }
770
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700771 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
772 int userId, String reason) throws RemoteException {
773 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
774 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
775 return duration;
776 }
777
Dianne Hackborn451c3462015-07-21 17:39:46 -0700778 @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
779 int userId, String reason) throws RemoteException {
780 long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
781 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
782 return duration;
783 }
784
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700785 @Override public void exitIdle(String reason) {
786 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
787 null);
788 exitIdleInternal(reason);
789 }
790
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700791 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
792 DeviceIdleController.this.dump(fd, pw, args);
793 }
794 }
795
Dianne Hackborna750a632015-06-16 17:18:23 -0700796 public final class LocalService {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700797 public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
798 String reason) {
799 addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
800 }
801
802 public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
803 setNetworkPolicyTempWhitelistCallbackInternal(callback);
Dianne Hackborna750a632015-06-16 17:18:23 -0700804 }
805 }
806
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700807 public DeviceIdleController(Context context) {
808 super(context);
809 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
810 mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
811 }
812
813 private static File getSystemDir() {
814 return new File(Environment.getDataDirectory(), "system");
815 }
816
817 @Override
818 public void onStart() {
819 final PackageManager pm = getContext().getPackageManager();
820
821 synchronized (this) {
Dianne Hackborn92617032015-06-19 15:32:19 -0700822 mEnabled = getContext().getResources().getBoolean(
823 com.android.internal.R.bool.config_enableAutoPowerModes);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700824 SystemConfig sysConfig = SystemConfig.getInstance();
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700825 ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
826 for (int i=0; i<allowPowerExceptIdle.size(); i++) {
827 String pkg = allowPowerExceptIdle.valueAt(i);
828 try {
829 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
830 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
831 int appid = UserHandle.getAppId(ai.uid);
832 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
833 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
834 }
835 } catch (PackageManager.NameNotFoundException e) {
836 }
837 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700838 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
839 for (int i=0; i<allowPower.size(); i++) {
840 String pkg = allowPower.valueAt(i);
841 try {
842 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
843 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700844 int appid = UserHandle.getAppId(ai.uid);
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700845 // These apps are on both the whitelist-except-idle as well
846 // as the full whitelist, so they apply in all cases.
847 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
848 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700849 mPowerSaveWhitelistApps.put(ai.packageName, appid);
850 mPowerSaveWhitelistSystemAppIds.put(appid, true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700851 }
852 } catch (PackageManager.NameNotFoundException e) {
853 }
854 }
855
Adam Lesinski31c05d12015-06-09 17:34:04 -0700856 mConstants = new Constants(mHandler, getContext().getContentResolver());
857
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700858 readConfigFileLocked();
859 updateWhitelistAppIdsLocked();
860
861 mScreenOn = true;
862 // Start out assuming we are charging. If we aren't, we will at least get
863 // a battery update the next time the level drops.
864 mCharging = true;
865 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -0700866 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700867 }
868
Dianne Hackborn1958e5e2015-06-12 18:11:41 -0700869 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
Dianne Hackborna750a632015-06-16 17:18:23 -0700870 publishLocalService(LocalService.class, new LocalService());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700871 }
872
873 @Override
874 public void onBootPhase(int phase) {
875 if (phase == PHASE_SYSTEM_SERVICES_READY) {
876 synchronized (this) {
877 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
878 mBatteryStats = BatteryStatsService.getService();
879 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
880 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700881 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700882 mDisplayManager = (DisplayManager) getContext().getSystemService(
883 Context.DISPLAY_SERVICE);
884 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
885 mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700886 mLocationManager = (LocationManager) getContext().getSystemService(
887 Context.LOCATION_SERVICE);
888 mLocationRequest = new LocationRequest()
889 .setQuality(LocationRequest.ACCURACY_FINE)
890 .setInterval(0)
891 .setFastestInterval(0)
892 .setNumUpdates(1);
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700893 mAnyMotionDetector = new AnyMotionDetector(
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700894 (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
895 mHandler, mSensorManager, this);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700896
897 Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
898 .setPackage("android")
899 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
900 mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
901
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700902 Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)
903 .setPackage("android")
904 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
905 mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
906
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700907 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700908 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
909 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700910
911 IntentFilter filter = new IntentFilter();
912 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
913 filter.addAction(ACTION_STEP_IDLE_STATE);
914 getContext().registerReceiver(mReceiver, filter);
915
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700916 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700917
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700918 mDisplayManager.registerDisplayListener(mDisplayListener, null);
919 updateDisplayLocked();
920 }
921 }
922 }
923
924 public boolean addPowerSaveWhitelistAppInternal(String name) {
925 synchronized (this) {
926 try {
927 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0);
928 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
929 reportPowerSaveWhitelistChangedLocked();
930 updateWhitelistAppIdsLocked();
931 writeConfigFileLocked();
932 }
933 return true;
934 } catch (PackageManager.NameNotFoundException e) {
935 return false;
936 }
937 }
938 }
939
940 public boolean removePowerSaveWhitelistAppInternal(String name) {
941 synchronized (this) {
942 if (mPowerSaveWhitelistUserApps.remove(name) != null) {
943 reportPowerSaveWhitelistChangedLocked();
944 updateWhitelistAppIdsLocked();
945 writeConfigFileLocked();
946 return true;
947 }
948 }
949 return false;
950 }
951
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700952 public String[] getSystemPowerWhitelistExceptIdleInternal() {
953 synchronized (this) {
954 int size = mPowerSaveWhitelistAppsExceptIdle.size();
955 String[] apps = new String[size];
956 for (int i = 0; i < size; i++) {
957 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
958 }
959 return apps;
960 }
961 }
962
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700963 public String[] getSystemPowerWhitelistInternal() {
964 synchronized (this) {
965 int size = mPowerSaveWhitelistApps.size();
966 String[] apps = new String[size];
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700967 for (int i = 0; i < size; i++) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700968 apps[i] = mPowerSaveWhitelistApps.keyAt(i);
969 }
970 return apps;
971 }
972 }
973
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700974 public String[] getFullPowerWhitelistExceptIdleInternal() {
975 synchronized (this) {
976 int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
977 String[] apps = new String[size];
978 int cur = 0;
979 for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
980 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
981 cur++;
982 }
983 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
984 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
985 cur++;
986 }
987 return apps;
988 }
989 }
990
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700991 public String[] getFullPowerWhitelistInternal() {
992 synchronized (this) {
993 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
994 String[] apps = new String[size];
995 int cur = 0;
996 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
997 apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
998 cur++;
999 }
1000 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1001 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1002 cur++;
1003 }
1004 return apps;
1005 }
1006 }
1007
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001008 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
1009 synchronized (this) {
1010 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
1011 || mPowerSaveWhitelistUserApps.containsKey(packageName);
1012 }
1013 }
1014
Amith Yamasani06bf8242015-05-08 16:36:21 -07001015 public boolean isPowerSaveWhitelistAppInternal(String packageName) {
1016 synchronized (this) {
1017 return mPowerSaveWhitelistApps.containsKey(packageName)
1018 || mPowerSaveWhitelistUserApps.containsKey(packageName);
1019 }
1020 }
1021
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001022 public int[] getAppIdWhitelistExceptIdleInternal() {
1023 synchronized (this) {
1024 return mPowerSaveWhitelistExceptIdleAppIdArray;
1025 }
1026 }
1027
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001028 public int[] getAppIdWhitelistInternal() {
1029 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001030 return mPowerSaveWhitelistAllAppIdArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001031 }
1032 }
1033
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001034 public int[] getAppIdTempWhitelistInternal() {
1035 synchronized (this) {
1036 return mTempWhitelistAppIdArray;
1037 }
1038 }
1039
1040 /**
1041 * Adds an app to the temporary whitelist and resets the endTime for granting the
1042 * app an exemption to access network and acquire wakelocks.
1043 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001044 public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001045 long duration, int userId, boolean sync, String reason) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001046 try {
1047 int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
1048 int appId = UserHandle.getAppId(uid);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001049 addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001050 } catch (NameNotFoundException e) {
1051 }
1052 }
1053
Dianne Hackborna750a632015-06-16 17:18:23 -07001054 /**
1055 * Adds an app to the temporary whitelist and resets the endTime for granting the
1056 * app an exemption to access network and acquire wakelocks.
1057 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001058 public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001059 long duration, boolean sync, String reason) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001060 final long timeNow = SystemClock.elapsedRealtime();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001061 Runnable networkPolicyTempWhitelistCallback = null;
Dianne Hackborna750a632015-06-16 17:18:23 -07001062 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001063 int callingAppId = UserHandle.getAppId(callingUid);
1064 if (callingAppId >= Process.FIRST_APPLICATION_UID) {
1065 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
1066 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
1067 + " is not on whitelist");
1068 }
1069 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001070 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001071 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
1072 final boolean newEntry = entry == null;
Dianne Hackborna750a632015-06-16 17:18:23 -07001073 // Set the new end time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001074 if (newEntry) {
1075 entry = new Pair<>(new MutableLong(0), reason);
1076 mTempWhitelistAppIdEndTimes.put(appId, entry);
1077 }
1078 entry.first.value = timeNow + duration;
Dianne Hackborna750a632015-06-16 17:18:23 -07001079 if (DEBUG) {
1080 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
1081 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001082 if (newEntry) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001083 // No pending timeout for the app id, post a delayed message
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001084 try {
1085 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
1086 reason, appId);
1087 } catch (RemoteException e) {
1088 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001089 postTempActiveTimeoutMessage(appId, duration);
1090 updateTempWhitelistAppIdsLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001091 if (mNetworkPolicyTempWhitelistCallback != null) {
1092 if (!sync) {
1093 mHandler.post(mNetworkPolicyTempWhitelistCallback);
1094 } else {
1095 networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
1096 }
1097 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001098 reportTempWhitelistChangedLocked();
1099 }
1100 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001101 if (networkPolicyTempWhitelistCallback != null) {
1102 networkPolicyTempWhitelistCallback.run();
1103 }
1104 }
1105
1106 public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
1107 synchronized (this) {
1108 mNetworkPolicyTempWhitelistCallback = callback;
1109 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001110 }
1111
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001112 private void postTempActiveTimeoutMessage(int uid, long delay) {
1113 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
1114 delay);
1115 }
1116
1117 void checkTempAppWhitelistTimeout(int uid) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001118 final long timeNow = SystemClock.elapsedRealtime();
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001119 synchronized (this) {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001120 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
1121 if (entry == null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001122 // Nothing to do
1123 return;
1124 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001125 if (timeNow >= entry.first.value) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001126 mTempWhitelistAppIdEndTimes.delete(uid);
1127 if (DEBUG) {
1128 Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
1129 }
1130 updateTempWhitelistAppIdsLocked();
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001131 if (mNetworkPolicyTempWhitelistCallback != null) {
1132 mHandler.post(mNetworkPolicyTempWhitelistCallback);
1133 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001134 reportTempWhitelistChangedLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001135 try {
1136 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
1137 entry.second, uid);
1138 } catch (RemoteException e) {
1139 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001140 } else {
1141 // Need more time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001142 postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001143 }
1144 }
1145 }
1146
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001147 public void exitIdleInternal(String reason) {
1148 synchronized (this) {
1149 becomeActiveLocked(reason, Binder.getCallingUid());
1150 }
1151 }
1152
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001153 void updateDisplayLocked() {
1154 mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
1155 // We consider any situation where the display is showing something to be it on,
1156 // because if there is anything shown we are going to be updating it at some
1157 // frequency so can't be allowed to go into deep sleeps.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001158 boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001159 if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001160 if (!screenOn && mScreenOn) {
1161 mScreenOn = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001162 if (!mForceIdle) {
1163 becomeInactiveIfAppropriateLocked();
1164 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001165 } else if (screenOn) {
1166 mScreenOn = true;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001167 if (!mForceIdle) {
1168 becomeActiveLocked("screen", Process.myUid());
1169 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001170 }
1171 }
1172
1173 void updateChargingLocked(boolean charging) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001174 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001175 if (!charging && mCharging) {
1176 mCharging = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001177 if (!mForceIdle) {
1178 becomeInactiveIfAppropriateLocked();
1179 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001180 } else if (charging) {
1181 mCharging = charging;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001182 if (!mForceIdle) {
1183 becomeActiveLocked("charging", Process.myUid());
1184 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001185 }
1186 }
1187
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001188 void scheduleReportActiveLocked(String activeReason, int activeUid) {
1189 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
1190 mState == STATE_IDLE ? 1 : 0, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001191 mHandler.sendMessage(msg);
1192 }
1193
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001194 void becomeActiveLocked(String activeReason, int activeUid) {
1195 if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001196 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001197 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
1198 scheduleReportActiveLocked(activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001199 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -07001200 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001201 resetIdleManagementLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001202 }
1203 }
1204
1205 void becomeInactiveIfAppropriateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001206 if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001207 if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001208 // Screen has turned off; we are now going to become inactive and start
1209 // waiting to see if we will ultimately go idle.
1210 mState = STATE_INACTIVE;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001211 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001212 resetIdleManagementLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001213 scheduleAlarmLocked(mInactiveTimeout, false);
1214 EventLogTags.writeDeviceIdle(mState, "no activity");
1215 }
1216 }
1217
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001218 void resetIdleManagementLocked() {
1219 mNextIdlePendingDelay = 0;
1220 mNextIdleDelay = 0;
1221 cancelAlarmLocked();
1222 cancelSensingAlarmLocked();
1223 cancelLocatingLocked();
1224 stopMonitoringSignificantMotion();
1225 mAnyMotionDetector.stop();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001226 }
1227
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001228 void exitForceIdleLocked() {
1229 if (mForceIdle) {
1230 mForceIdle = false;
1231 if (mScreenOn || mCharging) {
1232 becomeActiveLocked("exit-force-idle", Process.myUid());
1233 }
1234 }
1235 }
1236
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001237 void stepIdleStateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001238 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001239 EventLogTags.writeDeviceIdleStep();
1240
1241 final long now = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001242 if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001243 // Whoops, there is an upcoming alarm. We don't actually want to go idle.
1244 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001245 becomeActiveLocked("alarm", Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001246 }
1247 return;
1248 }
1249
1250 switch (mState) {
1251 case STATE_INACTIVE:
1252 // We have now been inactive long enough, it is time to start looking
1253 // for significant motion and sleep some more while doing so.
1254 startMonitoringSignificantMotion();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001255 scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001256 // Reset the upcoming idle delays.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001257 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
1258 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001259 mState = STATE_IDLE_PENDING;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001260 if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001261 EventLogTags.writeDeviceIdle(mState, "step");
1262 break;
1263 case STATE_IDLE_PENDING:
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001264 mState = STATE_SENSING;
1265 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001266 EventLogTags.writeDeviceIdle(mState, "step");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001267 scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001268 cancelSensingAlarmLocked();
1269 cancelLocatingLocked();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001270 mAnyMotionDetector.checkForAnyMotion();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001271 mNotMoving = false;
1272 mLocated = false;
1273 mLastGenericLocation = null;
1274 mLastGpsLocation = null;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001275 break;
1276 case STATE_SENSING:
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001277 mState = STATE_LOCATING;
1278 if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
1279 EventLogTags.writeDeviceIdle(mState, "step");
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001280 cancelSensingAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001281 scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
1282 mLocating = true;
1283 mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener,
1284 mHandler.getLooper());
1285 if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
1286 mHaveGps = true;
1287 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
1288 mGpsLocationListener, mHandler.getLooper());
1289 } else {
1290 mHaveGps = false;
1291 }
1292 break;
1293 case STATE_LOCATING:
1294 cancelSensingAlarmLocked();
1295 cancelLocatingLocked();
1296 mAnyMotionDetector.stop();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001297 case STATE_IDLE_MAINTENANCE:
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001298 scheduleAlarmLocked(mNextIdleDelay, true);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001299 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
1300 " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001301 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001302 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001303 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001304 mState = STATE_IDLE;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001305 EventLogTags.writeDeviceIdle(mState, "step");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001306 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
1307 break;
1308 case STATE_IDLE:
1309 // We have been idling long enough, now it is time to do some work.
1310 scheduleAlarmLocked(mNextIdlePendingDelay, false);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001311 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
1312 "Next alarm in " + mNextIdlePendingDelay + " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001313 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
1314 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001315 mState = STATE_IDLE_MAINTENANCE;
1316 EventLogTags.writeDeviceIdle(mState, "step");
1317 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1318 break;
1319 }
1320 }
1321
1322 void significantMotionLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001323 if (DEBUG) Slog.d(TAG, "significantMotionLocked()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001324 // When the sensor goes off, its trigger is automatically removed.
1325 mSigMotionActive = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001326 handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
1327 }
1328
1329 void handleMotionDetectedLocked(long timeout, String type) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001330 // The device is not yet active, so we want to go back to the pending idle
1331 // state to wait again for no motion. Note that we only monitor for significant
1332 // motion after moving out of the inactive state, so no need to worry about that.
1333 if (mState != STATE_ACTIVE) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001334 scheduleReportActiveLocked(type, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001335 mState = STATE_ACTIVE;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001336 mInactiveTimeout = timeout;
1337 EventLogTags.writeDeviceIdle(mState, type);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001338 becomeInactiveIfAppropriateLocked();
1339 }
1340 }
1341
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001342 void receivedGenericLocationLocked(Location location) {
1343 if (mState != STATE_LOCATING) {
1344 cancelLocatingLocked();
1345 return;
1346 }
1347 if (DEBUG) Slog.d(TAG, "Generic location: " + location);
1348 mLastGenericLocation = new Location(location);
1349 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHaveGps) {
1350 return;
1351 }
1352 mLocated = true;
1353 if (mNotMoving) {
1354 stepIdleStateLocked();
1355 }
1356 }
1357
1358 void receivedGpsLocationLocked(Location location) {
1359 if (mState != STATE_LOCATING) {
1360 cancelLocatingLocked();
1361 return;
1362 }
1363 if (DEBUG) Slog.d(TAG, "GPS location: " + location);
1364 mLastGpsLocation = new Location(location);
1365 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
1366 return;
1367 }
1368 mLocated = true;
1369 if (mNotMoving) {
1370 stepIdleStateLocked();
1371 }
1372 }
1373
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001374 void startMonitoringSignificantMotion() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001375 if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001376 if (mSigMotionSensor != null && !mSigMotionActive) {
1377 mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor);
1378 mSigMotionActive = true;
1379 }
1380 }
1381
1382 void stopMonitoringSignificantMotion() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001383 if (DEBUG) Slog.d(TAG, "stopMonitoringSignificantMotion()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001384 if (mSigMotionActive) {
1385 mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor);
1386 mSigMotionActive = false;
1387 }
1388 }
1389
1390 void cancelAlarmLocked() {
1391 if (mNextAlarmTime != 0) {
1392 mNextAlarmTime = 0;
1393 mAlarmManager.cancel(mAlarmIntent);
1394 }
1395 }
1396
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001397 void cancelSensingAlarmLocked() {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001398 if (mSensing) {
1399 if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
1400 mAlarmManager.cancel(mSensingAlarmIntent);
1401 mSensing = false;
1402 }
1403 }
1404
1405 void cancelLocatingLocked() {
1406 if (mLocating) {
1407 mLocationManager.removeUpdates(mGenericLocationListener);
1408 mLocationManager.removeUpdates(mGpsLocationListener);
1409 mLocating = false;
1410 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001411 }
1412
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001413 void scheduleAlarmLocked(long delay, boolean idleUntil) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001414 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001415 if (mSigMotionSensor == null) {
1416 // If there is no significant motion sensor on this device, then we won't schedule
1417 // alarms, because we can't determine if the device is not moving. This effectively
1418 // turns off normal exeuction of device idling, although it is still possible to
1419 // manually poke it by pretending like the alarm is going off.
1420 return;
1421 }
1422 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1423 if (idleUntil) {
1424 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1425 mNextAlarmTime, mAlarmIntent);
1426 } else {
1427 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1428 mNextAlarmTime, mAlarmIntent);
1429 }
1430 }
1431
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001432 void scheduleSensingAlarmLocked(long delay) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001433 if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
1434 cancelSensingAlarmLocked();
1435 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1436 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1437 mNextAlarmTime, mSensingAlarmIntent);
1438 mSensing = true;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001439 }
1440
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001441 private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
1442 ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
1443 outAppIds.clear();
1444 for (int i=0; i<systemApps.size(); i++) {
1445 outAppIds.put(systemApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001446 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001447 for (int i=0; i<userApps.size(); i++) {
1448 outAppIds.put(userApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001449 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001450 int size = outAppIds.size();
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001451 int[] appids = new int[size];
1452 for (int i = 0; i < size; i++) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001453 appids[i] = outAppIds.keyAt(i);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001454 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001455 return appids;
1456 }
1457
1458 private void updateWhitelistAppIdsLocked() {
1459 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
1460 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
1461 mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
1462 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001463 if (mLocalPowerManager != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001464 if (DEBUG) {
1465 Slog.d(TAG, "Setting wakelock whitelist to "
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001466 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001467 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001468 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001469 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001470 }
1471
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001472 private void updateTempWhitelistAppIdsLocked() {
1473 final int size = mTempWhitelistAppIdEndTimes.size();
1474 if (mTempWhitelistAppIdArray.length != size) {
1475 mTempWhitelistAppIdArray = new int[size];
1476 }
1477 for (int i = 0; i < size; i++) {
1478 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
1479 }
1480 if (mLocalPowerManager != null) {
1481 if (DEBUG) {
1482 Slog.d(TAG, "Setting wakelock temp whitelist to "
1483 + Arrays.toString(mTempWhitelistAppIdArray));
1484 }
1485 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
1486 }
1487 }
1488
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001489 private void reportPowerSaveWhitelistChangedLocked() {
1490 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
1491 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001492 getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
1493 }
1494
1495 private void reportTempWhitelistChangedLocked() {
1496 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
1497 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1498 getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001499 }
1500
1501 void readConfigFileLocked() {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001502 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001503 mPowerSaveWhitelistUserApps.clear();
1504 FileInputStream stream;
1505 try {
1506 stream = mConfigFile.openRead();
1507 } catch (FileNotFoundException e) {
1508 return;
1509 }
1510 try {
1511 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001512 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001513 readConfigFileLocked(parser);
1514 } catch (XmlPullParserException e) {
1515 } finally {
1516 try {
1517 stream.close();
1518 } catch (IOException e) {
1519 }
1520 }
1521
1522 }
1523
1524 private void readConfigFileLocked(XmlPullParser parser) {
1525 final PackageManager pm = getContext().getPackageManager();
1526
1527 try {
1528 int type;
1529 while ((type = parser.next()) != XmlPullParser.START_TAG
1530 && type != XmlPullParser.END_DOCUMENT) {
1531 ;
1532 }
1533
1534 if (type != XmlPullParser.START_TAG) {
1535 throw new IllegalStateException("no start tag found");
1536 }
1537
1538 int outerDepth = parser.getDepth();
1539 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1540 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1541 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1542 continue;
1543 }
1544
1545 String tagName = parser.getName();
1546 if (tagName.equals("wl")) {
1547 String name = parser.getAttributeValue(null, "n");
1548 if (name != null) {
1549 try {
1550 ApplicationInfo ai = pm.getApplicationInfo(name, 0);
1551 mPowerSaveWhitelistUserApps.put(ai.packageName,
1552 UserHandle.getAppId(ai.uid));
1553 } catch (PackageManager.NameNotFoundException e) {
1554 }
1555 }
1556 } else {
1557 Slog.w(TAG, "Unknown element under <config>: "
1558 + parser.getName());
1559 XmlUtils.skipCurrentTag(parser);
1560 }
1561 }
1562
1563 } catch (IllegalStateException e) {
1564 Slog.w(TAG, "Failed parsing config " + e);
1565 } catch (NullPointerException e) {
1566 Slog.w(TAG, "Failed parsing config " + e);
1567 } catch (NumberFormatException e) {
1568 Slog.w(TAG, "Failed parsing config " + e);
1569 } catch (XmlPullParserException e) {
1570 Slog.w(TAG, "Failed parsing config " + e);
1571 } catch (IOException e) {
1572 Slog.w(TAG, "Failed parsing config " + e);
1573 } catch (IndexOutOfBoundsException e) {
1574 Slog.w(TAG, "Failed parsing config " + e);
1575 }
1576 }
1577
1578 void writeConfigFileLocked() {
1579 mHandler.removeMessages(MSG_WRITE_CONFIG);
1580 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
1581 }
1582
1583 void handleWriteConfigFile() {
1584 final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
1585
1586 try {
1587 synchronized (this) {
1588 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001589 out.setOutput(memStream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001590 writeConfigFileLocked(out);
1591 }
1592 } catch (IOException e) {
1593 }
1594
1595 synchronized (mConfigFile) {
1596 FileOutputStream stream = null;
1597 try {
1598 stream = mConfigFile.startWrite();
1599 memStream.writeTo(stream);
1600 stream.flush();
1601 FileUtils.sync(stream);
1602 stream.close();
1603 mConfigFile.finishWrite(stream);
1604 } catch (IOException e) {
1605 Slog.w(TAG, "Error writing config file", e);
1606 mConfigFile.failWrite(stream);
1607 }
1608 }
1609 }
1610
1611 void writeConfigFileLocked(XmlSerializer out) throws IOException {
1612 out.startDocument(null, true);
1613 out.startTag(null, "config");
1614 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
1615 String name = mPowerSaveWhitelistUserApps.keyAt(i);
1616 out.startTag(null, "wl");
1617 out.attribute(null, "n", name);
1618 out.endTag(null, "wl");
1619 }
1620 out.endTag(null, "config");
1621 out.endDocument();
1622 }
1623
1624 private void dumpHelp(PrintWriter pw) {
1625 pw.println("Device idle controller (deviceidle) dump options:");
1626 pw.println(" [-h] [CMD]");
1627 pw.println(" -h: print this help text.");
1628 pw.println("Commands:");
1629 pw.println(" step");
1630 pw.println(" Immediately step to next state, without waiting for alarm.");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001631 pw.println(" force-idle");
1632 pw.println(" Force directly into idle mode, regardless of other device state.");
1633 pw.println(" Use \"step\" to get out.");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001634 pw.println(" disable");
1635 pw.println(" Completely disable device idle mode.");
1636 pw.println(" enable");
1637 pw.println(" Re-enable device idle mode after it had previously been disabled.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001638 pw.println(" enabled");
1639 pw.println(" Print 1 if device idle mode is currently enabled, else 0.");
Dianne Hackborn1b139682015-07-06 15:13:37 -07001640 pw.println(" whitelist");
1641 pw.println(" Print currently whitelisted apps.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001642 pw.println(" whitelist [package ...]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001643 pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001644 pw.println(" tempwhitelist [package ..]");
1645 pw.println(" Temporarily place packages in whitelist for 10 seconds.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001646 }
1647
1648 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1649 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1650 != PackageManager.PERMISSION_GRANTED) {
1651 pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
1652 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1653 + " without permission " + android.Manifest.permission.DUMP);
1654 return;
1655 }
1656
1657 if (args != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001658 int userId = UserHandle.USER_OWNER;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001659 for (int i=0; i<args.length; i++) {
1660 String arg = args[i];
1661 if ("-h".equals(arg)) {
1662 dumpHelp(pw);
1663 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001664 } else if ("-u".equals(arg)) {
1665 i++;
1666 if (i < args.length) {
1667 arg = args[i];
1668 userId = Integer.parseInt(arg);
1669 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001670 } else if ("-a".equals(arg)) {
1671 // Ignore, we always dump all.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001672 } else if ("step".equals(arg)) {
1673 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001674 long token = Binder.clearCallingIdentity();
1675 try {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001676 exitForceIdleLocked();
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001677 stepIdleStateLocked();
1678 pw.print("Stepped to: "); pw.println(stateToString(mState));
1679 } finally {
1680 Binder.restoreCallingIdentity(token);
1681 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001682 }
1683 return;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001684 } else if ("force-idle".equals(arg)) {
1685 synchronized (this) {
1686 long token = Binder.clearCallingIdentity();
1687 try {
1688 if (!mEnabled) {
1689 pw.println("Unable to go idle; not enabled");
1690 return;
1691 }
1692 mForceIdle = true;
1693 becomeInactiveIfAppropriateLocked();
1694 int curState = mState;
1695 while (curState != STATE_IDLE) {
1696 stepIdleStateLocked();
1697 if (curState == mState) {
1698 pw.print("Unable to go idle; stopped at ");
1699 pw.println(stateToString(mState));
1700 exitForceIdleLocked();
1701 return;
1702 }
1703 curState = mState;
1704 }
1705 pw.println("Now forced in to idle mode");
1706 } finally {
1707 Binder.restoreCallingIdentity(token);
1708 }
1709 }
1710 return;
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001711 } else if ("disable".equals(arg)) {
1712 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001713 long token = Binder.clearCallingIdentity();
1714 try {
1715 if (mEnabled) {
1716 mEnabled = false;
1717 becomeActiveLocked("disabled", Process.myUid());
1718 pw.println("Idle mode disabled");
1719 }
1720 } finally {
1721 Binder.restoreCallingIdentity(token);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001722 }
1723 }
1724 return;
1725 } else if ("enable".equals(arg)) {
1726 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001727 long token = Binder.clearCallingIdentity();
1728 try {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001729 exitForceIdleLocked();
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001730 if (!mEnabled) {
1731 mEnabled = true;
1732 becomeInactiveIfAppropriateLocked();
1733 pw.println("Idle mode enabled");
1734 }
1735 } finally {
1736 Binder.restoreCallingIdentity(token);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001737 }
1738 }
1739 return;
Dianne Hackborn92617032015-06-19 15:32:19 -07001740 } else if ("enabled".equals(arg)) {
1741 synchronized (this) {
1742 pw.println(mEnabled ? "1" : " 0");
1743 }
1744 return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001745 } else if ("whitelist".equals(arg)) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001746 long token = Binder.clearCallingIdentity();
1747 try {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001748 i++;
Dianne Hackborn1b139682015-07-06 15:13:37 -07001749 if (i < args.length) {
1750 while (i < args.length) {
1751 arg = args[i];
1752 i++;
1753 if (arg.length() < 1 || (arg.charAt(0) != '-'
1754 && arg.charAt(0) != '+')) {
1755 pw.println("Package must be prefixed with + or -: " + arg);
1756 return;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001757 }
Dianne Hackborn1b139682015-07-06 15:13:37 -07001758 char op = arg.charAt(0);
1759 String pkg = arg.substring(1);
1760 if (op == '+') {
1761 if (addPowerSaveWhitelistAppInternal(pkg)) {
1762 pw.println("Added: " + pkg);
1763 } else {
1764 pw.println("Unknown package: " + pkg);
1765 }
1766 } else {
1767 if (removePowerSaveWhitelistAppInternal(pkg)) {
1768 pw.println("Removed: " + pkg);
1769 }
1770 }
1771 }
1772 } else {
1773 synchronized (this) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001774 for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
1775 pw.print("system-excidle,");
1776 pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
1777 pw.print(",");
1778 pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
1779 }
Dianne Hackborn1b139682015-07-06 15:13:37 -07001780 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
1781 pw.print("system,");
1782 pw.print(mPowerSaveWhitelistApps.keyAt(j));
1783 pw.print(",");
1784 pw.println(mPowerSaveWhitelistApps.valueAt(j));
1785 }
1786 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
1787 pw.print("user,");
1788 pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
1789 pw.print(",");
1790 pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001791 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001792 }
1793 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001794 } finally {
1795 Binder.restoreCallingIdentity(token);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001796 }
1797 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001798 } else if ("tempwhitelist".equals(arg)) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001799 long token = Binder.clearCallingIdentity();
1800 try {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001801 i++;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001802 if (i >= args.length) {
1803 pw.println("At least one package name must be specified");
1804 return;
1805 }
1806 while (i < args.length) {
1807 arg = args[i];
1808 i++;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001809 addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId, true,
1810 "shell");
1811 pw.println("Added: " + arg);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001812 }
1813 } finally {
1814 Binder.restoreCallingIdentity(token);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001815 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001816 return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001817 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
1818 pw.println("Unknown option: " + arg);
1819 return;
1820 } else {
1821 pw.println("Unknown command: " + arg);
1822 return;
1823 }
1824 }
1825 }
1826
1827 synchronized (this) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001828 mConstants.dump(pw);
1829
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001830 int size = mPowerSaveWhitelistAppsExceptIdle.size();
1831 if (size > 0) {
1832 pw.println(" Whitelist (except idle) system apps:");
1833 for (int i = 0; i < size; i++) {
1834 pw.print(" ");
1835 pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
1836 }
1837 }
1838 size = mPowerSaveWhitelistApps.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001839 if (size > 0) {
1840 pw.println(" Whitelist system apps:");
1841 for (int i = 0; i < size; i++) {
1842 pw.print(" ");
1843 pw.println(mPowerSaveWhitelistApps.keyAt(i));
1844 }
1845 }
1846 size = mPowerSaveWhitelistUserApps.size();
1847 if (size > 0) {
1848 pw.println(" Whitelist user apps:");
1849 for (int i = 0; i < size; i++) {
1850 pw.print(" ");
1851 pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
1852 }
1853 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001854 size = mPowerSaveWhitelistExceptIdleAppIds.size();
1855 if (size > 0) {
1856 pw.println(" Whitelist (except idle) all app ids:");
1857 for (int i = 0; i < size; i++) {
1858 pw.print(" ");
1859 pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
1860 pw.println();
1861 }
1862 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001863 size = mPowerSaveWhitelistAllAppIds.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001864 if (size > 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001865 pw.println(" Whitelist all app ids:");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001866 for (int i = 0; i < size; i++) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001867 pw.print(" ");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001868 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001869 pw.println();
1870 }
1871 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001872 size = mTempWhitelistAppIdEndTimes.size();
1873 if (size > 0) {
1874 pw.println(" Temp whitelist schedule:");
1875 final long timeNow = SystemClock.elapsedRealtime();
1876 for (int i = 0; i < size; i++) {
1877 pw.print(" UID=");
1878 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
1879 pw.print(": ");
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001880 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
1881 TimeUtils.formatDuration(entry.first.value, timeNow, pw);
1882 pw.print(" - ");
1883 pw.println(entry.second);
Dianne Hackborna750a632015-06-16 17:18:23 -07001884 }
1885 }
1886 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
1887 if (size > 0) {
1888 pw.println(" Temp whitelist app ids:");
1889 for (int i = 0; i < size; i++) {
1890 pw.print(" ");
1891 pw.print(mTempWhitelistAppIdArray[i]);
1892 pw.println();
1893 }
1894 }
Adam Lesinski31c05d12015-06-09 17:34:04 -07001895
Dianne Hackborn92617032015-06-19 15:32:19 -07001896 pw.print(" mEnabled="); pw.println(mEnabled);
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001897 pw.print(" mForceIdle="); pw.println(mForceIdle);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001898 pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
1899 pw.print(" mCurDisplay="); pw.println(mCurDisplay);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001900 pw.print(" mScreenOn="); pw.println(mScreenOn);
1901 pw.print(" mCharging="); pw.println(mCharging);
1902 pw.print(" mSigMotionActive="); pw.println(mSigMotionActive);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001903 pw.print(" mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
1904 pw.println(mNotMoving);
1905 pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHaveGps=");
1906 pw.print(mHaveGps); pw.print(" mLocated="); pw.println(mLocated);
1907 if (mLastGenericLocation != null) {
1908 pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation);
1909 }
1910 if (mLastGpsLocation != null) {
1911 pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation);
1912 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001913 pw.print(" mState="); pw.println(stateToString(mState));
1914 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
1915 pw.println();
1916 if (mNextAlarmTime != 0) {
1917 pw.print(" mNextAlarmTime=");
1918 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
1919 pw.println();
1920 }
1921 if (mNextIdlePendingDelay != 0) {
1922 pw.print(" mNextIdlePendingDelay=");
1923 TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
1924 pw.println();
1925 }
1926 if (mNextIdleDelay != 0) {
1927 pw.print(" mNextIdleDelay=");
1928 TimeUtils.formatDuration(mNextIdleDelay, pw);
1929 pw.println();
1930 }
1931 }
1932 }
1933}