blob: 2f4ad3ff0e293fba8786e01b156ec15414041166 [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;
Joe LaPenna23d681b2015-08-27 15:12:11 -0700131 private boolean mHasGps;
132 private boolean mHasNetworkLocation;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700133 private Location mLastGenericLocation;
134 private Location mLastGpsLocation;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700135
136 /** Device is currently active. */
137 private static final int STATE_ACTIVE = 0;
138 /** Device is inactve (screen off, no motion) and we are waiting to for idle. */
139 private static final int STATE_INACTIVE = 1;
140 /** Device is past the initial inactive period, and waiting for the next idle period. */
141 private static final int STATE_IDLE_PENDING = 2;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700142 /** Device is currently sensing motion. */
143 private static final int STATE_SENSING = 3;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700144 /** Device is currently finding location (and may still be sensing). */
145 private static final int STATE_LOCATING = 4;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700146 /** Device is in the idle state, trying to stay asleep as much as possible. */
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700147 private static final int STATE_IDLE = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700148 /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700149 private static final int STATE_IDLE_MAINTENANCE = 6;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700150 private static String stateToString(int state) {
151 switch (state) {
152 case STATE_ACTIVE: return "ACTIVE";
153 case STATE_INACTIVE: return "INACTIVE";
154 case STATE_IDLE_PENDING: return "IDLE_PENDING";
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700155 case STATE_SENSING: return "SENSING";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700156 case STATE_LOCATING: return "LOCATING";
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700157 case STATE_IDLE: return "IDLE";
158 case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
159 default: return Integer.toString(state);
160 }
161 }
162
163 private int mState;
164
165 private long mInactiveTimeout;
166 private long mNextAlarmTime;
167 private long mNextIdlePendingDelay;
168 private long mNextIdleDelay;
169
170 public final AtomicFile mConfigFile;
171
172 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700173 * Package names the system has white-listed to opt out of power save restrictions,
174 * except for device idle mode.
175 */
176 private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
177
178 /**
179 * Package names the system has white-listed to opt out of power save restrictions for
180 * all modes.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700181 */
182 private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
183
184 /**
185 * Package names the user has white-listed to opt out of power save restrictions.
186 */
187 private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
188
189 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700190 * App IDs of built-in system apps that have been white-listed except for idle modes.
191 */
192 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
193 = new SparseBooleanArray();
194
195 /**
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700196 * App IDs of built-in system apps that have been white-listed.
197 */
198 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
199
200 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700201 * App IDs that have been white-listed to opt out of power save restrictions, except
202 * for device idle modes.
203 */
204 private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
205
206 /**
207 * Current app IDs that are in the complete power save white list, but shouldn't be
208 * excluded from idle modes. This array can be shared with others because it will not be
209 * modified once set.
210 */
211 private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
212
213 /**
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700214 * App IDs that have been white-listed to opt out of power save restrictions.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700215 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700216 private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700217
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700218 /**
219 * Current app IDs that are in the complete power save white list. This array can
220 * be shared with others because it will not be modified once set.
221 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700222 private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700223
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700224 /**
225 * List of end times for UIDs that are temporarily marked as being allowed to access
226 * the network and acquire wakelocks. Times are in milliseconds.
227 */
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700228 private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
229 = new SparseArray<>();
230
231 /**
232 * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
233 */
234 Runnable mNetworkPolicyTempWhitelistCallback;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700235
236 /**
237 * Current app IDs of temporarily whitelist apps for high-priority messages.
238 */
239 private int[] mTempWhitelistAppIdArray = new int[0];
240
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700241 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
242 @Override public void onReceive(Context context, Intent intent) {
243 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
244 int plugged = intent.getIntExtra("plugged", 0);
245 updateChargingLocked(plugged != 0);
246 } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
247 synchronized (DeviceIdleController.this) {
248 stepIdleStateLocked();
249 }
250 }
251 }
252 };
253
254 private final DisplayManager.DisplayListener mDisplayListener
255 = new DisplayManager.DisplayListener() {
256 @Override public void onDisplayAdded(int displayId) {
257 }
258
259 @Override public void onDisplayRemoved(int displayId) {
260 }
261
262 @Override public void onDisplayChanged(int displayId) {
263 if (displayId == Display.DEFAULT_DISPLAY) {
264 synchronized (DeviceIdleController.this) {
265 updateDisplayLocked();
266 }
267 }
268 }
269 };
270
271 private final TriggerEventListener mSigMotionListener = new TriggerEventListener() {
272 @Override public void onTrigger(TriggerEvent event) {
273 synchronized (DeviceIdleController.this) {
274 significantMotionLocked();
275 }
276 }
277 };
278
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700279 private final LocationListener mGenericLocationListener = new LocationListener() {
280 @Override
281 public void onLocationChanged(Location location) {
282 synchronized (DeviceIdleController.this) {
283 receivedGenericLocationLocked(location);
284 }
285 }
286
287 @Override
288 public void onStatusChanged(String provider, int status, Bundle extras) {
289 }
290
291 @Override
292 public void onProviderEnabled(String provider) {
293 }
294
295 @Override
296 public void onProviderDisabled(String provider) {
297 }
298 };
299
300 private final LocationListener mGpsLocationListener = new LocationListener() {
301 @Override
302 public void onLocationChanged(Location location) {
303 synchronized (DeviceIdleController.this) {
304 receivedGpsLocationLocked(location);
305 }
306 }
307
308 @Override
309 public void onStatusChanged(String provider, int status, Bundle extras) {
310 }
311
312 @Override
313 public void onProviderEnabled(String provider) {
314 }
315
316 @Override
317 public void onProviderDisabled(String provider) {
318 }
319 };
320
Adam Lesinski31c05d12015-06-09 17:34:04 -0700321 /**
322 * All times are in milliseconds. These constants are kept synchronized with the system
323 * global Settings. Any access to this class or its fields should be done while
324 * holding the DeviceIdleController lock.
325 */
Dianne Hackborna750a632015-06-16 17:18:23 -0700326 private final class Constants extends ContentObserver {
Adam Lesinski31c05d12015-06-09 17:34:04 -0700327 // Key names stored in the settings value.
328 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
329 private static final String KEY_SENSING_TIMEOUT = "sensing_to";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700330 private static final String KEY_LOCATING_TIMEOUT = "locating_to";
331 private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700332 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
333 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
334 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
335 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
336 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
337 private static final String KEY_IDLE_TIMEOUT = "idle_to";
338 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
339 private static final String KEY_IDLE_FACTOR = "idle_factor";
340 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
341 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
342 "max_temp_app_whitelist_duration";
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700343 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
344 "mms_temp_app_whitelist_duration";
Dianne Hackborn451c3462015-07-21 17:39:46 -0700345 private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
346 "sms_temp_app_whitelist_duration";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700347
348 /**
349 * This is the time, after becoming inactive, at which we start looking at the
350 * motion sensor to determine if the device is being left alone. We don't do this
351 * immediately after going inactive just because we don't want to be continually running
352 * the significant motion sensor whenever the screen is off.
353 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
354 * @see #KEY_INACTIVE_TIMEOUT
355 */
356 public long INACTIVE_TIMEOUT;
357
358 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700359 * If we don't receive a callback from AnyMotion in this amount of time +
360 * {@link #LOCATING_TIMEOUT}, we will change from
Adam Lesinski31c05d12015-06-09 17:34:04 -0700361 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
362 * will be ignored.
363 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
364 * @see #KEY_SENSING_TIMEOUT
365 */
366 public long SENSING_TIMEOUT;
367
368 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700369 * This is how long we will wait to try to get a good location fix before going in to
370 * idle mode.
371 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
372 * @see #KEY_LOCATING_TIMEOUT
373 */
374 public long LOCATING_TIMEOUT;
375
376 /**
377 * The desired maximum accuracy (in meters) we consider the location to be good enough to go
378 * on to idle. We will be trying to get an accuracy fix at least this good or until
379 * {@link #LOCATING_TIMEOUT} expires.
380 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
381 * @see #KEY_LOCATION_ACCURACY
382 */
383 public float LOCATION_ACCURACY;
384
385 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -0700386 * This is the time, after seeing motion, that we wait after becoming inactive from
387 * that until we start looking for motion again.
388 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
389 * @see #KEY_MOTION_INACTIVE_TIMEOUT
390 */
391 public long MOTION_INACTIVE_TIMEOUT;
392
393 /**
394 * This is the time, after the inactive timeout elapses, that we will wait looking
395 * for significant motion until we truly consider the device to be idle.
396 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
397 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
398 */
399 public long IDLE_AFTER_INACTIVE_TIMEOUT;
400
401 /**
402 * This is the initial time, after being idle, that we will allow ourself to be back
403 * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
404 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
405 * @see #KEY_IDLE_PENDING_TIMEOUT
406 */
407 public long IDLE_PENDING_TIMEOUT;
408
409 /**
410 * Maximum pending idle timeout (time spent running) we will be allowed to use.
411 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
412 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
413 */
414 public long MAX_IDLE_PENDING_TIMEOUT;
415
416 /**
417 * Scaling factor to apply to current pending idle timeout each time we cycle through
418 * that state.
419 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
420 * @see #KEY_IDLE_PENDING_FACTOR
421 */
422 public float IDLE_PENDING_FACTOR;
423
424 /**
425 * This is the initial time that we want to sit in the idle state before waking up
426 * again to return to pending idle and allowing normal work to run.
427 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
428 * @see #KEY_IDLE_TIMEOUT
429 */
430 public long IDLE_TIMEOUT;
431
432 /**
433 * Maximum idle duration we will be allowed to use.
434 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
435 * @see #KEY_MAX_IDLE_TIMEOUT
436 */
437 public long MAX_IDLE_TIMEOUT;
438
439 /**
440 * Scaling factor to apply to current idle timeout each time we cycle through that state.
441 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
442 * @see #KEY_IDLE_FACTOR
443 */
444 public float IDLE_FACTOR;
445
446 /**
447 * This is the minimum time we will allow until the next upcoming alarm for us to
448 * actually go in to idle mode.
449 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
450 * @see #KEY_MIN_TIME_TO_ALARM
451 */
452 public long MIN_TIME_TO_ALARM;
453
454 /**
455 * Max amount of time to temporarily whitelist an app when it receives a high priority
456 * tickle.
457 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
458 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
459 */
460 public long MAX_TEMP_APP_WHITELIST_DURATION;
461
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700462 /**
463 * Amount of time we would like to whitelist an app that is receiving an MMS.
464 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
465 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
466 */
467 public long MMS_TEMP_APP_WHITELIST_DURATION;
468
Dianne Hackborn451c3462015-07-21 17:39:46 -0700469 /**
470 * Amount of time we would like to whitelist an app that is receiving an SMS.
471 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
472 * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
473 */
474 public long SMS_TEMP_APP_WHITELIST_DURATION;
475
Adam Lesinski31c05d12015-06-09 17:34:04 -0700476 private final ContentResolver mResolver;
477 private final KeyValueListParser mParser = new KeyValueListParser(',');
478
479 public Constants(Handler handler, ContentResolver resolver) {
480 super(handler);
481 mResolver = resolver;
482 mResolver.registerContentObserver(
483 Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), false, this);
484 updateConstants();
485 }
486
487 @Override
488 public void onChange(boolean selfChange, Uri uri) {
489 updateConstants();
490 }
491
492 private void updateConstants() {
493 synchronized (DeviceIdleController.this) {
494 try {
495 mParser.setString(Settings.Global.getString(mResolver,
496 Settings.Global.DEVICE_IDLE_CONSTANTS));
497 } catch (IllegalArgumentException e) {
498 // Failed to parse the settings string, log this and move on
499 // with defaults.
500 Slog.e(TAG, "Bad device idle settings", e);
501 }
502
503 INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
504 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
505 SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700506 !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
507 LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
508 !DEBUG ? 30 * 1000L : 15 * 1000L);
509 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700510 MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
511 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
512 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
513 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
514 IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
515 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
516 MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
517 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
518 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
519 2f);
520 IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
521 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
522 MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
523 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
524 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
525 2f);
526 MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
527 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700528 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
529 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
530 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
Dianne Hackborn0b6134b2015-07-14 18:48:07 -0700531 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
Dianne Hackborn451c3462015-07-21 17:39:46 -0700532 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
533 KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700534 }
535 }
536
537 void dump(PrintWriter pw) {
538 pw.println(" Settings:");
539
Dianne Hackborna750a632015-06-16 17:18:23 -0700540 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700541 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
542 pw.println();
543
Dianne Hackborna750a632015-06-16 17:18:23 -0700544 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700545 TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
546 pw.println();
547
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700548 pw.print(" "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
549 TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
550 pw.println();
551
552 pw.print(" "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
553 pw.print(LOCATION_ACCURACY); pw.print("m");
554 pw.println();
555
Dianne Hackborna750a632015-06-16 17:18:23 -0700556 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700557 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
558 pw.println();
559
Dianne Hackborna750a632015-06-16 17:18:23 -0700560 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700561 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
562 pw.println();
563
Dianne Hackborna750a632015-06-16 17:18:23 -0700564 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700565 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
566 pw.println();
567
Dianne Hackborna750a632015-06-16 17:18:23 -0700568 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700569 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
570 pw.println();
571
Dianne Hackborna750a632015-06-16 17:18:23 -0700572 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700573 pw.println(IDLE_PENDING_FACTOR);
574
Dianne Hackborna750a632015-06-16 17:18:23 -0700575 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700576 TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
577 pw.println();
578
Dianne Hackborna750a632015-06-16 17:18:23 -0700579 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700580 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
581 pw.println();
582
Dianne Hackborna750a632015-06-16 17:18:23 -0700583 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700584 pw.println(IDLE_FACTOR);
585
Dianne Hackborna750a632015-06-16 17:18:23 -0700586 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700587 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
588 pw.println();
589
Dianne Hackborna750a632015-06-16 17:18:23 -0700590 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700591 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
592 pw.println();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700593
594 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
595 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
596 pw.println();
Dianne Hackborn451c3462015-07-21 17:39:46 -0700597
598 pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
599 TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
600 pw.println();
Adam Lesinski31c05d12015-06-09 17:34:04 -0700601 }
602 }
603
604 private Constants mConstants;
605
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700606 @Override
607 public void onAnyMotionResult(int result) {
608 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700609 if (result == AnyMotionDetector.RESULT_MOVED) {
610 if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
611 synchronized (this) {
612 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
613 }
614 } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
615 if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
616 if (mState == STATE_SENSING) {
617 // If we are currently sensing, it is time to move to locating.
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700618 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700619 mNotMoving = true;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700620 stepIdleStateLocked();
621 }
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700622 } else if (mState == STATE_LOCATING) {
623 // If we are currently locating, note that we are not moving and step
624 // if we have located the position.
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700625 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700626 mNotMoving = true;
627 if (mLocated) {
628 stepIdleStateLocked();
629 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700630 }
631 }
632 }
633 }
634
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700635 static final int MSG_WRITE_CONFIG = 1;
636 static final int MSG_REPORT_IDLE_ON = 2;
637 static final int MSG_REPORT_IDLE_OFF = 3;
638 static final int MSG_REPORT_ACTIVE = 4;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700639 static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700640
641 final class MyHandler extends Handler {
642 MyHandler(Looper looper) {
643 super(looper);
644 }
645
646 @Override public void handleMessage(Message msg) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700647 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700648 switch (msg.what) {
649 case MSG_WRITE_CONFIG: {
650 handleWriteConfigFile();
651 } break;
652 case MSG_REPORT_IDLE_ON: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700653 EventLogTags.writeDeviceIdleOnStart();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700654 mLocalPowerManager.setDeviceIdleMode(true);
655 try {
656 mNetworkPolicyManager.setDeviceIdleMode(true);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700657 mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700658 } catch (RemoteException e) {
659 }
660 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700661 EventLogTags.writeDeviceIdleOnComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700662 } break;
663 case MSG_REPORT_IDLE_OFF: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700664 EventLogTags.writeDeviceIdleOffStart("unknown");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700665 mLocalPowerManager.setDeviceIdleMode(false);
666 try {
667 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700668 mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700669 } catch (RemoteException e) {
670 }
671 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700672 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700673 } break;
674 case MSG_REPORT_ACTIVE: {
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700675 String activeReason = (String)msg.obj;
676 int activeUid = msg.arg1;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700677 boolean needBroadcast = msg.arg2 != 0;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700678 EventLogTags.writeDeviceIdleOffStart(
679 activeReason != null ? activeReason : "unknown");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700680 mLocalPowerManager.setDeviceIdleMode(false);
681 try {
682 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700683 mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700684 } catch (RemoteException e) {
685 }
686 if (needBroadcast) {
687 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
688 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700689 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700690 } break;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700691 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
692 int uid = msg.arg1;
693 checkTempAppWhitelistTimeout(uid);
694 } break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700695 }
696 }
697 }
698
699 final MyHandler mHandler;
700
701 private final class BinderService extends IDeviceIdleController.Stub {
702 @Override public void addPowerSaveWhitelistApp(String name) {
703 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
704 null);
705 addPowerSaveWhitelistAppInternal(name);
706 }
707
708 @Override public void removePowerSaveWhitelistApp(String name) {
709 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
710 null);
711 removePowerSaveWhitelistAppInternal(name);
712 }
713
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700714 @Override public String[] getSystemPowerWhitelistExceptIdle() {
715 return getSystemPowerWhitelistExceptIdleInternal();
716 }
717
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700718 @Override public String[] getSystemPowerWhitelist() {
719 return getSystemPowerWhitelistInternal();
720 }
721
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700722 @Override public String[] getFullPowerWhitelistExceptIdle() {
723 return getFullPowerWhitelistExceptIdleInternal();
724 }
725
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700726 @Override public String[] getFullPowerWhitelist() {
727 return getFullPowerWhitelistInternal();
728 }
729
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700730 @Override public int[] getAppIdWhitelistExceptIdle() {
731 return getAppIdWhitelistExceptIdleInternal();
732 }
733
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700734 @Override public int[] getAppIdWhitelist() {
735 return getAppIdWhitelistInternal();
736 }
737
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700738 @Override public int[] getAppIdTempWhitelist() {
739 return getAppIdTempWhitelistInternal();
740 }
741
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700742 @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
743 return isPowerSaveWhitelistExceptIdleAppInternal(name);
744 }
745
Amith Yamasani06bf8242015-05-08 16:36:21 -0700746 @Override public boolean isPowerSaveWhitelistApp(String name) {
747 return isPowerSaveWhitelistAppInternal(name);
748 }
749
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700750 @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700751 int userId, String reason) throws RemoteException {
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700752 getContext().enforceCallingPermission(
753 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
754 "No permission to change device idle whitelist");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700755 final int callingUid = Binder.getCallingUid();
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700756 userId = ActivityManagerNative.getDefault().handleIncomingUser(
757 Binder.getCallingPid(),
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700758 callingUid,
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700759 userId,
760 /*allowAll=*/ false,
761 /*requireFull=*/ false,
Dianne Hackborna750a632015-06-16 17:18:23 -0700762 "addPowerSaveTempWhitelistApp", null);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700763 final long token = Binder.clearCallingIdentity();
764 try {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700765 DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700766 packageName, duration, userId, true, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700767 } finally {
768 Binder.restoreCallingIdentity(token);
769 }
770 }
771
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700772 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
773 int userId, String reason) throws RemoteException {
774 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
775 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
776 return duration;
777 }
778
Dianne Hackborn451c3462015-07-21 17:39:46 -0700779 @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
780 int userId, String reason) throws RemoteException {
781 long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
782 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
783 return duration;
784 }
785
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700786 @Override public void exitIdle(String reason) {
787 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
788 null);
789 exitIdleInternal(reason);
790 }
791
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700792 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
793 DeviceIdleController.this.dump(fd, pw, args);
794 }
795 }
796
Dianne Hackborna750a632015-06-16 17:18:23 -0700797 public final class LocalService {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700798 public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
799 String reason) {
800 addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
801 }
802
803 public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
804 setNetworkPolicyTempWhitelistCallbackInternal(callback);
Dianne Hackborna750a632015-06-16 17:18:23 -0700805 }
806 }
807
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700808 public DeviceIdleController(Context context) {
809 super(context);
810 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
811 mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
812 }
813
814 private static File getSystemDir() {
815 return new File(Environment.getDataDirectory(), "system");
816 }
817
818 @Override
819 public void onStart() {
820 final PackageManager pm = getContext().getPackageManager();
821
822 synchronized (this) {
Dianne Hackborn92617032015-06-19 15:32:19 -0700823 mEnabled = getContext().getResources().getBoolean(
824 com.android.internal.R.bool.config_enableAutoPowerModes);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700825 SystemConfig sysConfig = SystemConfig.getInstance();
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700826 ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
827 for (int i=0; i<allowPowerExceptIdle.size(); i++) {
828 String pkg = allowPowerExceptIdle.valueAt(i);
829 try {
830 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
831 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
832 int appid = UserHandle.getAppId(ai.uid);
833 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
834 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
835 }
836 } catch (PackageManager.NameNotFoundException e) {
837 }
838 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700839 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
840 for (int i=0; i<allowPower.size(); i++) {
841 String pkg = allowPower.valueAt(i);
842 try {
843 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
844 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700845 int appid = UserHandle.getAppId(ai.uid);
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700846 // These apps are on both the whitelist-except-idle as well
847 // as the full whitelist, so they apply in all cases.
848 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
849 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700850 mPowerSaveWhitelistApps.put(ai.packageName, appid);
851 mPowerSaveWhitelistSystemAppIds.put(appid, true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700852 }
853 } catch (PackageManager.NameNotFoundException e) {
854 }
855 }
856
Adam Lesinski31c05d12015-06-09 17:34:04 -0700857 mConstants = new Constants(mHandler, getContext().getContentResolver());
858
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700859 readConfigFileLocked();
860 updateWhitelistAppIdsLocked();
861
862 mScreenOn = true;
863 // Start out assuming we are charging. If we aren't, we will at least get
864 // a battery update the next time the level drops.
865 mCharging = true;
866 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -0700867 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700868 }
869
Dianne Hackborn1958e5e2015-06-12 18:11:41 -0700870 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
Dianne Hackborna750a632015-06-16 17:18:23 -0700871 publishLocalService(LocalService.class, new LocalService());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700872 }
873
874 @Override
875 public void onBootPhase(int phase) {
876 if (phase == PHASE_SYSTEM_SERVICES_READY) {
877 synchronized (this) {
878 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
879 mBatteryStats = BatteryStatsService.getService();
880 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
881 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700882 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700883 mDisplayManager = (DisplayManager) getContext().getSystemService(
884 Context.DISPLAY_SERVICE);
885 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
Joe LaPenna23d681b2015-08-27 15:12:11 -0700886 int sigMotionSensorId = getContext().getResources().getInteger(
887 com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
888 if (sigMotionSensorId > 0) {
889 mSigMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
890 }
891 if (mSigMotionSensor == null && getContext().getResources().getBoolean(
892 com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
893 mSigMotionSensor = mSensorManager.getDefaultSensor(
894 Sensor.TYPE_WRIST_TILT_GESTURE);
895 }
896 if (mSigMotionSensor == null) {
897 // As a last ditch, fall back to SMD.
898 mSigMotionSensor = mSensorManager.getDefaultSensor(
899 Sensor.TYPE_SIGNIFICANT_MOTION);
900 }
901 if (getContext().getResources().getBoolean(
902 com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
903 mLocationManager = (LocationManager) getContext().getSystemService(
904 Context.LOCATION_SERVICE);
905 mLocationRequest = new LocationRequest()
906 .setQuality(LocationRequest.ACCURACY_FINE)
907 .setInterval(0)
908 .setFastestInterval(0)
909 .setNumUpdates(1);
910 }
911
912 float angleThreshold = getContext().getResources().getInteger(
913 com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700914 mAnyMotionDetector = new AnyMotionDetector(
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700915 (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
Joe LaPenna23d681b2015-08-27 15:12:11 -0700916 mHandler, mSensorManager, this, angleThreshold);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700917
918 Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
919 .setPackage("android")
920 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
921 mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
922
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700923 Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)
924 .setPackage("android")
925 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
926 mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
927
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700928 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700929 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
930 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700931
932 IntentFilter filter = new IntentFilter();
933 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
934 filter.addAction(ACTION_STEP_IDLE_STATE);
935 getContext().registerReceiver(mReceiver, filter);
936
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700937 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700938
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700939 mDisplayManager.registerDisplayListener(mDisplayListener, null);
940 updateDisplayLocked();
941 }
942 }
943 }
944
945 public boolean addPowerSaveWhitelistAppInternal(String name) {
946 synchronized (this) {
947 try {
948 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0);
949 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
950 reportPowerSaveWhitelistChangedLocked();
951 updateWhitelistAppIdsLocked();
952 writeConfigFileLocked();
953 }
954 return true;
955 } catch (PackageManager.NameNotFoundException e) {
956 return false;
957 }
958 }
959 }
960
961 public boolean removePowerSaveWhitelistAppInternal(String name) {
962 synchronized (this) {
963 if (mPowerSaveWhitelistUserApps.remove(name) != null) {
964 reportPowerSaveWhitelistChangedLocked();
965 updateWhitelistAppIdsLocked();
966 writeConfigFileLocked();
967 return true;
968 }
969 }
970 return false;
971 }
972
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700973 public String[] getSystemPowerWhitelistExceptIdleInternal() {
974 synchronized (this) {
975 int size = mPowerSaveWhitelistAppsExceptIdle.size();
976 String[] apps = new String[size];
977 for (int i = 0; i < size; i++) {
978 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
979 }
980 return apps;
981 }
982 }
983
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700984 public String[] getSystemPowerWhitelistInternal() {
985 synchronized (this) {
986 int size = mPowerSaveWhitelistApps.size();
987 String[] apps = new String[size];
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700988 for (int i = 0; i < size; i++) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700989 apps[i] = mPowerSaveWhitelistApps.keyAt(i);
990 }
991 return apps;
992 }
993 }
994
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700995 public String[] getFullPowerWhitelistExceptIdleInternal() {
996 synchronized (this) {
997 int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
998 String[] apps = new String[size];
999 int cur = 0;
1000 for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
1001 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1002 cur++;
1003 }
1004 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1005 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1006 cur++;
1007 }
1008 return apps;
1009 }
1010 }
1011
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001012 public String[] getFullPowerWhitelistInternal() {
1013 synchronized (this) {
1014 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
1015 String[] apps = new String[size];
1016 int cur = 0;
1017 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
1018 apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
1019 cur++;
1020 }
1021 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1022 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1023 cur++;
1024 }
1025 return apps;
1026 }
1027 }
1028
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001029 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
1030 synchronized (this) {
1031 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
1032 || mPowerSaveWhitelistUserApps.containsKey(packageName);
1033 }
1034 }
1035
Amith Yamasani06bf8242015-05-08 16:36:21 -07001036 public boolean isPowerSaveWhitelistAppInternal(String packageName) {
1037 synchronized (this) {
1038 return mPowerSaveWhitelistApps.containsKey(packageName)
1039 || mPowerSaveWhitelistUserApps.containsKey(packageName);
1040 }
1041 }
1042
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001043 public int[] getAppIdWhitelistExceptIdleInternal() {
1044 synchronized (this) {
1045 return mPowerSaveWhitelistExceptIdleAppIdArray;
1046 }
1047 }
1048
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001049 public int[] getAppIdWhitelistInternal() {
1050 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001051 return mPowerSaveWhitelistAllAppIdArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001052 }
1053 }
1054
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001055 public int[] getAppIdTempWhitelistInternal() {
1056 synchronized (this) {
1057 return mTempWhitelistAppIdArray;
1058 }
1059 }
1060
1061 /**
1062 * Adds an app to the temporary whitelist and resets the endTime for granting the
1063 * app an exemption to access network and acquire wakelocks.
1064 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001065 public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001066 long duration, int userId, boolean sync, String reason) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001067 try {
1068 int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
1069 int appId = UserHandle.getAppId(uid);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001070 addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001071 } catch (NameNotFoundException e) {
1072 }
1073 }
1074
Dianne Hackborna750a632015-06-16 17:18:23 -07001075 /**
1076 * Adds an app to the temporary whitelist and resets the endTime for granting the
1077 * app an exemption to access network and acquire wakelocks.
1078 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001079 public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001080 long duration, boolean sync, String reason) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001081 final long timeNow = SystemClock.elapsedRealtime();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001082 Runnable networkPolicyTempWhitelistCallback = null;
Dianne Hackborna750a632015-06-16 17:18:23 -07001083 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001084 int callingAppId = UserHandle.getAppId(callingUid);
1085 if (callingAppId >= Process.FIRST_APPLICATION_UID) {
1086 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
1087 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
1088 + " is not on whitelist");
1089 }
1090 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001091 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001092 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
1093 final boolean newEntry = entry == null;
Dianne Hackborna750a632015-06-16 17:18:23 -07001094 // Set the new end time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001095 if (newEntry) {
1096 entry = new Pair<>(new MutableLong(0), reason);
1097 mTempWhitelistAppIdEndTimes.put(appId, entry);
1098 }
1099 entry.first.value = timeNow + duration;
Dianne Hackborna750a632015-06-16 17:18:23 -07001100 if (DEBUG) {
1101 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
1102 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001103 if (newEntry) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001104 // No pending timeout for the app id, post a delayed message
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001105 try {
1106 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
1107 reason, appId);
1108 } catch (RemoteException e) {
1109 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001110 postTempActiveTimeoutMessage(appId, duration);
1111 updateTempWhitelistAppIdsLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001112 if (mNetworkPolicyTempWhitelistCallback != null) {
1113 if (!sync) {
1114 mHandler.post(mNetworkPolicyTempWhitelistCallback);
1115 } else {
1116 networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
1117 }
1118 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001119 reportTempWhitelistChangedLocked();
1120 }
1121 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001122 if (networkPolicyTempWhitelistCallback != null) {
1123 networkPolicyTempWhitelistCallback.run();
1124 }
1125 }
1126
1127 public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
1128 synchronized (this) {
1129 mNetworkPolicyTempWhitelistCallback = callback;
1130 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001131 }
1132
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001133 private void postTempActiveTimeoutMessage(int uid, long delay) {
1134 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
1135 delay);
1136 }
1137
1138 void checkTempAppWhitelistTimeout(int uid) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001139 final long timeNow = SystemClock.elapsedRealtime();
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001140 synchronized (this) {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001141 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
1142 if (entry == null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001143 // Nothing to do
1144 return;
1145 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001146 if (timeNow >= entry.first.value) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001147 mTempWhitelistAppIdEndTimes.delete(uid);
1148 if (DEBUG) {
1149 Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
1150 }
1151 updateTempWhitelistAppIdsLocked();
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001152 if (mNetworkPolicyTempWhitelistCallback != null) {
1153 mHandler.post(mNetworkPolicyTempWhitelistCallback);
1154 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001155 reportTempWhitelistChangedLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001156 try {
1157 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
1158 entry.second, uid);
1159 } catch (RemoteException e) {
1160 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001161 } else {
1162 // Need more time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001163 postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001164 }
1165 }
1166 }
1167
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001168 public void exitIdleInternal(String reason) {
1169 synchronized (this) {
1170 becomeActiveLocked(reason, Binder.getCallingUid());
1171 }
1172 }
1173
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001174 void updateDisplayLocked() {
1175 mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
1176 // We consider any situation where the display is showing something to be it on,
1177 // because if there is anything shown we are going to be updating it at some
1178 // frequency so can't be allowed to go into deep sleeps.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001179 boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001180 if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001181 if (!screenOn && mScreenOn) {
1182 mScreenOn = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001183 if (!mForceIdle) {
1184 becomeInactiveIfAppropriateLocked();
1185 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001186 } else if (screenOn) {
1187 mScreenOn = true;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001188 if (!mForceIdle) {
1189 becomeActiveLocked("screen", Process.myUid());
1190 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001191 }
1192 }
1193
1194 void updateChargingLocked(boolean charging) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001195 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001196 if (!charging && mCharging) {
1197 mCharging = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001198 if (!mForceIdle) {
1199 becomeInactiveIfAppropriateLocked();
1200 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001201 } else if (charging) {
1202 mCharging = charging;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001203 if (!mForceIdle) {
1204 becomeActiveLocked("charging", Process.myUid());
1205 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001206 }
1207 }
1208
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001209 void scheduleReportActiveLocked(String activeReason, int activeUid) {
1210 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
1211 mState == STATE_IDLE ? 1 : 0, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001212 mHandler.sendMessage(msg);
1213 }
1214
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001215 void becomeActiveLocked(String activeReason, int activeUid) {
1216 if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001217 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001218 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
1219 scheduleReportActiveLocked(activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001220 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -07001221 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001222 resetIdleManagementLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001223 }
1224 }
1225
1226 void becomeInactiveIfAppropriateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001227 if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001228 if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001229 // Screen has turned off; we are now going to become inactive and start
1230 // waiting to see if we will ultimately go idle.
1231 mState = STATE_INACTIVE;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001232 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001233 resetIdleManagementLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001234 scheduleAlarmLocked(mInactiveTimeout, false);
1235 EventLogTags.writeDeviceIdle(mState, "no activity");
1236 }
1237 }
1238
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001239 void resetIdleManagementLocked() {
1240 mNextIdlePendingDelay = 0;
1241 mNextIdleDelay = 0;
1242 cancelAlarmLocked();
1243 cancelSensingAlarmLocked();
1244 cancelLocatingLocked();
1245 stopMonitoringSignificantMotion();
1246 mAnyMotionDetector.stop();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001247 }
1248
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001249 void exitForceIdleLocked() {
1250 if (mForceIdle) {
1251 mForceIdle = false;
1252 if (mScreenOn || mCharging) {
1253 becomeActiveLocked("exit-force-idle", Process.myUid());
1254 }
1255 }
1256 }
1257
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001258 void stepIdleStateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001259 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001260 EventLogTags.writeDeviceIdleStep();
1261
1262 final long now = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001263 if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001264 // Whoops, there is an upcoming alarm. We don't actually want to go idle.
1265 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001266 becomeActiveLocked("alarm", Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001267 }
1268 return;
1269 }
1270
1271 switch (mState) {
1272 case STATE_INACTIVE:
1273 // We have now been inactive long enough, it is time to start looking
1274 // for significant motion and sleep some more while doing so.
1275 startMonitoringSignificantMotion();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001276 scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001277 // Reset the upcoming idle delays.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001278 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
1279 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001280 mState = STATE_IDLE_PENDING;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001281 if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001282 EventLogTags.writeDeviceIdle(mState, "step");
1283 break;
1284 case STATE_IDLE_PENDING:
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001285 mState = STATE_SENSING;
1286 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001287 EventLogTags.writeDeviceIdle(mState, "step");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001288 scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001289 cancelSensingAlarmLocked();
1290 cancelLocatingLocked();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001291 mAnyMotionDetector.checkForAnyMotion();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001292 mNotMoving = false;
1293 mLocated = false;
1294 mLastGenericLocation = null;
1295 mLastGpsLocation = null;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001296 break;
1297 case STATE_SENSING:
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001298 mState = STATE_LOCATING;
1299 if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
1300 EventLogTags.writeDeviceIdle(mState, "step");
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001301 cancelSensingAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001302 scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001303 if (mLocationManager != null
1304 && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
1305 mLocationManager.requestLocationUpdates(mLocationRequest,
1306 mGenericLocationListener, mHandler.getLooper());
1307 mLocating = true;
1308 } else {
1309 mHasNetworkLocation = false;
1310 }
1311 if (mLocationManager != null
1312 && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
1313 mHasGps = true;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001314 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
1315 mGpsLocationListener, mHandler.getLooper());
Joe LaPenna23d681b2015-08-27 15:12:11 -07001316 mLocating = true;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001317 } else {
Joe LaPenna23d681b2015-08-27 15:12:11 -07001318 mHasGps = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001319 }
Joe LaPenna23d681b2015-08-27 15:12:11 -07001320 // If we have a location provider, we're all set, the listeners will move state
1321 // forward.
1322 if (mLocating) {
1323 break;
1324 }
1325
1326 // Otherwise, we have to move from locating into idle maintenance.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001327 case STATE_LOCATING:
1328 cancelSensingAlarmLocked();
1329 cancelLocatingLocked();
1330 mAnyMotionDetector.stop();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001331 case STATE_IDLE_MAINTENANCE:
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001332 scheduleAlarmLocked(mNextIdleDelay, true);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001333 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
1334 " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001335 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001336 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001337 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001338 mState = STATE_IDLE;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001339 EventLogTags.writeDeviceIdle(mState, "step");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001340 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
1341 break;
1342 case STATE_IDLE:
1343 // We have been idling long enough, now it is time to do some work.
1344 scheduleAlarmLocked(mNextIdlePendingDelay, false);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001345 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
1346 "Next alarm in " + mNextIdlePendingDelay + " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001347 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
1348 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001349 mState = STATE_IDLE_MAINTENANCE;
1350 EventLogTags.writeDeviceIdle(mState, "step");
1351 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1352 break;
1353 }
1354 }
1355
1356 void significantMotionLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001357 if (DEBUG) Slog.d(TAG, "significantMotionLocked()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001358 // When the sensor goes off, its trigger is automatically removed.
1359 mSigMotionActive = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001360 handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
1361 }
1362
1363 void handleMotionDetectedLocked(long timeout, String type) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001364 // The device is not yet active, so we want to go back to the pending idle
1365 // state to wait again for no motion. Note that we only monitor for significant
1366 // motion after moving out of the inactive state, so no need to worry about that.
1367 if (mState != STATE_ACTIVE) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001368 scheduleReportActiveLocked(type, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001369 mState = STATE_ACTIVE;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001370 mInactiveTimeout = timeout;
1371 EventLogTags.writeDeviceIdle(mState, type);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001372 becomeInactiveIfAppropriateLocked();
1373 }
1374 }
1375
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001376 void receivedGenericLocationLocked(Location location) {
1377 if (mState != STATE_LOCATING) {
1378 cancelLocatingLocked();
1379 return;
1380 }
1381 if (DEBUG) Slog.d(TAG, "Generic location: " + location);
1382 mLastGenericLocation = new Location(location);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001383 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001384 return;
1385 }
1386 mLocated = true;
1387 if (mNotMoving) {
1388 stepIdleStateLocked();
1389 }
1390 }
1391
1392 void receivedGpsLocationLocked(Location location) {
1393 if (mState != STATE_LOCATING) {
1394 cancelLocatingLocked();
1395 return;
1396 }
1397 if (DEBUG) Slog.d(TAG, "GPS location: " + location);
1398 mLastGpsLocation = new Location(location);
1399 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
1400 return;
1401 }
1402 mLocated = true;
1403 if (mNotMoving) {
1404 stepIdleStateLocked();
1405 }
1406 }
1407
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001408 void startMonitoringSignificantMotion() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001409 if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001410 if (mSigMotionSensor != null && !mSigMotionActive) {
1411 mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor);
1412 mSigMotionActive = true;
1413 }
1414 }
1415
1416 void stopMonitoringSignificantMotion() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001417 if (DEBUG) Slog.d(TAG, "stopMonitoringSignificantMotion()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001418 if (mSigMotionActive) {
1419 mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor);
1420 mSigMotionActive = false;
1421 }
1422 }
1423
1424 void cancelAlarmLocked() {
1425 if (mNextAlarmTime != 0) {
1426 mNextAlarmTime = 0;
1427 mAlarmManager.cancel(mAlarmIntent);
1428 }
1429 }
1430
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001431 void cancelSensingAlarmLocked() {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001432 if (mSensing) {
1433 if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
1434 mAlarmManager.cancel(mSensingAlarmIntent);
1435 mSensing = false;
1436 }
1437 }
1438
1439 void cancelLocatingLocked() {
1440 if (mLocating) {
1441 mLocationManager.removeUpdates(mGenericLocationListener);
1442 mLocationManager.removeUpdates(mGpsLocationListener);
1443 mLocating = false;
1444 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001445 }
1446
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001447 void scheduleAlarmLocked(long delay, boolean idleUntil) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001448 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001449 if (mSigMotionSensor == null) {
Joe LaPenna23d681b2015-08-27 15:12:11 -07001450 // If there is no motion sensor on this device, then we won't schedule
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001451 // alarms, because we can't determine if the device is not moving. This effectively
Joe LaPenna23d681b2015-08-27 15:12:11 -07001452 // turns off normal execution of device idling, although it is still possible to
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001453 // manually poke it by pretending like the alarm is going off.
1454 return;
1455 }
1456 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1457 if (idleUntil) {
1458 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1459 mNextAlarmTime, mAlarmIntent);
1460 } else {
1461 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1462 mNextAlarmTime, mAlarmIntent);
1463 }
1464 }
1465
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001466 void scheduleSensingAlarmLocked(long delay) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001467 if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
1468 cancelSensingAlarmLocked();
1469 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1470 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1471 mNextAlarmTime, mSensingAlarmIntent);
1472 mSensing = true;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001473 }
1474
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001475 private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
1476 ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
1477 outAppIds.clear();
1478 for (int i=0; i<systemApps.size(); i++) {
1479 outAppIds.put(systemApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001480 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001481 for (int i=0; i<userApps.size(); i++) {
1482 outAppIds.put(userApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001483 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001484 int size = outAppIds.size();
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001485 int[] appids = new int[size];
1486 for (int i = 0; i < size; i++) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001487 appids[i] = outAppIds.keyAt(i);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001488 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001489 return appids;
1490 }
1491
1492 private void updateWhitelistAppIdsLocked() {
1493 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
1494 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
1495 mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
1496 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001497 if (mLocalPowerManager != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001498 if (DEBUG) {
1499 Slog.d(TAG, "Setting wakelock whitelist to "
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001500 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001501 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001502 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001503 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001504 }
1505
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001506 private void updateTempWhitelistAppIdsLocked() {
1507 final int size = mTempWhitelistAppIdEndTimes.size();
1508 if (mTempWhitelistAppIdArray.length != size) {
1509 mTempWhitelistAppIdArray = new int[size];
1510 }
1511 for (int i = 0; i < size; i++) {
1512 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
1513 }
1514 if (mLocalPowerManager != null) {
1515 if (DEBUG) {
1516 Slog.d(TAG, "Setting wakelock temp whitelist to "
1517 + Arrays.toString(mTempWhitelistAppIdArray));
1518 }
1519 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
1520 }
1521 }
1522
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001523 private void reportPowerSaveWhitelistChangedLocked() {
1524 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
1525 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001526 getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
1527 }
1528
1529 private void reportTempWhitelistChangedLocked() {
1530 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
1531 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1532 getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001533 }
1534
1535 void readConfigFileLocked() {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001536 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001537 mPowerSaveWhitelistUserApps.clear();
1538 FileInputStream stream;
1539 try {
1540 stream = mConfigFile.openRead();
1541 } catch (FileNotFoundException e) {
1542 return;
1543 }
1544 try {
1545 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001546 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001547 readConfigFileLocked(parser);
1548 } catch (XmlPullParserException e) {
1549 } finally {
1550 try {
1551 stream.close();
1552 } catch (IOException e) {
1553 }
1554 }
1555
1556 }
1557
1558 private void readConfigFileLocked(XmlPullParser parser) {
1559 final PackageManager pm = getContext().getPackageManager();
1560
1561 try {
1562 int type;
1563 while ((type = parser.next()) != XmlPullParser.START_TAG
1564 && type != XmlPullParser.END_DOCUMENT) {
1565 ;
1566 }
1567
1568 if (type != XmlPullParser.START_TAG) {
1569 throw new IllegalStateException("no start tag found");
1570 }
1571
1572 int outerDepth = parser.getDepth();
1573 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1574 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1575 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1576 continue;
1577 }
1578
1579 String tagName = parser.getName();
1580 if (tagName.equals("wl")) {
1581 String name = parser.getAttributeValue(null, "n");
1582 if (name != null) {
1583 try {
1584 ApplicationInfo ai = pm.getApplicationInfo(name, 0);
1585 mPowerSaveWhitelistUserApps.put(ai.packageName,
1586 UserHandle.getAppId(ai.uid));
1587 } catch (PackageManager.NameNotFoundException e) {
1588 }
1589 }
1590 } else {
1591 Slog.w(TAG, "Unknown element under <config>: "
1592 + parser.getName());
1593 XmlUtils.skipCurrentTag(parser);
1594 }
1595 }
1596
1597 } catch (IllegalStateException e) {
1598 Slog.w(TAG, "Failed parsing config " + e);
1599 } catch (NullPointerException e) {
1600 Slog.w(TAG, "Failed parsing config " + e);
1601 } catch (NumberFormatException e) {
1602 Slog.w(TAG, "Failed parsing config " + e);
1603 } catch (XmlPullParserException e) {
1604 Slog.w(TAG, "Failed parsing config " + e);
1605 } catch (IOException e) {
1606 Slog.w(TAG, "Failed parsing config " + e);
1607 } catch (IndexOutOfBoundsException e) {
1608 Slog.w(TAG, "Failed parsing config " + e);
1609 }
1610 }
1611
1612 void writeConfigFileLocked() {
1613 mHandler.removeMessages(MSG_WRITE_CONFIG);
1614 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
1615 }
1616
1617 void handleWriteConfigFile() {
1618 final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
1619
1620 try {
1621 synchronized (this) {
1622 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001623 out.setOutput(memStream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001624 writeConfigFileLocked(out);
1625 }
1626 } catch (IOException e) {
1627 }
1628
1629 synchronized (mConfigFile) {
1630 FileOutputStream stream = null;
1631 try {
1632 stream = mConfigFile.startWrite();
1633 memStream.writeTo(stream);
1634 stream.flush();
1635 FileUtils.sync(stream);
1636 stream.close();
1637 mConfigFile.finishWrite(stream);
1638 } catch (IOException e) {
1639 Slog.w(TAG, "Error writing config file", e);
1640 mConfigFile.failWrite(stream);
1641 }
1642 }
1643 }
1644
1645 void writeConfigFileLocked(XmlSerializer out) throws IOException {
1646 out.startDocument(null, true);
1647 out.startTag(null, "config");
1648 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
1649 String name = mPowerSaveWhitelistUserApps.keyAt(i);
1650 out.startTag(null, "wl");
1651 out.attribute(null, "n", name);
1652 out.endTag(null, "wl");
1653 }
1654 out.endTag(null, "config");
1655 out.endDocument();
1656 }
1657
1658 private void dumpHelp(PrintWriter pw) {
1659 pw.println("Device idle controller (deviceidle) dump options:");
1660 pw.println(" [-h] [CMD]");
1661 pw.println(" -h: print this help text.");
1662 pw.println("Commands:");
1663 pw.println(" step");
1664 pw.println(" Immediately step to next state, without waiting for alarm.");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001665 pw.println(" force-idle");
1666 pw.println(" Force directly into idle mode, regardless of other device state.");
1667 pw.println(" Use \"step\" to get out.");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001668 pw.println(" disable");
1669 pw.println(" Completely disable device idle mode.");
1670 pw.println(" enable");
1671 pw.println(" Re-enable device idle mode after it had previously been disabled.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001672 pw.println(" enabled");
1673 pw.println(" Print 1 if device idle mode is currently enabled, else 0.");
Dianne Hackborn1b139682015-07-06 15:13:37 -07001674 pw.println(" whitelist");
1675 pw.println(" Print currently whitelisted apps.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001676 pw.println(" whitelist [package ...]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001677 pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001678 pw.println(" tempwhitelist [package ..]");
1679 pw.println(" Temporarily place packages in whitelist for 10 seconds.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001680 }
1681
1682 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1683 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1684 != PackageManager.PERMISSION_GRANTED) {
1685 pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
1686 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1687 + " without permission " + android.Manifest.permission.DUMP);
1688 return;
1689 }
1690
1691 if (args != null) {
Xiaohui Chen7c696362015-09-16 09:56:14 -07001692 int userId = UserHandle.USER_SYSTEM;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001693 for (int i=0; i<args.length; i++) {
1694 String arg = args[i];
1695 if ("-h".equals(arg)) {
1696 dumpHelp(pw);
1697 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001698 } else if ("-u".equals(arg)) {
1699 i++;
1700 if (i < args.length) {
1701 arg = args[i];
1702 userId = Integer.parseInt(arg);
1703 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001704 } else if ("-a".equals(arg)) {
1705 // Ignore, we always dump all.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001706 } else if ("step".equals(arg)) {
1707 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001708 long token = Binder.clearCallingIdentity();
1709 try {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001710 exitForceIdleLocked();
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001711 stepIdleStateLocked();
1712 pw.print("Stepped to: "); pw.println(stateToString(mState));
1713 } finally {
1714 Binder.restoreCallingIdentity(token);
1715 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001716 }
1717 return;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001718 } else if ("force-idle".equals(arg)) {
1719 synchronized (this) {
1720 long token = Binder.clearCallingIdentity();
1721 try {
1722 if (!mEnabled) {
1723 pw.println("Unable to go idle; not enabled");
1724 return;
1725 }
1726 mForceIdle = true;
1727 becomeInactiveIfAppropriateLocked();
1728 int curState = mState;
1729 while (curState != STATE_IDLE) {
1730 stepIdleStateLocked();
1731 if (curState == mState) {
1732 pw.print("Unable to go idle; stopped at ");
1733 pw.println(stateToString(mState));
1734 exitForceIdleLocked();
1735 return;
1736 }
1737 curState = mState;
1738 }
1739 pw.println("Now forced in to idle mode");
1740 } finally {
1741 Binder.restoreCallingIdentity(token);
1742 }
1743 }
1744 return;
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001745 } else if ("disable".equals(arg)) {
1746 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001747 long token = Binder.clearCallingIdentity();
1748 try {
1749 if (mEnabled) {
1750 mEnabled = false;
1751 becomeActiveLocked("disabled", Process.myUid());
1752 pw.println("Idle mode disabled");
1753 }
1754 } finally {
1755 Binder.restoreCallingIdentity(token);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001756 }
1757 }
1758 return;
1759 } else if ("enable".equals(arg)) {
1760 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001761 long token = Binder.clearCallingIdentity();
1762 try {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001763 exitForceIdleLocked();
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001764 if (!mEnabled) {
1765 mEnabled = true;
1766 becomeInactiveIfAppropriateLocked();
1767 pw.println("Idle mode enabled");
1768 }
1769 } finally {
1770 Binder.restoreCallingIdentity(token);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001771 }
1772 }
1773 return;
Dianne Hackborn92617032015-06-19 15:32:19 -07001774 } else if ("enabled".equals(arg)) {
1775 synchronized (this) {
1776 pw.println(mEnabled ? "1" : " 0");
1777 }
1778 return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001779 } else if ("whitelist".equals(arg)) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001780 long token = Binder.clearCallingIdentity();
1781 try {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001782 i++;
Dianne Hackborn1b139682015-07-06 15:13:37 -07001783 if (i < args.length) {
1784 while (i < args.length) {
1785 arg = args[i];
1786 i++;
1787 if (arg.length() < 1 || (arg.charAt(0) != '-'
1788 && arg.charAt(0) != '+')) {
1789 pw.println("Package must be prefixed with + or -: " + arg);
1790 return;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001791 }
Dianne Hackborn1b139682015-07-06 15:13:37 -07001792 char op = arg.charAt(0);
1793 String pkg = arg.substring(1);
1794 if (op == '+') {
1795 if (addPowerSaveWhitelistAppInternal(pkg)) {
1796 pw.println("Added: " + pkg);
1797 } else {
1798 pw.println("Unknown package: " + pkg);
1799 }
1800 } else {
1801 if (removePowerSaveWhitelistAppInternal(pkg)) {
1802 pw.println("Removed: " + pkg);
1803 }
1804 }
1805 }
1806 } else {
1807 synchronized (this) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001808 for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
1809 pw.print("system-excidle,");
1810 pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
1811 pw.print(",");
1812 pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
1813 }
Dianne Hackborn1b139682015-07-06 15:13:37 -07001814 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
1815 pw.print("system,");
1816 pw.print(mPowerSaveWhitelistApps.keyAt(j));
1817 pw.print(",");
1818 pw.println(mPowerSaveWhitelistApps.valueAt(j));
1819 }
1820 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
1821 pw.print("user,");
1822 pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
1823 pw.print(",");
1824 pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001825 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001826 }
1827 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001828 } finally {
1829 Binder.restoreCallingIdentity(token);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001830 }
1831 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001832 } else if ("tempwhitelist".equals(arg)) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001833 long token = Binder.clearCallingIdentity();
1834 try {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001835 i++;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001836 if (i >= args.length) {
1837 pw.println("At least one package name must be specified");
1838 return;
1839 }
1840 while (i < args.length) {
1841 arg = args[i];
1842 i++;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001843 addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId, true,
1844 "shell");
1845 pw.println("Added: " + arg);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001846 }
1847 } finally {
1848 Binder.restoreCallingIdentity(token);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001849 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001850 return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001851 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
1852 pw.println("Unknown option: " + arg);
1853 return;
1854 } else {
1855 pw.println("Unknown command: " + arg);
1856 return;
1857 }
1858 }
1859 }
1860
1861 synchronized (this) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001862 mConstants.dump(pw);
1863
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001864 int size = mPowerSaveWhitelistAppsExceptIdle.size();
1865 if (size > 0) {
1866 pw.println(" Whitelist (except idle) system apps:");
1867 for (int i = 0; i < size; i++) {
1868 pw.print(" ");
1869 pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
1870 }
1871 }
1872 size = mPowerSaveWhitelistApps.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001873 if (size > 0) {
1874 pw.println(" Whitelist system apps:");
1875 for (int i = 0; i < size; i++) {
1876 pw.print(" ");
1877 pw.println(mPowerSaveWhitelistApps.keyAt(i));
1878 }
1879 }
1880 size = mPowerSaveWhitelistUserApps.size();
1881 if (size > 0) {
1882 pw.println(" Whitelist user apps:");
1883 for (int i = 0; i < size; i++) {
1884 pw.print(" ");
1885 pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
1886 }
1887 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001888 size = mPowerSaveWhitelistExceptIdleAppIds.size();
1889 if (size > 0) {
1890 pw.println(" Whitelist (except idle) all app ids:");
1891 for (int i = 0; i < size; i++) {
1892 pw.print(" ");
1893 pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
1894 pw.println();
1895 }
1896 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001897 size = mPowerSaveWhitelistAllAppIds.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001898 if (size > 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001899 pw.println(" Whitelist all app ids:");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001900 for (int i = 0; i < size; i++) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001901 pw.print(" ");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001902 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001903 pw.println();
1904 }
1905 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001906 size = mTempWhitelistAppIdEndTimes.size();
1907 if (size > 0) {
1908 pw.println(" Temp whitelist schedule:");
1909 final long timeNow = SystemClock.elapsedRealtime();
1910 for (int i = 0; i < size; i++) {
1911 pw.print(" UID=");
1912 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
1913 pw.print(": ");
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001914 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
1915 TimeUtils.formatDuration(entry.first.value, timeNow, pw);
1916 pw.print(" - ");
1917 pw.println(entry.second);
Dianne Hackborna750a632015-06-16 17:18:23 -07001918 }
1919 }
1920 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
1921 if (size > 0) {
1922 pw.println(" Temp whitelist app ids:");
1923 for (int i = 0; i < size; i++) {
1924 pw.print(" ");
1925 pw.print(mTempWhitelistAppIdArray[i]);
1926 pw.println();
1927 }
1928 }
Adam Lesinski31c05d12015-06-09 17:34:04 -07001929
Dianne Hackborn92617032015-06-19 15:32:19 -07001930 pw.print(" mEnabled="); pw.println(mEnabled);
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001931 pw.print(" mForceIdle="); pw.println(mForceIdle);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001932 pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
1933 pw.print(" mCurDisplay="); pw.println(mCurDisplay);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001934 pw.print(" mScreenOn="); pw.println(mScreenOn);
1935 pw.print(" mCharging="); pw.println(mCharging);
1936 pw.print(" mSigMotionActive="); pw.println(mSigMotionActive);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001937 pw.print(" mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
1938 pw.println(mNotMoving);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001939 pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
1940 pw.print(mHasGps); pw.print(" mHasNetwork=");
1941 pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001942 if (mLastGenericLocation != null) {
1943 pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation);
1944 }
1945 if (mLastGpsLocation != null) {
1946 pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation);
1947 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001948 pw.print(" mState="); pw.println(stateToString(mState));
1949 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
1950 pw.println();
1951 if (mNextAlarmTime != 0) {
1952 pw.print(" mNextAlarmTime=");
1953 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
1954 pw.println();
1955 }
1956 if (mNextIdlePendingDelay != 0) {
1957 pw.print(" mNextIdlePendingDelay=");
1958 TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
1959 pw.println();
1960 }
1961 if (mNextIdleDelay != 0) {
1962 pw.print(" mNextIdleDelay=");
1963 TimeUtils.formatDuration(mNextIdleDelay, pw);
1964 pw.println();
1965 }
1966 }
1967 }
1968}