blob: c7c9d29aae65e3a704b7e729ec00bba6aaf30744 [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;
37import android.net.INetworkPolicyManager;
Adam Lesinski31c05d12015-06-09 17:34:04 -070038import android.net.Uri;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070039import android.os.BatteryStats;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070040import android.os.Binder;
41import android.os.Environment;
42import android.os.FileUtils;
43import android.os.Handler;
44import android.os.IDeviceIdleController;
45import android.os.Looper;
46import android.os.Message;
47import android.os.PowerManager;
48import android.os.PowerManagerInternal;
Dianne Hackbornb6683c42015-06-18 17:40:33 -070049import android.os.Process;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070050import android.os.RemoteException;
51import android.os.ServiceManager;
52import android.os.SystemClock;
53import android.os.UserHandle;
Adam Lesinski31c05d12015-06-09 17:34:04 -070054import android.provider.Settings;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070055import android.util.ArrayMap;
56import android.util.ArraySet;
Adam Lesinski31c05d12015-06-09 17:34:04 -070057import android.util.KeyValueListParser;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070058import android.util.MutableLong;
59import android.util.Pair;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070060import android.util.Slog;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070061import android.util.SparseArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070062import android.util.SparseBooleanArray;
63import android.util.TimeUtils;
64import android.util.Xml;
65import android.view.Display;
Amith Yamasani520d8f22015-05-08 16:36:21 -070066
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070067import com.android.internal.app.IBatteryStats;
68import com.android.internal.os.AtomicFile;
69import com.android.internal.os.BackgroundThread;
70import com.android.internal.util.FastXmlSerializer;
71import com.android.internal.util.XmlUtils;
72import com.android.server.am.BatteryStatsService;
Amith Yamasani520d8f22015-05-08 16:36:21 -070073
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070074import org.xmlpull.v1.XmlPullParser;
75import org.xmlpull.v1.XmlPullParserException;
76import org.xmlpull.v1.XmlSerializer;
77
78import java.io.ByteArrayOutputStream;
79import java.io.File;
80import java.io.FileDescriptor;
81import java.io.FileInputStream;
82import java.io.FileNotFoundException;
83import java.io.FileOutputStream;
84import java.io.IOException;
85import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +010086import java.nio.charset.StandardCharsets;
Amith Yamasaniaf575b92015-05-29 15:35:26 -070087import java.util.Arrays;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070088
89/**
90 * Keeps track of device idleness and drives low power mode based on that.
91 */
Kevin Gabayan89ecf822015-05-18 12:10:07 -070092public class DeviceIdleController extends SystemService
93 implements AnyMotionDetector.DeviceIdleCallback {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070094 private static final String TAG = "DeviceIdleController";
95
Amith Yamasaniaf575b92015-05-29 15:35:26 -070096 private static final boolean DEBUG = false;
Kevin Gabayan89ecf822015-05-18 12:10:07 -070097
Amith Yamasaniaf575b92015-05-29 15:35:26 -070098 private static final boolean COMPRESS_TIME = false;
Amith Yamasani520d8f22015-05-08 16:36:21 -070099
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700100 private static final String ACTION_STEP_IDLE_STATE =
101 "com.android.server.device_idle.STEP_IDLE_STATE";
102
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700103 private AlarmManager mAlarmManager;
104 private IBatteryStats mBatteryStats;
105 private PowerManagerInternal mLocalPowerManager;
106 private INetworkPolicyManager mNetworkPolicyManager;
107 private DisplayManager mDisplayManager;
108 private SensorManager mSensorManager;
109 private Sensor mSigMotionSensor;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700110 private PendingIntent mSensingAlarmIntent;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700111 private PendingIntent mAlarmIntent;
112 private Intent mIdleIntent;
113 private Display mCurDisplay;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700114 private AnyMotionDetector mAnyMotionDetector;
Dianne Hackborn92617032015-06-19 15:32:19 -0700115 private boolean mEnabled;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700116 private boolean mScreenOn;
117 private boolean mCharging;
118 private boolean mSigMotionActive;
119
120 /** Device is currently active. */
121 private static final int STATE_ACTIVE = 0;
122 /** Device is inactve (screen off, no motion) and we are waiting to for idle. */
123 private static final int STATE_INACTIVE = 1;
124 /** Device is past the initial inactive period, and waiting for the next idle period. */
125 private static final int STATE_IDLE_PENDING = 2;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700126 /** Device is currently sensing motion. */
127 private static final int STATE_SENSING = 3;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700128 /** Device is in the idle state, trying to stay asleep as much as possible. */
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700129 private static final int STATE_IDLE = 4;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700130 /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700131 private static final int STATE_IDLE_MAINTENANCE = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700132 private static String stateToString(int state) {
133 switch (state) {
134 case STATE_ACTIVE: return "ACTIVE";
135 case STATE_INACTIVE: return "INACTIVE";
136 case STATE_IDLE_PENDING: return "IDLE_PENDING";
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700137 case STATE_SENSING: return "SENSING";
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700138 case STATE_IDLE: return "IDLE";
139 case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
140 default: return Integer.toString(state);
141 }
142 }
143
144 private int mState;
145
146 private long mInactiveTimeout;
147 private long mNextAlarmTime;
148 private long mNextIdlePendingDelay;
149 private long mNextIdleDelay;
150
151 public final AtomicFile mConfigFile;
152
153 /**
154 * Package names the system has white-listed to opt out of power save restrictions.
155 */
156 private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
157
158 /**
159 * Package names the user has white-listed to opt out of power save restrictions.
160 */
161 private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
162
163 /**
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700164 * App IDs of built-in system apps that have been white-listed.
165 */
166 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
167
168 /**
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700169 * App IDs that have been white-listed to opt out of power save restrictions.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700170 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700171 private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700172
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700173 /**
174 * Current app IDs that are in the complete power save white list. This array can
175 * be shared with others because it will not be modified once set.
176 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700177 private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700178
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700179 /**
180 * List of end times for UIDs that are temporarily marked as being allowed to access
181 * the network and acquire wakelocks. Times are in milliseconds.
182 */
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700183 private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
184 = new SparseArray<>();
185
186 /**
187 * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
188 */
189 Runnable mNetworkPolicyTempWhitelistCallback;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700190
191 /**
192 * Current app IDs of temporarily whitelist apps for high-priority messages.
193 */
194 private int[] mTempWhitelistAppIdArray = new int[0];
195
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700196 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
197 @Override public void onReceive(Context context, Intent intent) {
198 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
199 int plugged = intent.getIntExtra("plugged", 0);
200 updateChargingLocked(plugged != 0);
201 } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
202 synchronized (DeviceIdleController.this) {
203 stepIdleStateLocked();
204 }
205 }
206 }
207 };
208
209 private final DisplayManager.DisplayListener mDisplayListener
210 = new DisplayManager.DisplayListener() {
211 @Override public void onDisplayAdded(int displayId) {
212 }
213
214 @Override public void onDisplayRemoved(int displayId) {
215 }
216
217 @Override public void onDisplayChanged(int displayId) {
218 if (displayId == Display.DEFAULT_DISPLAY) {
219 synchronized (DeviceIdleController.this) {
220 updateDisplayLocked();
221 }
222 }
223 }
224 };
225
226 private final TriggerEventListener mSigMotionListener = new TriggerEventListener() {
227 @Override public void onTrigger(TriggerEvent event) {
228 synchronized (DeviceIdleController.this) {
229 significantMotionLocked();
230 }
231 }
232 };
233
Adam Lesinski31c05d12015-06-09 17:34:04 -0700234 /**
235 * All times are in milliseconds. These constants are kept synchronized with the system
236 * global Settings. Any access to this class or its fields should be done while
237 * holding the DeviceIdleController lock.
238 */
Dianne Hackborna750a632015-06-16 17:18:23 -0700239 private final class Constants extends ContentObserver {
Adam Lesinski31c05d12015-06-09 17:34:04 -0700240 // Key names stored in the settings value.
241 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
242 private static final String KEY_SENSING_TIMEOUT = "sensing_to";
243 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
244 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
245 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
246 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
247 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
248 private static final String KEY_IDLE_TIMEOUT = "idle_to";
249 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
250 private static final String KEY_IDLE_FACTOR = "idle_factor";
251 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
252 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
253 "max_temp_app_whitelist_duration";
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700254 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
255 "mms_temp_app_whitelist_duration";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700256
257 /**
258 * This is the time, after becoming inactive, at which we start looking at the
259 * motion sensor to determine if the device is being left alone. We don't do this
260 * immediately after going inactive just because we don't want to be continually running
261 * the significant motion sensor whenever the screen is off.
262 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
263 * @see #KEY_INACTIVE_TIMEOUT
264 */
265 public long INACTIVE_TIMEOUT;
266
267 /**
268 * If we don't receive a callback from AnyMotion in this amount of time, we will change from
269 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
270 * will be ignored.
271 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
272 * @see #KEY_SENSING_TIMEOUT
273 */
274 public long SENSING_TIMEOUT;
275
276 /**
277 * This is the time, after seeing motion, that we wait after becoming inactive from
278 * that until we start looking for motion again.
279 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
280 * @see #KEY_MOTION_INACTIVE_TIMEOUT
281 */
282 public long MOTION_INACTIVE_TIMEOUT;
283
284 /**
285 * This is the time, after the inactive timeout elapses, that we will wait looking
286 * for significant motion until we truly consider the device to be idle.
287 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
288 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
289 */
290 public long IDLE_AFTER_INACTIVE_TIMEOUT;
291
292 /**
293 * This is the initial time, after being idle, that we will allow ourself to be back
294 * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
295 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
296 * @see #KEY_IDLE_PENDING_TIMEOUT
297 */
298 public long IDLE_PENDING_TIMEOUT;
299
300 /**
301 * Maximum pending idle timeout (time spent running) we will be allowed to use.
302 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
303 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
304 */
305 public long MAX_IDLE_PENDING_TIMEOUT;
306
307 /**
308 * Scaling factor to apply to current pending idle timeout each time we cycle through
309 * that state.
310 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
311 * @see #KEY_IDLE_PENDING_FACTOR
312 */
313 public float IDLE_PENDING_FACTOR;
314
315 /**
316 * This is the initial time that we want to sit in the idle state before waking up
317 * again to return to pending idle and allowing normal work to run.
318 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
319 * @see #KEY_IDLE_TIMEOUT
320 */
321 public long IDLE_TIMEOUT;
322
323 /**
324 * Maximum idle duration we will be allowed to use.
325 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
326 * @see #KEY_MAX_IDLE_TIMEOUT
327 */
328 public long MAX_IDLE_TIMEOUT;
329
330 /**
331 * Scaling factor to apply to current idle timeout each time we cycle through that state.
332 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
333 * @see #KEY_IDLE_FACTOR
334 */
335 public float IDLE_FACTOR;
336
337 /**
338 * This is the minimum time we will allow until the next upcoming alarm for us to
339 * actually go in to idle mode.
340 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
341 * @see #KEY_MIN_TIME_TO_ALARM
342 */
343 public long MIN_TIME_TO_ALARM;
344
345 /**
346 * Max amount of time to temporarily whitelist an app when it receives a high priority
347 * tickle.
348 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
349 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
350 */
351 public long MAX_TEMP_APP_WHITELIST_DURATION;
352
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700353 /**
354 * Amount of time we would like to whitelist an app that is receiving an MMS.
355 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
356 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
357 */
358 public long MMS_TEMP_APP_WHITELIST_DURATION;
359
Adam Lesinski31c05d12015-06-09 17:34:04 -0700360 private final ContentResolver mResolver;
361 private final KeyValueListParser mParser = new KeyValueListParser(',');
362
363 public Constants(Handler handler, ContentResolver resolver) {
364 super(handler);
365 mResolver = resolver;
366 mResolver.registerContentObserver(
367 Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), false, this);
368 updateConstants();
369 }
370
371 @Override
372 public void onChange(boolean selfChange, Uri uri) {
373 updateConstants();
374 }
375
376 private void updateConstants() {
377 synchronized (DeviceIdleController.this) {
378 try {
379 mParser.setString(Settings.Global.getString(mResolver,
380 Settings.Global.DEVICE_IDLE_CONSTANTS));
381 } catch (IllegalArgumentException e) {
382 // Failed to parse the settings string, log this and move on
383 // with defaults.
384 Slog.e(TAG, "Bad device idle settings", e);
385 }
386
387 INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
388 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
389 SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
390 !DEBUG ? 5 * 60 * 1000L : 60 * 1000L);
391 MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
392 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
393 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
394 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
395 IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
396 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
397 MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
398 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
399 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
400 2f);
401 IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
402 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
403 MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
404 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
405 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
406 2f);
407 MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
408 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700409 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
410 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
411 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
Dianne Hackborn0b6134b2015-07-14 18:48:07 -0700412 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700413 }
414 }
415
416 void dump(PrintWriter pw) {
417 pw.println(" Settings:");
418
Dianne Hackborna750a632015-06-16 17:18:23 -0700419 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700420 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
421 pw.println();
422
Dianne Hackborna750a632015-06-16 17:18:23 -0700423 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700424 TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
425 pw.println();
426
Dianne Hackborna750a632015-06-16 17:18:23 -0700427 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700428 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
429 pw.println();
430
Dianne Hackborna750a632015-06-16 17:18:23 -0700431 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700432 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
433 pw.println();
434
Dianne Hackborna750a632015-06-16 17:18:23 -0700435 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700436 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
437 pw.println();
438
Dianne Hackborna750a632015-06-16 17:18:23 -0700439 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700440 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
441 pw.println();
442
Dianne Hackborna750a632015-06-16 17:18:23 -0700443 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700444 pw.println(IDLE_PENDING_FACTOR);
445
Dianne Hackborna750a632015-06-16 17:18:23 -0700446 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700447 TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
448 pw.println();
449
Dianne Hackborna750a632015-06-16 17:18:23 -0700450 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700451 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
452 pw.println();
453
Dianne Hackborna750a632015-06-16 17:18:23 -0700454 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700455 pw.println(IDLE_FACTOR);
456
Dianne Hackborna750a632015-06-16 17:18:23 -0700457 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700458 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
459 pw.println();
460
Dianne Hackborna750a632015-06-16 17:18:23 -0700461 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700462 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
463 pw.println();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700464
465 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
466 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
467 pw.println();
Adam Lesinski31c05d12015-06-09 17:34:04 -0700468 }
469 }
470
471 private Constants mConstants;
472
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700473 @Override
474 public void onAnyMotionResult(int result) {
475 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
476 if (mState == STATE_SENSING) {
477 if (result == AnyMotionDetector.RESULT_STATIONARY) {
478 if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
479 synchronized (this) {
480 stepIdleStateLocked();
481 }
482 } else if (result == AnyMotionDetector.RESULT_MOVED) {
483 if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
484 synchronized (this) {
Dianne Hackborna750a632015-06-16 17:18:23 -0700485 EventLogTags.writeDeviceIdle(mState, "sense_moved");
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700486 enterInactiveStateLocked();
487 }
488 }
489 }
490 }
491
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700492 static final int MSG_WRITE_CONFIG = 1;
493 static final int MSG_REPORT_IDLE_ON = 2;
494 static final int MSG_REPORT_IDLE_OFF = 3;
495 static final int MSG_REPORT_ACTIVE = 4;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700496 static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700497
498 final class MyHandler extends Handler {
499 MyHandler(Looper looper) {
500 super(looper);
501 }
502
503 @Override public void handleMessage(Message msg) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700504 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700505 switch (msg.what) {
506 case MSG_WRITE_CONFIG: {
507 handleWriteConfigFile();
508 } break;
509 case MSG_REPORT_IDLE_ON: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700510 EventLogTags.writeDeviceIdleOnStart();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700511 mLocalPowerManager.setDeviceIdleMode(true);
512 try {
513 mNetworkPolicyManager.setDeviceIdleMode(true);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700514 mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700515 } catch (RemoteException e) {
516 }
517 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700518 EventLogTags.writeDeviceIdleOnComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700519 } break;
520 case MSG_REPORT_IDLE_OFF: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700521 EventLogTags.writeDeviceIdleOffStart("unknown");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700522 mLocalPowerManager.setDeviceIdleMode(false);
523 try {
524 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700525 mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700526 } catch (RemoteException e) {
527 }
528 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700529 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700530 } break;
531 case MSG_REPORT_ACTIVE: {
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700532 String activeReason = (String)msg.obj;
533 int activeUid = msg.arg1;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700534 boolean needBroadcast = msg.arg2 != 0;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700535 EventLogTags.writeDeviceIdleOffStart(
536 activeReason != null ? activeReason : "unknown");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700537 mLocalPowerManager.setDeviceIdleMode(false);
538 try {
539 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700540 mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700541 } catch (RemoteException e) {
542 }
543 if (needBroadcast) {
544 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
545 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700546 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700547 } break;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700548 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
549 int uid = msg.arg1;
550 checkTempAppWhitelistTimeout(uid);
551 } break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700552 }
553 }
554 }
555
556 final MyHandler mHandler;
557
558 private final class BinderService extends IDeviceIdleController.Stub {
559 @Override public void addPowerSaveWhitelistApp(String name) {
560 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
561 null);
562 addPowerSaveWhitelistAppInternal(name);
563 }
564
565 @Override public void removePowerSaveWhitelistApp(String name) {
566 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
567 null);
568 removePowerSaveWhitelistAppInternal(name);
569 }
570
571 @Override public String[] getSystemPowerWhitelist() {
572 return getSystemPowerWhitelistInternal();
573 }
574
575 @Override public String[] getFullPowerWhitelist() {
576 return getFullPowerWhitelistInternal();
577 }
578
579 @Override public int[] getAppIdWhitelist() {
580 return getAppIdWhitelistInternal();
581 }
582
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700583 @Override public int[] getAppIdTempWhitelist() {
584 return getAppIdTempWhitelistInternal();
585 }
586
Amith Yamasani06bf8242015-05-08 16:36:21 -0700587 @Override public boolean isPowerSaveWhitelistApp(String name) {
588 return isPowerSaveWhitelistAppInternal(name);
589 }
590
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700591 @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700592 int userId, String reason) throws RemoteException {
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700593 getContext().enforceCallingPermission(
594 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
595 "No permission to change device idle whitelist");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700596 final int callingUid = Binder.getCallingUid();
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700597 userId = ActivityManagerNative.getDefault().handleIncomingUser(
598 Binder.getCallingPid(),
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700599 callingUid,
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700600 userId,
601 /*allowAll=*/ false,
602 /*requireFull=*/ false,
Dianne Hackborna750a632015-06-16 17:18:23 -0700603 "addPowerSaveTempWhitelistApp", null);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700604 final long token = Binder.clearCallingIdentity();
605 try {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700606 DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700607 packageName, duration, userId, true, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700608 } finally {
609 Binder.restoreCallingIdentity(token);
610 }
611 }
612
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700613 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
614 int userId, String reason) throws RemoteException {
615 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
616 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
617 return duration;
618 }
619
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700620 @Override public void exitIdle(String reason) {
621 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
622 null);
623 exitIdleInternal(reason);
624 }
625
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700626 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
627 DeviceIdleController.this.dump(fd, pw, args);
628 }
629 }
630
Dianne Hackborna750a632015-06-16 17:18:23 -0700631 public final class LocalService {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700632 public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
633 String reason) {
634 addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
635 }
636
637 public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
638 setNetworkPolicyTempWhitelistCallbackInternal(callback);
Dianne Hackborna750a632015-06-16 17:18:23 -0700639 }
640 }
641
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700642 public DeviceIdleController(Context context) {
643 super(context);
644 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
645 mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
646 }
647
648 private static File getSystemDir() {
649 return new File(Environment.getDataDirectory(), "system");
650 }
651
652 @Override
653 public void onStart() {
654 final PackageManager pm = getContext().getPackageManager();
655
656 synchronized (this) {
Dianne Hackborn92617032015-06-19 15:32:19 -0700657 mEnabled = getContext().getResources().getBoolean(
658 com.android.internal.R.bool.config_enableAutoPowerModes);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700659 SystemConfig sysConfig = SystemConfig.getInstance();
660 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
661 for (int i=0; i<allowPower.size(); i++) {
662 String pkg = allowPower.valueAt(i);
663 try {
664 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
665 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700666 int appid = UserHandle.getAppId(ai.uid);
667 mPowerSaveWhitelistApps.put(ai.packageName, appid);
668 mPowerSaveWhitelistSystemAppIds.put(appid, true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700669 }
670 } catch (PackageManager.NameNotFoundException e) {
671 }
672 }
673
Adam Lesinski31c05d12015-06-09 17:34:04 -0700674 mConstants = new Constants(mHandler, getContext().getContentResolver());
675
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700676 readConfigFileLocked();
677 updateWhitelistAppIdsLocked();
678
679 mScreenOn = true;
680 // Start out assuming we are charging. If we aren't, we will at least get
681 // a battery update the next time the level drops.
682 mCharging = true;
683 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -0700684 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700685 }
686
Dianne Hackborn1958e5e2015-06-12 18:11:41 -0700687 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
Dianne Hackborna750a632015-06-16 17:18:23 -0700688 publishLocalService(LocalService.class, new LocalService());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700689 }
690
691 @Override
692 public void onBootPhase(int phase) {
693 if (phase == PHASE_SYSTEM_SERVICES_READY) {
694 synchronized (this) {
695 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
696 mBatteryStats = BatteryStatsService.getService();
697 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
698 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
699 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
700 mDisplayManager = (DisplayManager) getContext().getSystemService(
701 Context.DISPLAY_SERVICE);
702 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
703 mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700704 mAnyMotionDetector = new AnyMotionDetector(
705 mAlarmManager,
706 (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
707 mHandler, mSensorManager, this);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700708
709 Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
710 .setPackage("android")
711 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
712 mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
713
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700714 Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)
715 .setPackage("android")
716 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
717 mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
718
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700719 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700720 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
721 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700722
723 IntentFilter filter = new IntentFilter();
724 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
725 filter.addAction(ACTION_STEP_IDLE_STATE);
726 getContext().registerReceiver(mReceiver, filter);
727
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700728 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700729
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700730 mDisplayManager.registerDisplayListener(mDisplayListener, null);
731 updateDisplayLocked();
732 }
733 }
734 }
735
736 public boolean addPowerSaveWhitelistAppInternal(String name) {
737 synchronized (this) {
738 try {
739 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0);
740 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
741 reportPowerSaveWhitelistChangedLocked();
742 updateWhitelistAppIdsLocked();
743 writeConfigFileLocked();
744 }
745 return true;
746 } catch (PackageManager.NameNotFoundException e) {
747 return false;
748 }
749 }
750 }
751
752 public boolean removePowerSaveWhitelistAppInternal(String name) {
753 synchronized (this) {
754 if (mPowerSaveWhitelistUserApps.remove(name) != null) {
755 reportPowerSaveWhitelistChangedLocked();
756 updateWhitelistAppIdsLocked();
757 writeConfigFileLocked();
758 return true;
759 }
760 }
761 return false;
762 }
763
764 public String[] getSystemPowerWhitelistInternal() {
765 synchronized (this) {
766 int size = mPowerSaveWhitelistApps.size();
767 String[] apps = new String[size];
768 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
769 apps[i] = mPowerSaveWhitelistApps.keyAt(i);
770 }
771 return apps;
772 }
773 }
774
775 public String[] getFullPowerWhitelistInternal() {
776 synchronized (this) {
777 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
778 String[] apps = new String[size];
779 int cur = 0;
780 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
781 apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
782 cur++;
783 }
784 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
785 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
786 cur++;
787 }
788 return apps;
789 }
790 }
791
Amith Yamasani06bf8242015-05-08 16:36:21 -0700792 public boolean isPowerSaveWhitelistAppInternal(String packageName) {
793 synchronized (this) {
794 return mPowerSaveWhitelistApps.containsKey(packageName)
795 || mPowerSaveWhitelistUserApps.containsKey(packageName);
796 }
797 }
798
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700799 public int[] getAppIdWhitelistInternal() {
800 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700801 return mPowerSaveWhitelistAllAppIdArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700802 }
803 }
804
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700805 public int[] getAppIdTempWhitelistInternal() {
806 synchronized (this) {
807 return mTempWhitelistAppIdArray;
808 }
809 }
810
811 /**
812 * Adds an app to the temporary whitelist and resets the endTime for granting the
813 * app an exemption to access network and acquire wakelocks.
814 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700815 public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700816 long duration, int userId, boolean sync, String reason) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700817 try {
818 int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
819 int appId = UserHandle.getAppId(uid);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700820 addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700821 } catch (NameNotFoundException e) {
822 }
823 }
824
Dianne Hackborna750a632015-06-16 17:18:23 -0700825 /**
826 * Adds an app to the temporary whitelist and resets the endTime for granting the
827 * app an exemption to access network and acquire wakelocks.
828 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700829 public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700830 long duration, boolean sync, String reason) {
Dianne Hackborna750a632015-06-16 17:18:23 -0700831 final long timeNow = SystemClock.elapsedRealtime();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700832 Runnable networkPolicyTempWhitelistCallback = null;
Dianne Hackborna750a632015-06-16 17:18:23 -0700833 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700834 int callingAppId = UserHandle.getAppId(callingUid);
835 if (callingAppId >= Process.FIRST_APPLICATION_UID) {
836 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
837 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
838 + " is not on whitelist");
839 }
840 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700841 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700842 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
843 final boolean newEntry = entry == null;
Dianne Hackborna750a632015-06-16 17:18:23 -0700844 // Set the new end time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700845 if (newEntry) {
846 entry = new Pair<>(new MutableLong(0), reason);
847 mTempWhitelistAppIdEndTimes.put(appId, entry);
848 }
849 entry.first.value = timeNow + duration;
Dianne Hackborna750a632015-06-16 17:18:23 -0700850 if (DEBUG) {
851 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
852 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700853 if (newEntry) {
Dianne Hackborna750a632015-06-16 17:18:23 -0700854 // No pending timeout for the app id, post a delayed message
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700855 try {
856 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
857 reason, appId);
858 } catch (RemoteException e) {
859 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700860 postTempActiveTimeoutMessage(appId, duration);
861 updateTempWhitelistAppIdsLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700862 if (mNetworkPolicyTempWhitelistCallback != null) {
863 if (!sync) {
864 mHandler.post(mNetworkPolicyTempWhitelistCallback);
865 } else {
866 networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
867 }
868 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700869 reportTempWhitelistChangedLocked();
870 }
871 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700872 if (networkPolicyTempWhitelistCallback != null) {
873 networkPolicyTempWhitelistCallback.run();
874 }
875 }
876
877 public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
878 synchronized (this) {
879 mNetworkPolicyTempWhitelistCallback = callback;
880 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700881 }
882
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700883 private void postTempActiveTimeoutMessage(int uid, long delay) {
884 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
885 delay);
886 }
887
888 void checkTempAppWhitelistTimeout(int uid) {
Dianne Hackborna750a632015-06-16 17:18:23 -0700889 final long timeNow = SystemClock.elapsedRealtime();
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700890 synchronized (this) {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700891 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
892 if (entry == null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700893 // Nothing to do
894 return;
895 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700896 if (timeNow >= entry.first.value) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700897 mTempWhitelistAppIdEndTimes.delete(uid);
898 if (DEBUG) {
899 Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
900 }
901 updateTempWhitelistAppIdsLocked();
902 reportTempWhitelistChangedLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700903 try {
904 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
905 entry.second, uid);
906 } catch (RemoteException e) {
907 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700908 } else {
909 // Need more time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700910 postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700911 }
912 }
913 }
914
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700915 public void exitIdleInternal(String reason) {
916 synchronized (this) {
917 becomeActiveLocked(reason, Binder.getCallingUid());
918 }
919 }
920
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700921 void updateDisplayLocked() {
922 mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
923 // We consider any situation where the display is showing something to be it on,
924 // because if there is anything shown we are going to be updating it at some
925 // frequency so can't be allowed to go into deep sleeps.
926 boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700927 if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700928 if (!screenOn && mScreenOn) {
929 mScreenOn = false;
930 becomeInactiveIfAppropriateLocked();
931 } else if (screenOn) {
932 mScreenOn = true;
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700933 becomeActiveLocked("screen", Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700934 }
935 }
936
937 void updateChargingLocked(boolean charging) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700938 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700939 if (!charging && mCharging) {
940 mCharging = false;
941 becomeInactiveIfAppropriateLocked();
942 } else if (charging) {
943 mCharging = charging;
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700944 becomeActiveLocked("charging", Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700945 }
946 }
947
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700948 void scheduleReportActiveLocked(String activeReason, int activeUid) {
949 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
950 mState == STATE_IDLE ? 1 : 0, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700951 mHandler.sendMessage(msg);
952 }
953
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700954 void becomeActiveLocked(String activeReason, int activeUid) {
955 if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700956 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700957 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
958 scheduleReportActiveLocked(activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700959 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -0700960 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700961 mNextIdlePendingDelay = 0;
962 mNextIdleDelay = 0;
963 cancelAlarmLocked();
964 stopMonitoringSignificantMotion();
965 }
966 }
967
968 void becomeInactiveIfAppropriateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700969 if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
Dianne Hackborn92617032015-06-19 15:32:19 -0700970 if (!mScreenOn && !mCharging && mEnabled && mState == STATE_ACTIVE) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700971 // Screen has turned off; we are now going to become inactive and start
972 // waiting to see if we will ultimately go idle.
973 mState = STATE_INACTIVE;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700974 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700975 mNextIdlePendingDelay = 0;
976 mNextIdleDelay = 0;
977 scheduleAlarmLocked(mInactiveTimeout, false);
978 EventLogTags.writeDeviceIdle(mState, "no activity");
979 }
980 }
981
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700982 /**
983 * This is called when we've failed to receive a callback from AnyMotionDetector
984 * within the DEFAULT_SENSING_TIMEOUT, to return to STATE_INACTIVE.
985 */
986 void enterInactiveStateLocked() {
Adam Lesinski31c05d12015-06-09 17:34:04 -0700987 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700988 becomeInactiveIfAppropriateLocked();
989 }
990
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700991 void stepIdleStateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700992 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700993 EventLogTags.writeDeviceIdleStep();
994
995 final long now = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -0700996 if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700997 // Whoops, there is an upcoming alarm. We don't actually want to go idle.
998 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700999 becomeActiveLocked("alarm", Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001000 }
1001 return;
1002 }
1003
1004 switch (mState) {
1005 case STATE_INACTIVE:
1006 // We have now been inactive long enough, it is time to start looking
1007 // for significant motion and sleep some more while doing so.
1008 startMonitoringSignificantMotion();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001009 scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001010 // Reset the upcoming idle delays.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001011 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
1012 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001013 mState = STATE_IDLE_PENDING;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001014 if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001015 EventLogTags.writeDeviceIdle(mState, "step");
1016 break;
1017 case STATE_IDLE_PENDING:
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001018 mState = STATE_SENSING;
1019 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001020 scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001021 mAnyMotionDetector.checkForAnyMotion();
1022 break;
1023 case STATE_SENSING:
1024 cancelSensingAlarmLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001025 case STATE_IDLE_MAINTENANCE:
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001026 scheduleAlarmLocked(mNextIdleDelay, true);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001027 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
1028 " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001029 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001030 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001031 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001032 mState = STATE_IDLE;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001033 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
1034 break;
1035 case STATE_IDLE:
1036 // We have been idling long enough, now it is time to do some work.
1037 scheduleAlarmLocked(mNextIdlePendingDelay, false);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001038 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
1039 "Next alarm in " + mNextIdlePendingDelay + " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001040 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
1041 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001042 mState = STATE_IDLE_MAINTENANCE;
1043 EventLogTags.writeDeviceIdle(mState, "step");
1044 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1045 break;
1046 }
1047 }
1048
1049 void significantMotionLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001050 if (DEBUG) Slog.d(TAG, "significantMotionLocked()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001051 // When the sensor goes off, its trigger is automatically removed.
1052 mSigMotionActive = false;
1053 // The device is not yet active, so we want to go back to the pending idle
1054 // state to wait again for no motion. Note that we only monitor for significant
1055 // motion after moving out of the inactive state, so no need to worry about that.
1056 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001057 scheduleReportActiveLocked("motion", Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001058 mState = STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -07001059 mInactiveTimeout = mConstants.MOTION_INACTIVE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001060 EventLogTags.writeDeviceIdle(mState, "motion");
1061 becomeInactiveIfAppropriateLocked();
1062 }
1063 }
1064
1065 void startMonitoringSignificantMotion() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001066 if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001067 if (mSigMotionSensor != null && !mSigMotionActive) {
1068 mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor);
1069 mSigMotionActive = true;
1070 }
1071 }
1072
1073 void stopMonitoringSignificantMotion() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001074 if (DEBUG) Slog.d(TAG, "stopMonitoringSignificantMotion()");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001075 if (mSigMotionActive) {
1076 mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor);
1077 mSigMotionActive = false;
1078 }
1079 }
1080
1081 void cancelAlarmLocked() {
1082 if (mNextAlarmTime != 0) {
1083 mNextAlarmTime = 0;
1084 mAlarmManager.cancel(mAlarmIntent);
1085 }
1086 }
1087
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001088 void cancelSensingAlarmLocked() {
1089 if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
1090 mAlarmManager.cancel(mSensingAlarmIntent);
1091 }
1092
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001093 void scheduleAlarmLocked(long delay, boolean idleUntil) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001094 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001095 if (mSigMotionSensor == null) {
1096 // If there is no significant motion sensor on this device, then we won't schedule
1097 // alarms, because we can't determine if the device is not moving. This effectively
1098 // turns off normal exeuction of device idling, although it is still possible to
1099 // manually poke it by pretending like the alarm is going off.
1100 return;
1101 }
1102 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1103 if (idleUntil) {
1104 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1105 mNextAlarmTime, mAlarmIntent);
1106 } else {
1107 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1108 mNextAlarmTime, mAlarmIntent);
1109 }
1110 }
1111
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001112 void scheduleSensingAlarmLocked(long delay) {
1113 if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
1114 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1115 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1116 mNextAlarmTime, mSensingAlarmIntent);
1117 }
1118
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001119 private void updateWhitelistAppIdsLocked() {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001120 mPowerSaveWhitelistAllAppIds.clear();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001121 for (int i=0; i<mPowerSaveWhitelistApps.size(); i++) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001122 mPowerSaveWhitelistAllAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001123 }
1124 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001125 mPowerSaveWhitelistAllAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001126 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001127 int size = mPowerSaveWhitelistAllAppIds.size();
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001128 int[] appids = new int[size];
1129 for (int i = 0; i < size; i++) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001130 appids[i] = mPowerSaveWhitelistAllAppIds.keyAt(i);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001131 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001132 mPowerSaveWhitelistAllAppIdArray = appids;
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001133 if (mLocalPowerManager != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001134 if (DEBUG) {
1135 Slog.d(TAG, "Setting wakelock whitelist to "
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001136 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001137 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001138 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001139 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001140 }
1141
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001142 private void updateTempWhitelistAppIdsLocked() {
1143 final int size = mTempWhitelistAppIdEndTimes.size();
1144 if (mTempWhitelistAppIdArray.length != size) {
1145 mTempWhitelistAppIdArray = new int[size];
1146 }
1147 for (int i = 0; i < size; i++) {
1148 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
1149 }
1150 if (mLocalPowerManager != null) {
1151 if (DEBUG) {
1152 Slog.d(TAG, "Setting wakelock temp whitelist to "
1153 + Arrays.toString(mTempWhitelistAppIdArray));
1154 }
1155 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
1156 }
1157 }
1158
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001159 private void reportPowerSaveWhitelistChangedLocked() {
1160 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
1161 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001162 getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
1163 }
1164
1165 private void reportTempWhitelistChangedLocked() {
1166 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
1167 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1168 getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001169 }
1170
1171 void readConfigFileLocked() {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001172 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001173 mPowerSaveWhitelistUserApps.clear();
1174 FileInputStream stream;
1175 try {
1176 stream = mConfigFile.openRead();
1177 } catch (FileNotFoundException e) {
1178 return;
1179 }
1180 try {
1181 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001182 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001183 readConfigFileLocked(parser);
1184 } catch (XmlPullParserException e) {
1185 } finally {
1186 try {
1187 stream.close();
1188 } catch (IOException e) {
1189 }
1190 }
1191
1192 }
1193
1194 private void readConfigFileLocked(XmlPullParser parser) {
1195 final PackageManager pm = getContext().getPackageManager();
1196
1197 try {
1198 int type;
1199 while ((type = parser.next()) != XmlPullParser.START_TAG
1200 && type != XmlPullParser.END_DOCUMENT) {
1201 ;
1202 }
1203
1204 if (type != XmlPullParser.START_TAG) {
1205 throw new IllegalStateException("no start tag found");
1206 }
1207
1208 int outerDepth = parser.getDepth();
1209 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1210 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1211 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1212 continue;
1213 }
1214
1215 String tagName = parser.getName();
1216 if (tagName.equals("wl")) {
1217 String name = parser.getAttributeValue(null, "n");
1218 if (name != null) {
1219 try {
1220 ApplicationInfo ai = pm.getApplicationInfo(name, 0);
1221 mPowerSaveWhitelistUserApps.put(ai.packageName,
1222 UserHandle.getAppId(ai.uid));
1223 } catch (PackageManager.NameNotFoundException e) {
1224 }
1225 }
1226 } else {
1227 Slog.w(TAG, "Unknown element under <config>: "
1228 + parser.getName());
1229 XmlUtils.skipCurrentTag(parser);
1230 }
1231 }
1232
1233 } catch (IllegalStateException e) {
1234 Slog.w(TAG, "Failed parsing config " + e);
1235 } catch (NullPointerException e) {
1236 Slog.w(TAG, "Failed parsing config " + e);
1237 } catch (NumberFormatException e) {
1238 Slog.w(TAG, "Failed parsing config " + e);
1239 } catch (XmlPullParserException e) {
1240 Slog.w(TAG, "Failed parsing config " + e);
1241 } catch (IOException e) {
1242 Slog.w(TAG, "Failed parsing config " + e);
1243 } catch (IndexOutOfBoundsException e) {
1244 Slog.w(TAG, "Failed parsing config " + e);
1245 }
1246 }
1247
1248 void writeConfigFileLocked() {
1249 mHandler.removeMessages(MSG_WRITE_CONFIG);
1250 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
1251 }
1252
1253 void handleWriteConfigFile() {
1254 final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
1255
1256 try {
1257 synchronized (this) {
1258 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001259 out.setOutput(memStream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001260 writeConfigFileLocked(out);
1261 }
1262 } catch (IOException e) {
1263 }
1264
1265 synchronized (mConfigFile) {
1266 FileOutputStream stream = null;
1267 try {
1268 stream = mConfigFile.startWrite();
1269 memStream.writeTo(stream);
1270 stream.flush();
1271 FileUtils.sync(stream);
1272 stream.close();
1273 mConfigFile.finishWrite(stream);
1274 } catch (IOException e) {
1275 Slog.w(TAG, "Error writing config file", e);
1276 mConfigFile.failWrite(stream);
1277 }
1278 }
1279 }
1280
1281 void writeConfigFileLocked(XmlSerializer out) throws IOException {
1282 out.startDocument(null, true);
1283 out.startTag(null, "config");
1284 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
1285 String name = mPowerSaveWhitelistUserApps.keyAt(i);
1286 out.startTag(null, "wl");
1287 out.attribute(null, "n", name);
1288 out.endTag(null, "wl");
1289 }
1290 out.endTag(null, "config");
1291 out.endDocument();
1292 }
1293
1294 private void dumpHelp(PrintWriter pw) {
1295 pw.println("Device idle controller (deviceidle) dump options:");
1296 pw.println(" [-h] [CMD]");
1297 pw.println(" -h: print this help text.");
1298 pw.println("Commands:");
1299 pw.println(" step");
1300 pw.println(" Immediately step to next state, without waiting for alarm.");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001301 pw.println(" disable");
1302 pw.println(" Completely disable device idle mode.");
1303 pw.println(" enable");
1304 pw.println(" Re-enable device idle mode after it had previously been disabled.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001305 pw.println(" enabled");
1306 pw.println(" Print 1 if device idle mode is currently enabled, else 0.");
Dianne Hackborn1b139682015-07-06 15:13:37 -07001307 pw.println(" whitelist");
1308 pw.println(" Print currently whitelisted apps.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001309 pw.println(" whitelist [package ...]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001310 pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001311 pw.println(" tempwhitelist [package ..]");
1312 pw.println(" Temporarily place packages in whitelist for 10 seconds.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001313 }
1314
1315 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1316 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1317 != PackageManager.PERMISSION_GRANTED) {
1318 pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
1319 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1320 + " without permission " + android.Manifest.permission.DUMP);
1321 return;
1322 }
1323
1324 if (args != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001325 int userId = UserHandle.USER_OWNER;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001326 for (int i=0; i<args.length; i++) {
1327 String arg = args[i];
1328 if ("-h".equals(arg)) {
1329 dumpHelp(pw);
1330 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001331 } else if ("-u".equals(arg)) {
1332 i++;
1333 if (i < args.length) {
1334 arg = args[i];
1335 userId = Integer.parseInt(arg);
1336 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001337 } else if ("-a".equals(arg)) {
1338 // Ignore, we always dump all.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001339 } else if ("step".equals(arg)) {
1340 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001341 long token = Binder.clearCallingIdentity();
1342 try {
1343 stepIdleStateLocked();
1344 pw.print("Stepped to: "); pw.println(stateToString(mState));
1345 } finally {
1346 Binder.restoreCallingIdentity(token);
1347 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001348 }
1349 return;
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001350 } else if ("disable".equals(arg)) {
1351 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001352 long token = Binder.clearCallingIdentity();
1353 try {
1354 if (mEnabled) {
1355 mEnabled = false;
1356 becomeActiveLocked("disabled", Process.myUid());
1357 pw.println("Idle mode disabled");
1358 }
1359 } finally {
1360 Binder.restoreCallingIdentity(token);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001361 }
1362 }
1363 return;
1364 } else if ("enable".equals(arg)) {
1365 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001366 long token = Binder.clearCallingIdentity();
1367 try {
1368 if (!mEnabled) {
1369 mEnabled = true;
1370 becomeInactiveIfAppropriateLocked();
1371 pw.println("Idle mode enabled");
1372 }
1373 } finally {
1374 Binder.restoreCallingIdentity(token);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001375 }
1376 }
1377 return;
Dianne Hackborn92617032015-06-19 15:32:19 -07001378 } else if ("enabled".equals(arg)) {
1379 synchronized (this) {
1380 pw.println(mEnabled ? "1" : " 0");
1381 }
1382 return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001383 } else if ("whitelist".equals(arg)) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001384 long token = Binder.clearCallingIdentity();
1385 try {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001386 i++;
Dianne Hackborn1b139682015-07-06 15:13:37 -07001387 if (i < args.length) {
1388 while (i < args.length) {
1389 arg = args[i];
1390 i++;
1391 if (arg.length() < 1 || (arg.charAt(0) != '-'
1392 && arg.charAt(0) != '+')) {
1393 pw.println("Package must be prefixed with + or -: " + arg);
1394 return;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001395 }
Dianne Hackborn1b139682015-07-06 15:13:37 -07001396 char op = arg.charAt(0);
1397 String pkg = arg.substring(1);
1398 if (op == '+') {
1399 if (addPowerSaveWhitelistAppInternal(pkg)) {
1400 pw.println("Added: " + pkg);
1401 } else {
1402 pw.println("Unknown package: " + pkg);
1403 }
1404 } else {
1405 if (removePowerSaveWhitelistAppInternal(pkg)) {
1406 pw.println("Removed: " + pkg);
1407 }
1408 }
1409 }
1410 } else {
1411 synchronized (this) {
1412 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
1413 pw.print("system,");
1414 pw.print(mPowerSaveWhitelistApps.keyAt(j));
1415 pw.print(",");
1416 pw.println(mPowerSaveWhitelistApps.valueAt(j));
1417 }
1418 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
1419 pw.print("user,");
1420 pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
1421 pw.print(",");
1422 pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001423 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001424 }
1425 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001426 } finally {
1427 Binder.restoreCallingIdentity(token);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001428 }
1429 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001430 } else if ("tempwhitelist".equals(arg)) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001431 long token = Binder.clearCallingIdentity();
1432 try {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001433 i++;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001434 if (i >= args.length) {
1435 pw.println("At least one package name must be specified");
1436 return;
1437 }
1438 while (i < args.length) {
1439 arg = args[i];
1440 i++;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001441 addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId, true,
1442 "shell");
1443 pw.println("Added: " + arg);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001444 }
1445 } finally {
1446 Binder.restoreCallingIdentity(token);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001447 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001448 return;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001449 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
1450 pw.println("Unknown option: " + arg);
1451 return;
1452 } else {
1453 pw.println("Unknown command: " + arg);
1454 return;
1455 }
1456 }
1457 }
1458
1459 synchronized (this) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001460 mConstants.dump(pw);
1461
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001462 int size = mPowerSaveWhitelistApps.size();
1463 if (size > 0) {
1464 pw.println(" Whitelist system apps:");
1465 for (int i = 0; i < size; i++) {
1466 pw.print(" ");
1467 pw.println(mPowerSaveWhitelistApps.keyAt(i));
1468 }
1469 }
1470 size = mPowerSaveWhitelistUserApps.size();
1471 if (size > 0) {
1472 pw.println(" Whitelist user apps:");
1473 for (int i = 0; i < size; i++) {
1474 pw.print(" ");
1475 pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
1476 }
1477 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001478 size = mPowerSaveWhitelistAllAppIds.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001479 if (size > 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001480 pw.println(" Whitelist all app ids:");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001481 for (int i = 0; i < size; i++) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001482 pw.print(" ");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001483 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001484 pw.println();
1485 }
1486 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001487 size = mTempWhitelistAppIdEndTimes.size();
1488 if (size > 0) {
1489 pw.println(" Temp whitelist schedule:");
1490 final long timeNow = SystemClock.elapsedRealtime();
1491 for (int i = 0; i < size; i++) {
1492 pw.print(" UID=");
1493 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
1494 pw.print(": ");
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001495 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
1496 TimeUtils.formatDuration(entry.first.value, timeNow, pw);
1497 pw.print(" - ");
1498 pw.println(entry.second);
Dianne Hackborna750a632015-06-16 17:18:23 -07001499 }
1500 }
1501 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
1502 if (size > 0) {
1503 pw.println(" Temp whitelist app ids:");
1504 for (int i = 0; i < size; i++) {
1505 pw.print(" ");
1506 pw.print(mTempWhitelistAppIdArray[i]);
1507 pw.println();
1508 }
1509 }
Adam Lesinski31c05d12015-06-09 17:34:04 -07001510
Dianne Hackborn92617032015-06-19 15:32:19 -07001511 pw.print(" mEnabled="); pw.println(mEnabled);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001512 pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
1513 pw.print(" mCurDisplay="); pw.println(mCurDisplay);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001514 pw.print(" mScreenOn="); pw.println(mScreenOn);
1515 pw.print(" mCharging="); pw.println(mCharging);
1516 pw.print(" mSigMotionActive="); pw.println(mSigMotionActive);
1517 pw.print(" mState="); pw.println(stateToString(mState));
1518 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
1519 pw.println();
1520 if (mNextAlarmTime != 0) {
1521 pw.print(" mNextAlarmTime=");
1522 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
1523 pw.println();
1524 }
1525 if (mNextIdlePendingDelay != 0) {
1526 pw.print(" mNextIdlePendingDelay=");
1527 TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
1528 pw.println();
1529 }
1530 if (mNextIdleDelay != 0) {
1531 pw.print(" mNextIdleDelay=");
1532 TimeUtils.formatDuration(mNextIdleDelay, pw);
1533 pw.println();
1534 }
1535 }
1536 }
1537}