blob: 496e4dfda6e0334976efd71ba59b2d1823cdb20f [file] [log] [blame]
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Amith Yamasaniaf575b92015-05-29 15:35:26 -070019import android.Manifest;
20import android.app.ActivityManagerNative;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070021import android.app.AlarmManager;
22import android.app.PendingIntent;
23import android.content.BroadcastReceiver;
Adam Lesinski31c05d12015-06-09 17:34:04 -070024import android.content.ContentResolver;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070025import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.pm.ApplicationInfo;
29import android.content.pm.PackageManager;
Amith Yamasaniaf575b92015-05-29 15:35:26 -070030import android.content.pm.PackageManager.NameNotFoundException;
Adam Lesinski31c05d12015-06-09 17:34:04 -070031import android.database.ContentObserver;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070032import android.hardware.Sensor;
33import android.hardware.SensorManager;
Nick Vaccaro20feaea2015-09-17 17:22:44 -070034import android.hardware.SensorEvent;
35import android.hardware.SensorEventListener;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070036import android.hardware.TriggerEvent;
37import android.hardware.TriggerEventListener;
38import android.hardware.display.DisplayManager;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -070039import android.location.LocationRequest;
40import android.location.Location;
41import android.location.LocationListener;
42import android.location.LocationManager;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070043import android.net.INetworkPolicyManager;
Adam Lesinski31c05d12015-06-09 17:34:04 -070044import android.net.Uri;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070045import android.os.BatteryStats;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070046import android.os.Binder;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -070047import android.os.Bundle;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070048import android.os.Environment;
49import android.os.FileUtils;
50import android.os.Handler;
51import android.os.IDeviceIdleController;
52import android.os.Looper;
53import android.os.Message;
54import android.os.PowerManager;
55import android.os.PowerManagerInternal;
Dianne Hackbornb6683c42015-06-18 17:40:33 -070056import android.os.Process;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070057import android.os.RemoteException;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -070058import android.os.ResultReceiver;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070059import android.os.ServiceManager;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -070060import android.os.ShellCommand;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070061import android.os.SystemClock;
62import android.os.UserHandle;
Adam Lesinski31c05d12015-06-09 17:34:04 -070063import android.provider.Settings;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070064import android.util.ArrayMap;
65import android.util.ArraySet;
Adam Lesinski31c05d12015-06-09 17:34:04 -070066import android.util.KeyValueListParser;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070067import android.util.MutableLong;
68import android.util.Pair;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070069import android.util.Slog;
Dianne Hackbornfd854ee2015-07-13 18:00:37 -070070import android.util.SparseArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070071import android.util.SparseBooleanArray;
72import android.util.TimeUtils;
73import android.util.Xml;
74import android.view.Display;
Amith Yamasani520d8f22015-05-08 16:36:21 -070075
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070076import com.android.internal.app.IBatteryStats;
77import com.android.internal.os.AtomicFile;
78import com.android.internal.os.BackgroundThread;
79import com.android.internal.util.FastXmlSerializer;
80import com.android.internal.util.XmlUtils;
81import com.android.server.am.BatteryStatsService;
Amith Yamasani520d8f22015-05-08 16:36:21 -070082
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070083import org.xmlpull.v1.XmlPullParser;
84import org.xmlpull.v1.XmlPullParserException;
85import org.xmlpull.v1.XmlSerializer;
86
87import java.io.ByteArrayOutputStream;
88import java.io.File;
89import java.io.FileDescriptor;
90import java.io.FileInputStream;
91import java.io.FileNotFoundException;
92import java.io.FileOutputStream;
93import java.io.IOException;
94import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +010095import java.nio.charset.StandardCharsets;
Amith Yamasaniaf575b92015-05-29 15:35:26 -070096import java.util.Arrays;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -070097
98/**
99 * Keeps track of device idleness and drives low power mode based on that.
100 */
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700101public class DeviceIdleController extends SystemService
102 implements AnyMotionDetector.DeviceIdleCallback {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700103 private static final String TAG = "DeviceIdleController";
104
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700105 private static final boolean DEBUG = false;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700106
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700107 private static final boolean COMPRESS_TIME = false;
Amith Yamasani520d8f22015-05-08 16:36:21 -0700108
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700109 private static final String ACTION_STEP_IDLE_STATE =
110 "com.android.server.device_idle.STEP_IDLE_STATE";
111
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700112 private static final String ACTION_STEP_LIGHT_IDLE_STATE =
113 "com.android.server.device_idle.STEP_LIGHT_IDLE_STATE";
114
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700115 private AlarmManager mAlarmManager;
116 private IBatteryStats mBatteryStats;
117 private PowerManagerInternal mLocalPowerManager;
118 private INetworkPolicyManager mNetworkPolicyManager;
119 private DisplayManager mDisplayManager;
120 private SensorManager mSensorManager;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700121 private Sensor mMotionSensor;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700122 private LocationManager mLocationManager;
123 private LocationRequest mLocationRequest;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700124 private PendingIntent mAlarmIntent;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700125 private PendingIntent mLightAlarmIntent;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700126 private Intent mIdleIntent;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700127 private Intent mLightIdleIntent;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700128 private Display mCurDisplay;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700129 private AnyMotionDetector mAnyMotionDetector;
Dianne Hackborn92617032015-06-19 15:32:19 -0700130 private boolean mEnabled;
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700131 private boolean mForceIdle;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700132 private boolean mScreenOn;
133 private boolean mCharging;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700134 private boolean mNotMoving;
135 private boolean mLocating;
136 private boolean mLocated;
Joe LaPenna23d681b2015-08-27 15:12:11 -0700137 private boolean mHasGps;
138 private boolean mHasNetworkLocation;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700139 private Location mLastGenericLocation;
140 private Location mLastGpsLocation;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700141
142 /** Device is currently active. */
143 private static final int STATE_ACTIVE = 0;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700144 /** Device is inactive (screen off, no motion) and we are waiting to for idle. */
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700145 private static final int STATE_INACTIVE = 1;
146 /** Device is past the initial inactive period, and waiting for the next idle period. */
147 private static final int STATE_IDLE_PENDING = 2;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700148 /** Device is currently sensing motion. */
149 private static final int STATE_SENSING = 3;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700150 /** Device is currently finding location (and may still be sensing). */
151 private static final int STATE_LOCATING = 4;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700152 /** Device is in the idle state, trying to stay asleep as much as possible. */
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700153 private static final int STATE_IDLE = 5;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700154 /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700155 private static final int STATE_IDLE_MAINTENANCE = 6;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700156 private static String stateToString(int state) {
157 switch (state) {
158 case STATE_ACTIVE: return "ACTIVE";
159 case STATE_INACTIVE: return "INACTIVE";
160 case STATE_IDLE_PENDING: return "IDLE_PENDING";
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700161 case STATE_SENSING: return "SENSING";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700162 case STATE_LOCATING: return "LOCATING";
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700163 case STATE_IDLE: return "IDLE";
164 case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
165 default: return Integer.toString(state);
166 }
167 }
168
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700169 /** Device is currently active. */
170 private static final int LIGHT_STATE_ACTIVE = 0;
171 /** Device is inactive (screen off) and we are waiting to for the first light idle. */
172 private static final int LIGHT_STATE_INACTIVE = 1;
173 /** Device is in the light idle state, trying to stay asleep as much as possible. */
174 private static final int LIGHT_STATE_IDLE = 2;
175 /** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
176 private static final int LIGHT_STATE_IDLE_MAINTENANCE = 3;
177 /** Device light idle state is overriden, now applying full doze state. */
178 private static final int LIGHT_STATE_OVERRIDE = 4;
179 private static String lightStateToString(int state) {
180 switch (state) {
181 case LIGHT_STATE_ACTIVE: return "ACTIVE";
182 case LIGHT_STATE_INACTIVE: return "INACTIVE";
183 case LIGHT_STATE_IDLE: return "IDLE";
184 case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
185 case LIGHT_STATE_OVERRIDE: return "OVERRIDE";
186 default: return Integer.toString(state);
187 }
188 }
189
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700190 private int mState;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700191 private int mLightState;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700192
193 private long mInactiveTimeout;
194 private long mNextAlarmTime;
195 private long mNextIdlePendingDelay;
196 private long mNextIdleDelay;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700197 private long mNextLightAlarmTime;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700198
199 public final AtomicFile mConfigFile;
200
201 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700202 * Package names the system has white-listed to opt out of power save restrictions,
203 * except for device idle mode.
204 */
205 private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
206
207 /**
208 * Package names the system has white-listed to opt out of power save restrictions for
209 * all modes.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700210 */
211 private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
212
213 /**
214 * Package names the user has white-listed to opt out of power save restrictions.
215 */
216 private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
217
218 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700219 * App IDs of built-in system apps that have been white-listed except for idle modes.
220 */
221 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
222 = new SparseBooleanArray();
223
224 /**
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700225 * App IDs of built-in system apps that have been white-listed.
226 */
227 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
228
229 /**
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700230 * App IDs that have been white-listed to opt out of power save restrictions, except
231 * for device idle modes.
232 */
233 private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
234
235 /**
236 * Current app IDs that are in the complete power save white list, but shouldn't be
237 * excluded from idle modes. This array can be shared with others because it will not be
238 * modified once set.
239 */
240 private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
241
242 /**
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700243 * App IDs that have been white-listed to opt out of power save restrictions.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700244 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700245 private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700246
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700247 /**
248 * Current app IDs that are in the complete power save white list. This array can
249 * be shared with others because it will not be modified once set.
250 */
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700251 private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -0700252
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700253 /**
254 * List of end times for UIDs that are temporarily marked as being allowed to access
255 * the network and acquire wakelocks. Times are in milliseconds.
256 */
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700257 private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
258 = new SparseArray<>();
259
260 /**
261 * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
262 */
263 Runnable mNetworkPolicyTempWhitelistCallback;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700264
265 /**
266 * Current app IDs of temporarily whitelist apps for high-priority messages.
267 */
268 private int[] mTempWhitelistAppIdArray = new int[0];
269
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700270 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
271 @Override public void onReceive(Context context, Intent intent) {
272 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
273 int plugged = intent.getIntExtra("plugged", 0);
274 updateChargingLocked(plugged != 0);
Dianne Hackborn1b79ad72015-10-12 10:59:47 -0700275 } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
276 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
277 Uri data = intent.getData();
278 String ssp;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700279 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
Dianne Hackborn1b79ad72015-10-12 10:59:47 -0700280 removePowerSaveWhitelistAppInternal(ssp);
281 }
282 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700283 } else if (ACTION_STEP_LIGHT_IDLE_STATE.equals(intent.getAction())) {
284 synchronized (DeviceIdleController.this) {
285 stepLightIdleStateLocked();
286 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700287 } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
288 synchronized (DeviceIdleController.this) {
289 stepIdleStateLocked();
290 }
291 }
292 }
293 };
294
295 private final DisplayManager.DisplayListener mDisplayListener
296 = new DisplayManager.DisplayListener() {
297 @Override public void onDisplayAdded(int displayId) {
298 }
299
300 @Override public void onDisplayRemoved(int displayId) {
301 }
302
303 @Override public void onDisplayChanged(int displayId) {
304 if (displayId == Display.DEFAULT_DISPLAY) {
305 synchronized (DeviceIdleController.this) {
306 updateDisplayLocked();
307 }
308 }
309 }
310 };
311
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700312 private final class MotionListener extends TriggerEventListener
313 implements SensorEventListener {
314
315 boolean active = false;
316
317 @Override
318 public void onTrigger(TriggerEvent event) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700319 synchronized (DeviceIdleController.this) {
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700320 active = false;
321 motionLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700322 }
323 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700324
325 @Override
326 public void onSensorChanged(SensorEvent event) {
327 synchronized (DeviceIdleController.this) {
328 mSensorManager.unregisterListener(this, mMotionSensor);
329 active = false;
330 motionLocked();
331 }
332 }
333
334 @Override
335 public void onAccuracyChanged(Sensor sensor, int accuracy) {}
336
337 public boolean registerLocked() {
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700338 boolean success;
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700339 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
340 success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
341 } else {
342 success = mSensorManager.registerListener(
343 mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL);
344 }
345 if (success) {
346 active = true;
347 } else {
348 Slog.e(TAG, "Unable to register for " + mMotionSensor);
349 }
350 return success;
351 }
352
353 public void unregisterLocked() {
354 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
355 mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor);
356 } else {
357 mSensorManager.unregisterListener(mMotionListener);
358 }
359 active = false;
360 }
361 }
362 private final MotionListener mMotionListener = new MotionListener();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700363
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700364 private final LocationListener mGenericLocationListener = new LocationListener() {
365 @Override
366 public void onLocationChanged(Location location) {
367 synchronized (DeviceIdleController.this) {
368 receivedGenericLocationLocked(location);
369 }
370 }
371
372 @Override
373 public void onStatusChanged(String provider, int status, Bundle extras) {
374 }
375
376 @Override
377 public void onProviderEnabled(String provider) {
378 }
379
380 @Override
381 public void onProviderDisabled(String provider) {
382 }
383 };
384
385 private final LocationListener mGpsLocationListener = new LocationListener() {
386 @Override
387 public void onLocationChanged(Location location) {
388 synchronized (DeviceIdleController.this) {
389 receivedGpsLocationLocked(location);
390 }
391 }
392
393 @Override
394 public void onStatusChanged(String provider, int status, Bundle extras) {
395 }
396
397 @Override
398 public void onProviderEnabled(String provider) {
399 }
400
401 @Override
402 public void onProviderDisabled(String provider) {
403 }
404 };
405
Adam Lesinski31c05d12015-06-09 17:34:04 -0700406 /**
407 * All times are in milliseconds. These constants are kept synchronized with the system
408 * global Settings. Any access to this class or its fields should be done while
409 * holding the DeviceIdleController lock.
410 */
Dianne Hackborna750a632015-06-16 17:18:23 -0700411 private final class Constants extends ContentObserver {
Adam Lesinski31c05d12015-06-09 17:34:04 -0700412 // Key names stored in the settings value.
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700413 private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
414 private static final String KEY_LIGHT_IDLE_PENDING_TIMEOUT = "light_idle_pending_to";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700415 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
416 private static final String KEY_SENSING_TIMEOUT = "sensing_to";
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700417 private static final String KEY_LOCATING_TIMEOUT = "locating_to";
418 private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700419 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
420 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
421 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
422 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
423 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
424 private static final String KEY_IDLE_TIMEOUT = "idle_to";
425 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
426 private static final String KEY_IDLE_FACTOR = "idle_factor";
427 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
428 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
429 "max_temp_app_whitelist_duration";
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700430 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
431 "mms_temp_app_whitelist_duration";
Dianne Hackborn451c3462015-07-21 17:39:46 -0700432 private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
433 "sms_temp_app_whitelist_duration";
Adam Lesinski31c05d12015-06-09 17:34:04 -0700434
435 /**
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700436 * This is the time, after becoming inactive, that we will start going
437 * in to light-weight idle mode.
438 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
439 * @see #KEY_LIGHT_IDLE_TIMEOUT
440 */
441 public long LIGHT_IDLE_TIMEOUT;
442
443 /**
444 * This is the initial time, after light idle idle, that we will will sit in the
445 * LIGHT_IDLE_MAINTENANCE period for the system to run normally before returning to idle.
446 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
447 * @see #KEY_LIGHT_IDLE_PENDING_TIMEOUT
448 */
449 public long LIGHT_IDLE_PENDING_TIMEOUT;
450
451 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -0700452 * This is the time, after becoming inactive, at which we start looking at the
453 * motion sensor to determine if the device is being left alone. We don't do this
454 * immediately after going inactive just because we don't want to be continually running
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700455 * the motion sensor whenever the screen is off.
Adam Lesinski31c05d12015-06-09 17:34:04 -0700456 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
457 * @see #KEY_INACTIVE_TIMEOUT
458 */
459 public long INACTIVE_TIMEOUT;
460
461 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700462 * If we don't receive a callback from AnyMotion in this amount of time +
463 * {@link #LOCATING_TIMEOUT}, we will change from
Adam Lesinski31c05d12015-06-09 17:34:04 -0700464 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
465 * will be ignored.
466 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
467 * @see #KEY_SENSING_TIMEOUT
468 */
469 public long SENSING_TIMEOUT;
470
471 /**
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700472 * This is how long we will wait to try to get a good location fix before going in to
473 * idle mode.
474 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
475 * @see #KEY_LOCATING_TIMEOUT
476 */
477 public long LOCATING_TIMEOUT;
478
479 /**
480 * The desired maximum accuracy (in meters) we consider the location to be good enough to go
481 * on to idle. We will be trying to get an accuracy fix at least this good or until
482 * {@link #LOCATING_TIMEOUT} expires.
483 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
484 * @see #KEY_LOCATION_ACCURACY
485 */
486 public float LOCATION_ACCURACY;
487
488 /**
Adam Lesinski31c05d12015-06-09 17:34:04 -0700489 * This is the time, after seeing motion, that we wait after becoming inactive from
490 * that until we start looking for motion again.
491 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
492 * @see #KEY_MOTION_INACTIVE_TIMEOUT
493 */
494 public long MOTION_INACTIVE_TIMEOUT;
495
496 /**
497 * This is the time, after the inactive timeout elapses, that we will wait looking
Nick Vaccaro20feaea2015-09-17 17:22:44 -0700498 * for motion until we truly consider the device to be idle.
Adam Lesinski31c05d12015-06-09 17:34:04 -0700499 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
500 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
501 */
502 public long IDLE_AFTER_INACTIVE_TIMEOUT;
503
504 /**
505 * This is the initial time, after being idle, that we will allow ourself to be back
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700506 * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
507 * idle.
Adam Lesinski31c05d12015-06-09 17:34:04 -0700508 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
509 * @see #KEY_IDLE_PENDING_TIMEOUT
510 */
511 public long IDLE_PENDING_TIMEOUT;
512
513 /**
514 * Maximum pending idle timeout (time spent running) we will be allowed to use.
515 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
516 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
517 */
518 public long MAX_IDLE_PENDING_TIMEOUT;
519
520 /**
521 * Scaling factor to apply to current pending idle timeout each time we cycle through
522 * that state.
523 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
524 * @see #KEY_IDLE_PENDING_FACTOR
525 */
526 public float IDLE_PENDING_FACTOR;
527
528 /**
529 * This is the initial time that we want to sit in the idle state before waking up
530 * again to return to pending idle and allowing normal work to run.
531 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
532 * @see #KEY_IDLE_TIMEOUT
533 */
534 public long IDLE_TIMEOUT;
535
536 /**
537 * Maximum idle duration we will be allowed to use.
538 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
539 * @see #KEY_MAX_IDLE_TIMEOUT
540 */
541 public long MAX_IDLE_TIMEOUT;
542
543 /**
544 * Scaling factor to apply to current idle timeout each time we cycle through that state.
545 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
546 * @see #KEY_IDLE_FACTOR
547 */
548 public float IDLE_FACTOR;
549
550 /**
551 * This is the minimum time we will allow until the next upcoming alarm for us to
552 * actually go in to idle mode.
553 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
554 * @see #KEY_MIN_TIME_TO_ALARM
555 */
556 public long MIN_TIME_TO_ALARM;
557
558 /**
559 * Max amount of time to temporarily whitelist an app when it receives a high priority
560 * tickle.
561 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
562 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
563 */
564 public long MAX_TEMP_APP_WHITELIST_DURATION;
565
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700566 /**
567 * Amount of time we would like to whitelist an app that is receiving an MMS.
568 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
569 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
570 */
571 public long MMS_TEMP_APP_WHITELIST_DURATION;
572
Dianne Hackborn451c3462015-07-21 17:39:46 -0700573 /**
574 * Amount of time we would like to whitelist an app that is receiving an SMS.
575 * @see Settings.Global#DEVICE_IDLE_CONSTANTS
576 * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
577 */
578 public long SMS_TEMP_APP_WHITELIST_DURATION;
579
Adam Lesinski31c05d12015-06-09 17:34:04 -0700580 private final ContentResolver mResolver;
581 private final KeyValueListParser mParser = new KeyValueListParser(',');
582
583 public Constants(Handler handler, ContentResolver resolver) {
584 super(handler);
585 mResolver = resolver;
586 mResolver.registerContentObserver(
587 Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), false, this);
588 updateConstants();
589 }
590
591 @Override
592 public void onChange(boolean selfChange, Uri uri) {
593 updateConstants();
594 }
595
596 private void updateConstants() {
597 synchronized (DeviceIdleController.this) {
598 try {
599 mParser.setString(Settings.Global.getString(mResolver,
600 Settings.Global.DEVICE_IDLE_CONSTANTS));
601 } catch (IllegalArgumentException e) {
602 // Failed to parse the settings string, log this and move on
603 // with defaults.
604 Slog.e(TAG, "Bad device idle settings", e);
605 }
606
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700607 LIGHT_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_TIMEOUT,
608 !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
609 LIGHT_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_PENDING_TIMEOUT,
610 !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700611 INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
612 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
613 SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700614 !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
615 LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
616 !DEBUG ? 30 * 1000L : 15 * 1000L);
617 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700618 MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
619 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
620 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
621 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
622 IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
623 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
624 MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
625 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
626 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
627 2f);
628 IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
629 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
630 MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
631 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
632 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
633 2f);
634 MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
635 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700636 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
637 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
638 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
Dianne Hackborn0b6134b2015-07-14 18:48:07 -0700639 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
Dianne Hackborn451c3462015-07-21 17:39:46 -0700640 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
641 KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
Adam Lesinski31c05d12015-06-09 17:34:04 -0700642 }
643 }
644
645 void dump(PrintWriter pw) {
646 pw.println(" Settings:");
647
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700648 pw.print(" "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
649 TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
650 pw.println();
651
652 pw.print(" "); pw.print(KEY_LIGHT_IDLE_PENDING_TIMEOUT); pw.print("=");
653 TimeUtils.formatDuration(LIGHT_IDLE_PENDING_TIMEOUT, pw);
654 pw.println();
655
Dianne Hackborna750a632015-06-16 17:18:23 -0700656 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700657 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
658 pw.println();
659
Dianne Hackborna750a632015-06-16 17:18:23 -0700660 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700661 TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
662 pw.println();
663
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700664 pw.print(" "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
665 TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
666 pw.println();
667
668 pw.print(" "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
669 pw.print(LOCATION_ACCURACY); pw.print("m");
670 pw.println();
671
Dianne Hackborna750a632015-06-16 17:18:23 -0700672 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700673 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
674 pw.println();
675
Dianne Hackborna750a632015-06-16 17:18:23 -0700676 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700677 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
678 pw.println();
679
Dianne Hackborna750a632015-06-16 17:18:23 -0700680 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700681 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
682 pw.println();
683
Dianne Hackborna750a632015-06-16 17:18:23 -0700684 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700685 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
686 pw.println();
687
Dianne Hackborna750a632015-06-16 17:18:23 -0700688 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700689 pw.println(IDLE_PENDING_FACTOR);
690
Dianne Hackborna750a632015-06-16 17:18:23 -0700691 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700692 TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
693 pw.println();
694
Dianne Hackborna750a632015-06-16 17:18:23 -0700695 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700696 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
697 pw.println();
698
Dianne Hackborna750a632015-06-16 17:18:23 -0700699 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700700 pw.println(IDLE_FACTOR);
701
Dianne Hackborna750a632015-06-16 17:18:23 -0700702 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700703 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
704 pw.println();
705
Dianne Hackborna750a632015-06-16 17:18:23 -0700706 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
Adam Lesinski31c05d12015-06-09 17:34:04 -0700707 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
708 pw.println();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700709
710 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
711 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
712 pw.println();
Dianne Hackborn451c3462015-07-21 17:39:46 -0700713
714 pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
715 TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
716 pw.println();
Adam Lesinski31c05d12015-06-09 17:34:04 -0700717 }
718 }
719
720 private Constants mConstants;
721
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700722 @Override
723 public void onAnyMotionResult(int result) {
724 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700725 if (result == AnyMotionDetector.RESULT_MOVED) {
726 if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
727 synchronized (this) {
728 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
729 }
730 } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
731 if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
732 if (mState == STATE_SENSING) {
733 // If we are currently sensing, it is time to move to locating.
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700734 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700735 mNotMoving = true;
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700736 stepIdleStateLocked();
737 }
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700738 } else if (mState == STATE_LOCATING) {
739 // If we are currently locating, note that we are not moving and step
740 // if we have located the position.
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700741 synchronized (this) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -0700742 mNotMoving = true;
743 if (mLocated) {
744 stepIdleStateLocked();
745 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700746 }
747 }
748 }
749 }
750
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700751 static final int MSG_WRITE_CONFIG = 1;
752 static final int MSG_REPORT_IDLE_ON = 2;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700753 static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
754 static final int MSG_REPORT_IDLE_OFF = 4;
755 static final int MSG_REPORT_ACTIVE = 5;
756 static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700757
758 final class MyHandler extends Handler {
759 MyHandler(Looper looper) {
760 super(looper);
761 }
762
763 @Override public void handleMessage(Message msg) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -0700764 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700765 switch (msg.what) {
766 case MSG_WRITE_CONFIG: {
767 handleWriteConfigFile();
768 } break;
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700769 case MSG_REPORT_IDLE_ON:
770 case MSG_REPORT_IDLE_ON_LIGHT: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700771 EventLogTags.writeDeviceIdleOnStart();
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700772 final boolean fullChanged;
773 final boolean lightChanged;
774 if (msg.what == MSG_REPORT_IDLE_ON) {
775 fullChanged = mLocalPowerManager.setDeviceIdleMode(true);
776 lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
777 } else {
778 fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
779 lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
780 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700781 try {
782 mNetworkPolicyManager.setDeviceIdleMode(true);
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700783 mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON
784 ? BatteryStats.DEVICE_IDLE_MODE_FULL
785 : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700786 } catch (RemoteException e) {
787 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700788 if (fullChanged) {
789 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
790 }
791 if (lightChanged) {
792 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
793 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700794 EventLogTags.writeDeviceIdleOnComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700795 } break;
796 case MSG_REPORT_IDLE_OFF: {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700797 EventLogTags.writeDeviceIdleOffStart("unknown");
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700798 final boolean fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
799 final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700800 try {
801 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700802 mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
803 null, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700804 } catch (RemoteException e) {
805 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700806 if (fullChanged) {
807 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
808 }
809 if (lightChanged) {
810 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
811 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700812 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700813 } break;
814 case MSG_REPORT_ACTIVE: {
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700815 String activeReason = (String)msg.obj;
816 int activeUid = msg.arg1;
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700817 EventLogTags.writeDeviceIdleOffStart(
818 activeReason != null ? activeReason : "unknown");
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700819 final boolean fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
820 final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700821 try {
822 mNetworkPolicyManager.setDeviceIdleMode(false);
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700823 mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
824 activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700825 } catch (RemoteException e) {
826 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700827 if (fullChanged) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700828 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
829 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700830 if (lightChanged) {
831 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
832 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700833 EventLogTags.writeDeviceIdleOffComplete();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700834 } break;
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700835 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
836 int uid = msg.arg1;
837 checkTempAppWhitelistTimeout(uid);
838 } break;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700839 }
840 }
841 }
842
843 final MyHandler mHandler;
844
Dianne Hackborn9461b6f2015-10-07 17:33:16 -0700845 BinderService mBinderService;
846
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700847 private final class BinderService extends IDeviceIdleController.Stub {
848 @Override public void addPowerSaveWhitelistApp(String name) {
849 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
850 null);
851 addPowerSaveWhitelistAppInternal(name);
852 }
853
854 @Override public void removePowerSaveWhitelistApp(String name) {
855 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
856 null);
857 removePowerSaveWhitelistAppInternal(name);
858 }
859
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700860 @Override public String[] getSystemPowerWhitelistExceptIdle() {
861 return getSystemPowerWhitelistExceptIdleInternal();
862 }
863
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700864 @Override public String[] getSystemPowerWhitelist() {
865 return getSystemPowerWhitelistInternal();
866 }
867
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700868 @Override public String[] getFullPowerWhitelistExceptIdle() {
869 return getFullPowerWhitelistExceptIdleInternal();
870 }
871
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700872 @Override public String[] getFullPowerWhitelist() {
873 return getFullPowerWhitelistInternal();
874 }
875
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700876 @Override public int[] getAppIdWhitelistExceptIdle() {
877 return getAppIdWhitelistExceptIdleInternal();
878 }
879
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700880 @Override public int[] getAppIdWhitelist() {
881 return getAppIdWhitelistInternal();
882 }
883
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700884 @Override public int[] getAppIdTempWhitelist() {
885 return getAppIdTempWhitelistInternal();
886 }
887
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700888 @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
889 return isPowerSaveWhitelistExceptIdleAppInternal(name);
890 }
891
Amith Yamasani06bf8242015-05-08 16:36:21 -0700892 @Override public boolean isPowerSaveWhitelistApp(String name) {
893 return isPowerSaveWhitelistAppInternal(name);
894 }
895
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700896 @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700897 int userId, String reason) throws RemoteException {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -0700898 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700899 }
900
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700901 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
902 int userId, String reason) throws RemoteException {
903 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -0700904 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700905 return duration;
906 }
907
Dianne Hackborn451c3462015-07-21 17:39:46 -0700908 @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
909 int userId, String reason) throws RemoteException {
910 long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
Dianne Hackborn9461b6f2015-10-07 17:33:16 -0700911 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
Dianne Hackborn451c3462015-07-21 17:39:46 -0700912 return duration;
913 }
914
Dianne Hackbornb6683c42015-06-18 17:40:33 -0700915 @Override public void exitIdle(String reason) {
916 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
917 null);
918 exitIdleInternal(reason);
919 }
920
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700921 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
922 DeviceIdleController.this.dump(fd, pw, args);
923 }
Dianne Hackborn9461b6f2015-10-07 17:33:16 -0700924
925 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
926 FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
927 (new Shell()).exec(this, in, out, err, args, resultReceiver);
928 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700929 }
930
Dianne Hackborna750a632015-06-16 17:18:23 -0700931 public final class LocalService {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -0700932 public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
933 String reason) {
934 addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
935 }
936
937 public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
938 setNetworkPolicyTempWhitelistCallbackInternal(callback);
Dianne Hackborna750a632015-06-16 17:18:23 -0700939 }
940 }
941
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700942 public DeviceIdleController(Context context) {
943 super(context);
944 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
945 mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
946 }
947
948 private static File getSystemDir() {
949 return new File(Environment.getDataDirectory(), "system");
950 }
951
952 @Override
953 public void onStart() {
954 final PackageManager pm = getContext().getPackageManager();
955
956 synchronized (this) {
Dianne Hackborn92617032015-06-19 15:32:19 -0700957 mEnabled = getContext().getResources().getBoolean(
958 com.android.internal.R.bool.config_enableAutoPowerModes);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700959 SystemConfig sysConfig = SystemConfig.getInstance();
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700960 ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
961 for (int i=0; i<allowPowerExceptIdle.size(); i++) {
962 String pkg = allowPowerExceptIdle.valueAt(i);
963 try {
964 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
965 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
966 int appid = UserHandle.getAppId(ai.uid);
967 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
968 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
969 }
970 } catch (PackageManager.NameNotFoundException e) {
971 }
972 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700973 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
974 for (int i=0; i<allowPower.size(); i++) {
975 String pkg = allowPower.valueAt(i);
976 try {
977 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
978 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700979 int appid = UserHandle.getAppId(ai.uid);
Dianne Hackborn4a503b12015-08-06 22:19:06 -0700980 // These apps are on both the whitelist-except-idle as well
981 // as the full whitelist, so they apply in all cases.
982 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
983 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -0700984 mPowerSaveWhitelistApps.put(ai.packageName, appid);
985 mPowerSaveWhitelistSystemAppIds.put(appid, true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700986 }
987 } catch (PackageManager.NameNotFoundException e) {
988 }
989 }
990
Adam Lesinski31c05d12015-06-09 17:34:04 -0700991 mConstants = new Constants(mHandler, getContext().getContentResolver());
992
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700993 readConfigFileLocked();
994 updateWhitelistAppIdsLocked();
995
996 mScreenOn = true;
997 // Start out assuming we are charging. If we aren't, we will at least get
998 // a battery update the next time the level drops.
999 mCharging = true;
1000 mState = STATE_ACTIVE;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001001 mLightState = LIGHT_STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -07001002 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001003 }
1004
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001005 mBinderService = new BinderService();
1006 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);
Dianne Hackborna750a632015-06-16 17:18:23 -07001007 publishLocalService(LocalService.class, new LocalService());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001008 }
1009
1010 @Override
1011 public void onBootPhase(int phase) {
1012 if (phase == PHASE_SYSTEM_SERVICES_READY) {
1013 synchronized (this) {
1014 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
1015 mBatteryStats = BatteryStatsService.getService();
1016 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
1017 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001018 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001019 mDisplayManager = (DisplayManager) getContext().getSystemService(
1020 Context.DISPLAY_SERVICE);
1021 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001022 int sigMotionSensorId = getContext().getResources().getInteger(
1023 com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
1024 if (sigMotionSensorId > 0) {
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001025 mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001026 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001027 if (mMotionSensor == null && getContext().getResources().getBoolean(
Joe LaPenna23d681b2015-08-27 15:12:11 -07001028 com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001029 mMotionSensor = mSensorManager.getDefaultSensor(
1030 Sensor.TYPE_WRIST_TILT_GESTURE, true);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001031 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001032 if (mMotionSensor == null) {
Joe LaPenna23d681b2015-08-27 15:12:11 -07001033 // As a last ditch, fall back to SMD.
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001034 mMotionSensor = mSensorManager.getDefaultSensor(
1035 Sensor.TYPE_SIGNIFICANT_MOTION, true);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001036 }
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001037
Joe LaPenna23d681b2015-08-27 15:12:11 -07001038 if (getContext().getResources().getBoolean(
1039 com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
1040 mLocationManager = (LocationManager) getContext().getSystemService(
1041 Context.LOCATION_SERVICE);
1042 mLocationRequest = new LocationRequest()
1043 .setQuality(LocationRequest.ACCURACY_FINE)
1044 .setInterval(0)
1045 .setFastestInterval(0)
1046 .setNumUpdates(1);
1047 }
1048
1049 float angleThreshold = getContext().getResources().getInteger(
1050 com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001051 mAnyMotionDetector = new AnyMotionDetector(
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001052 (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
Joe LaPenna23d681b2015-08-27 15:12:11 -07001053 mHandler, mSensorManager, this, angleThreshold);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001054
1055 Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
1056 .setPackage("android")
1057 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1058 mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
1059
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001060 Intent intentLight = new Intent(ACTION_STEP_LIGHT_IDLE_STATE)
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001061 .setPackage("android")
1062 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001063 mLightAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentLight, 0);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001064
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001065 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001066 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1067 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001068 mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
1069 mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1070 | Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001071
1072 IntentFilter filter = new IntentFilter();
1073 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
1074 filter.addAction(ACTION_STEP_IDLE_STATE);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001075 filter.addAction(ACTION_STEP_LIGHT_IDLE_STATE);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001076 getContext().registerReceiver(mReceiver, filter);
Dianne Hackborn1b79ad72015-10-12 10:59:47 -07001077 filter = new IntentFilter();
1078 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
1079 filter.addDataScheme("package");
1080 getContext().registerReceiver(mReceiver, filter);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001081
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001082 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001083
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001084 mDisplayManager.registerDisplayListener(mDisplayListener, null);
1085 updateDisplayLocked();
1086 }
1087 }
1088 }
1089
1090 public boolean addPowerSaveWhitelistAppInternal(String name) {
1091 synchronized (this) {
1092 try {
Dianne Hackborn1b79ad72015-10-12 10:59:47 -07001093 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
1094 PackageManager.GET_UNINSTALLED_PACKAGES
1095 | PackageManager.GET_DISABLED_COMPONENTS
1096 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001097 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
1098 reportPowerSaveWhitelistChangedLocked();
1099 updateWhitelistAppIdsLocked();
1100 writeConfigFileLocked();
1101 }
1102 return true;
1103 } catch (PackageManager.NameNotFoundException e) {
1104 return false;
1105 }
1106 }
1107 }
1108
1109 public boolean removePowerSaveWhitelistAppInternal(String name) {
1110 synchronized (this) {
1111 if (mPowerSaveWhitelistUserApps.remove(name) != null) {
1112 reportPowerSaveWhitelistChangedLocked();
1113 updateWhitelistAppIdsLocked();
1114 writeConfigFileLocked();
1115 return true;
1116 }
1117 }
1118 return false;
1119 }
1120
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001121 public String[] getSystemPowerWhitelistExceptIdleInternal() {
1122 synchronized (this) {
1123 int size = mPowerSaveWhitelistAppsExceptIdle.size();
1124 String[] apps = new String[size];
1125 for (int i = 0; i < size; i++) {
1126 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1127 }
1128 return apps;
1129 }
1130 }
1131
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001132 public String[] getSystemPowerWhitelistInternal() {
1133 synchronized (this) {
1134 int size = mPowerSaveWhitelistApps.size();
1135 String[] apps = new String[size];
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001136 for (int i = 0; i < size; i++) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001137 apps[i] = mPowerSaveWhitelistApps.keyAt(i);
1138 }
1139 return apps;
1140 }
1141 }
1142
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001143 public String[] getFullPowerWhitelistExceptIdleInternal() {
1144 synchronized (this) {
1145 int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
1146 String[] apps = new String[size];
1147 int cur = 0;
1148 for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
1149 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1150 cur++;
1151 }
1152 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1153 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1154 cur++;
1155 }
1156 return apps;
1157 }
1158 }
1159
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001160 public String[] getFullPowerWhitelistInternal() {
1161 synchronized (this) {
1162 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
1163 String[] apps = new String[size];
1164 int cur = 0;
1165 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
1166 apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
1167 cur++;
1168 }
1169 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1170 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1171 cur++;
1172 }
1173 return apps;
1174 }
1175 }
1176
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001177 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
1178 synchronized (this) {
1179 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
1180 || mPowerSaveWhitelistUserApps.containsKey(packageName);
1181 }
1182 }
1183
Amith Yamasani06bf8242015-05-08 16:36:21 -07001184 public boolean isPowerSaveWhitelistAppInternal(String packageName) {
1185 synchronized (this) {
1186 return mPowerSaveWhitelistApps.containsKey(packageName)
1187 || mPowerSaveWhitelistUserApps.containsKey(packageName);
1188 }
1189 }
1190
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001191 public int[] getAppIdWhitelistExceptIdleInternal() {
1192 synchronized (this) {
1193 return mPowerSaveWhitelistExceptIdleAppIdArray;
1194 }
1195 }
1196
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001197 public int[] getAppIdWhitelistInternal() {
1198 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001199 return mPowerSaveWhitelistAllAppIdArray;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001200 }
1201 }
1202
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001203 public int[] getAppIdTempWhitelistInternal() {
1204 synchronized (this) {
1205 return mTempWhitelistAppIdArray;
1206 }
1207 }
1208
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001209 void addPowerSaveTempWhitelistAppChecked(String packageName, long duration,
1210 int userId, String reason) throws RemoteException {
1211 getContext().enforceCallingPermission(
1212 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
1213 "No permission to change device idle whitelist");
1214 final int callingUid = Binder.getCallingUid();
1215 userId = ActivityManagerNative.getDefault().handleIncomingUser(
1216 Binder.getCallingPid(),
1217 callingUid,
1218 userId,
1219 /*allowAll=*/ false,
1220 /*requireFull=*/ false,
1221 "addPowerSaveTempWhitelistApp", null);
1222 final long token = Binder.clearCallingIdentity();
1223 try {
1224 addPowerSaveTempWhitelistAppInternal(callingUid,
1225 packageName, duration, userId, true, reason);
1226 } finally {
1227 Binder.restoreCallingIdentity(token);
1228 }
1229 }
1230
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001231 /**
1232 * Adds an app to the temporary whitelist and resets the endTime for granting the
1233 * app an exemption to access network and acquire wakelocks.
1234 */
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001235 void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001236 long duration, int userId, boolean sync, String reason) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001237 try {
1238 int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
1239 int appId = UserHandle.getAppId(uid);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001240 addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001241 } catch (NameNotFoundException e) {
1242 }
1243 }
1244
Dianne Hackborna750a632015-06-16 17:18:23 -07001245 /**
1246 * Adds an app to the temporary whitelist and resets the endTime for granting the
1247 * app an exemption to access network and acquire wakelocks.
1248 */
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001249 void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001250 long duration, boolean sync, String reason) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001251 final long timeNow = SystemClock.elapsedRealtime();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001252 Runnable networkPolicyTempWhitelistCallback = null;
Dianne Hackborna750a632015-06-16 17:18:23 -07001253 synchronized (this) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001254 int callingAppId = UserHandle.getAppId(callingUid);
1255 if (callingAppId >= Process.FIRST_APPLICATION_UID) {
1256 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
1257 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
1258 + " is not on whitelist");
1259 }
1260 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001261 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001262 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
1263 final boolean newEntry = entry == null;
Dianne Hackborna750a632015-06-16 17:18:23 -07001264 // Set the new end time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001265 if (newEntry) {
1266 entry = new Pair<>(new MutableLong(0), reason);
1267 mTempWhitelistAppIdEndTimes.put(appId, entry);
1268 }
1269 entry.first.value = timeNow + duration;
Dianne Hackborna750a632015-06-16 17:18:23 -07001270 if (DEBUG) {
1271 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
1272 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001273 if (newEntry) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001274 // No pending timeout for the app id, post a delayed message
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001275 try {
1276 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
1277 reason, appId);
1278 } catch (RemoteException e) {
1279 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001280 postTempActiveTimeoutMessage(appId, duration);
1281 updateTempWhitelistAppIdsLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001282 if (mNetworkPolicyTempWhitelistCallback != null) {
1283 if (!sync) {
1284 mHandler.post(mNetworkPolicyTempWhitelistCallback);
1285 } else {
1286 networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
1287 }
1288 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001289 reportTempWhitelistChangedLocked();
1290 }
1291 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001292 if (networkPolicyTempWhitelistCallback != null) {
1293 networkPolicyTempWhitelistCallback.run();
1294 }
1295 }
1296
1297 public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
1298 synchronized (this) {
1299 mNetworkPolicyTempWhitelistCallback = callback;
1300 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001301 }
1302
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001303 private void postTempActiveTimeoutMessage(int uid, long delay) {
1304 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
1305 delay);
1306 }
1307
1308 void checkTempAppWhitelistTimeout(int uid) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001309 final long timeNow = SystemClock.elapsedRealtime();
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001310 synchronized (this) {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001311 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
1312 if (entry == null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001313 // Nothing to do
1314 return;
1315 }
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001316 if (timeNow >= entry.first.value) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001317 mTempWhitelistAppIdEndTimes.delete(uid);
1318 if (DEBUG) {
1319 Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
1320 }
1321 updateTempWhitelistAppIdsLocked();
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001322 if (mNetworkPolicyTempWhitelistCallback != null) {
1323 mHandler.post(mNetworkPolicyTempWhitelistCallback);
1324 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001325 reportTempWhitelistChangedLocked();
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001326 try {
1327 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
1328 entry.second, uid);
1329 } catch (RemoteException e) {
1330 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001331 } else {
1332 // Need more time
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001333 postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001334 }
1335 }
1336 }
1337
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001338 public void exitIdleInternal(String reason) {
1339 synchronized (this) {
1340 becomeActiveLocked(reason, Binder.getCallingUid());
1341 }
1342 }
1343
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001344 void updateDisplayLocked() {
1345 mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
1346 // We consider any situation where the display is showing something to be it on,
1347 // because if there is anything shown we are going to be updating it at some
1348 // frequency so can't be allowed to go into deep sleeps.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001349 boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001350 if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001351 if (!screenOn && mScreenOn) {
1352 mScreenOn = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001353 if (!mForceIdle) {
1354 becomeInactiveIfAppropriateLocked();
1355 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001356 } else if (screenOn) {
1357 mScreenOn = true;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001358 if (!mForceIdle) {
1359 becomeActiveLocked("screen", Process.myUid());
1360 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001361 }
1362 }
1363
1364 void updateChargingLocked(boolean charging) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001365 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001366 if (!charging && mCharging) {
1367 mCharging = false;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001368 if (!mForceIdle) {
1369 becomeInactiveIfAppropriateLocked();
1370 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001371 } else if (charging) {
1372 mCharging = charging;
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001373 if (!mForceIdle) {
1374 becomeActiveLocked("charging", Process.myUid());
1375 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001376 }
1377 }
1378
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001379 void scheduleReportActiveLocked(String activeReason, int activeUid) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001380 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001381 mHandler.sendMessage(msg);
1382 }
1383
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001384 void becomeActiveLocked(String activeReason, int activeUid) {
1385 if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001386 if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001387 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001388 EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001389 scheduleReportActiveLocked(activeReason, activeUid);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001390 mState = STATE_ACTIVE;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001391 mLightState = LIGHT_STATE_ACTIVE;
Adam Lesinski31c05d12015-06-09 17:34:04 -07001392 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001393 resetIdleManagementLocked();
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001394 resetLightIdleManagementLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001395 }
1396 }
1397
1398 void becomeInactiveIfAppropriateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001399 if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001400 if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001401 // Screen has turned off; we are now going to become inactive and start
1402 // waiting to see if we will ultimately go idle.
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001403 if (mState == STATE_ACTIVE) {
1404 mState = STATE_INACTIVE;
1405 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
1406 resetIdleManagementLocked();
1407 scheduleAlarmLocked(mInactiveTimeout, false);
1408 EventLogTags.writeDeviceIdle(mState, "no activity");
1409 }
1410 if (mLightState == LIGHT_STATE_ACTIVE) {
1411 mLightState = LIGHT_STATE_INACTIVE;
1412 if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
1413 resetLightIdleManagementLocked();
1414 scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_TIMEOUT);
1415 EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
1416 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001417 }
1418 }
1419
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001420 void resetIdleManagementLocked() {
1421 mNextIdlePendingDelay = 0;
1422 mNextIdleDelay = 0;
1423 cancelAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001424 cancelLocatingLocked();
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001425 stopMonitoringMotionLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001426 mAnyMotionDetector.stop();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001427 }
1428
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001429 void resetLightIdleManagementLocked() {
1430 cancelLightAlarmLocked();
1431 }
1432
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001433 void exitForceIdleLocked() {
1434 if (mForceIdle) {
1435 mForceIdle = false;
1436 if (mScreenOn || mCharging) {
1437 becomeActiveLocked("exit-force-idle", Process.myUid());
1438 }
1439 }
1440 }
1441
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001442 void stepLightIdleStateLocked() {
1443 if (mLightState == LIGHT_STATE_OVERRIDE) {
1444 // If we are already in full device idle mode, then
1445 // there is nothing left to do for light mode.
1446 return;
1447 }
1448
1449 if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState);
1450 EventLogTags.writeDeviceIdleLightStep();
1451
1452 switch (mLightState) {
1453 case LIGHT_STATE_INACTIVE:
1454 case LIGHT_STATE_IDLE_MAINTENANCE:
1455 scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_TIMEOUT);
1456 if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
1457 mLightState = LIGHT_STATE_IDLE;
1458 EventLogTags.writeDeviceIdleLight(mLightState, "step");
1459 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
1460 break;
1461 case LIGHT_STATE_IDLE:
1462 // We have been idling long enough, now it is time to do some work.
1463 scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_PENDING_TIMEOUT);
1464 if (DEBUG) Slog.d(TAG,
1465 "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
1466 mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
1467 EventLogTags.writeDeviceIdleLight(mLightState, "step");
1468 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1469 break;
1470 }
1471 }
1472
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001473 void stepIdleStateLocked() {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001474 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001475 EventLogTags.writeDeviceIdleStep();
1476
1477 final long now = SystemClock.elapsedRealtime();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001478 if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001479 // Whoops, there is an upcoming alarm. We don't actually want to go idle.
1480 if (mState != STATE_ACTIVE) {
Dianne Hackbornb6683c42015-06-18 17:40:33 -07001481 becomeActiveLocked("alarm", Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001482 }
1483 return;
1484 }
1485
1486 switch (mState) {
1487 case STATE_INACTIVE:
1488 // We have now been inactive long enough, it is time to start looking
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001489 // for motion and sleep some more while doing so.
1490 startMonitoringMotionLocked();
Adam Lesinski31c05d12015-06-09 17:34:04 -07001491 scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001492 // Reset the upcoming idle delays.
Adam Lesinski31c05d12015-06-09 17:34:04 -07001493 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
1494 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001495 mState = STATE_IDLE_PENDING;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001496 if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001497 EventLogTags.writeDeviceIdle(mState, "step");
1498 break;
1499 case STATE_IDLE_PENDING:
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001500 mState = STATE_SENSING;
1501 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001502 EventLogTags.writeDeviceIdle(mState, "step");
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001503 cancelAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001504 cancelLocatingLocked();
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001505 mAnyMotionDetector.checkForAnyMotion();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001506 mNotMoving = false;
1507 mLocated = false;
1508 mLastGenericLocation = null;
1509 mLastGpsLocation = null;
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001510 break;
1511 case STATE_SENSING:
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001512 mState = STATE_LOCATING;
1513 if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
1514 EventLogTags.writeDeviceIdle(mState, "step");
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001515 scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001516 if (mLocationManager != null
1517 && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
1518 mLocationManager.requestLocationUpdates(mLocationRequest,
1519 mGenericLocationListener, mHandler.getLooper());
1520 mLocating = true;
1521 } else {
1522 mHasNetworkLocation = false;
1523 }
1524 if (mLocationManager != null
1525 && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
1526 mHasGps = true;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001527 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
1528 mGpsLocationListener, mHandler.getLooper());
Joe LaPenna23d681b2015-08-27 15:12:11 -07001529 mLocating = true;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001530 } else {
Joe LaPenna23d681b2015-08-27 15:12:11 -07001531 mHasGps = false;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001532 }
Joe LaPenna23d681b2015-08-27 15:12:11 -07001533 // If we have a location provider, we're all set, the listeners will move state
1534 // forward.
1535 if (mLocating) {
1536 break;
1537 }
1538
1539 // Otherwise, we have to move from locating into idle maintenance.
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001540 case STATE_LOCATING:
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001541 cancelAlarmLocked();
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001542 cancelLocatingLocked();
1543 mAnyMotionDetector.stop();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001544 case STATE_IDLE_MAINTENANCE:
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001545 scheduleAlarmLocked(mNextIdleDelay, true);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001546 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
1547 " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001548 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001549 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
Adam Lesinski31c05d12015-06-09 17:34:04 -07001550 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001551 mState = STATE_IDLE;
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001552 if (mLightState != LIGHT_STATE_OVERRIDE) {
1553 mLightState = LIGHT_STATE_OVERRIDE;
1554 cancelLightAlarmLocked();
1555 }
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001556 EventLogTags.writeDeviceIdle(mState, "step");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001557 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
1558 break;
1559 case STATE_IDLE:
1560 // We have been idling long enough, now it is time to do some work.
1561 scheduleAlarmLocked(mNextIdlePendingDelay, false);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001562 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
1563 "Next alarm in " + mNextIdlePendingDelay + " ms.");
Adam Lesinski31c05d12015-06-09 17:34:04 -07001564 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
1565 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001566 mState = STATE_IDLE_MAINTENANCE;
1567 EventLogTags.writeDeviceIdle(mState, "step");
1568 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1569 break;
1570 }
1571 }
1572
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001573 void motionLocked() {
1574 if (DEBUG) Slog.d(TAG, "motionLocked()");
1575 // The motion sensor will have been disabled at this point
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001576 handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
1577 }
1578
1579 void handleMotionDetectedLocked(long timeout, String type) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001580 // The device is not yet active, so we want to go back to the pending idle
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001581 // state to wait again for no motion. Note that we only monitor for motion
1582 // after moving out of the inactive state, so no need to worry about that.
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001583 boolean becomeInactive = false;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001584 if (mState != STATE_ACTIVE) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001585 scheduleReportActiveLocked(type, Process.myUid());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001586 mState = STATE_ACTIVE;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001587 mInactiveTimeout = timeout;
1588 EventLogTags.writeDeviceIdle(mState, type);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001589 becomeInactive = true;
1590 }
1591 if (mLightState == LIGHT_STATE_OVERRIDE) {
1592 // We went out of light idle mode because we had started full idle mode... let's
1593 // now go back and reset things so we resume light idling if appropriate.
1594 mLightState = STATE_ACTIVE;
1595 EventLogTags.writeDeviceIdleLight(mLightState, type);
1596 becomeInactive = true;
1597 }
1598 if (becomeInactive) {
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001599 becomeInactiveIfAppropriateLocked();
1600 }
1601 }
1602
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001603 void receivedGenericLocationLocked(Location location) {
1604 if (mState != STATE_LOCATING) {
1605 cancelLocatingLocked();
1606 return;
1607 }
1608 if (DEBUG) Slog.d(TAG, "Generic location: " + location);
1609 mLastGenericLocation = new Location(location);
Joe LaPenna23d681b2015-08-27 15:12:11 -07001610 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001611 return;
1612 }
1613 mLocated = true;
1614 if (mNotMoving) {
1615 stepIdleStateLocked();
1616 }
1617 }
1618
1619 void receivedGpsLocationLocked(Location location) {
1620 if (mState != STATE_LOCATING) {
1621 cancelLocatingLocked();
1622 return;
1623 }
1624 if (DEBUG) Slog.d(TAG, "GPS location: " + location);
1625 mLastGpsLocation = new Location(location);
1626 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
1627 return;
1628 }
1629 mLocated = true;
1630 if (mNotMoving) {
1631 stepIdleStateLocked();
1632 }
1633 }
1634
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001635 void startMonitoringMotionLocked() {
1636 if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()");
1637 if (mMotionSensor != null && !mMotionListener.active) {
1638 mMotionListener.registerLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001639 }
1640 }
1641
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001642 void stopMonitoringMotionLocked() {
1643 if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()");
1644 if (mMotionSensor != null && mMotionListener.active) {
1645 mMotionListener.unregisterLocked();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001646 }
1647 }
1648
1649 void cancelAlarmLocked() {
1650 if (mNextAlarmTime != 0) {
1651 mNextAlarmTime = 0;
1652 mAlarmManager.cancel(mAlarmIntent);
1653 }
1654 }
1655
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001656 void cancelLightAlarmLocked() {
1657 if (mNextLightAlarmTime != 0) {
1658 mNextLightAlarmTime = 0;
1659 mAlarmManager.cancel(mLightAlarmIntent);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001660 }
1661 }
1662
1663 void cancelLocatingLocked() {
1664 if (mLocating) {
1665 mLocationManager.removeUpdates(mGenericLocationListener);
1666 mLocationManager.removeUpdates(mGpsLocationListener);
1667 mLocating = false;
1668 }
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001669 }
1670
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001671 void scheduleAlarmLocked(long delay, boolean idleUntil) {
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001672 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
Nick Vaccaro20feaea2015-09-17 17:22:44 -07001673 if (mMotionSensor == null) {
Joe LaPenna23d681b2015-08-27 15:12:11 -07001674 // If there is no motion sensor on this device, then we won't schedule
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001675 // alarms, because we can't determine if the device is not moving. This effectively
Joe LaPenna23d681b2015-08-27 15:12:11 -07001676 // turns off normal execution of device idling, although it is still possible to
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001677 // manually poke it by pretending like the alarm is going off.
1678 return;
1679 }
1680 mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1681 if (idleUntil) {
1682 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1683 mNextAlarmTime, mAlarmIntent);
1684 } else {
1685 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1686 mNextAlarmTime, mAlarmIntent);
1687 }
1688 }
1689
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001690 void scheduleLightAlarmLocked(long delay) {
1691 if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
1692 if (mMotionSensor == null) {
1693 // If there is no motion sensor on this device, then we won't schedule
1694 // alarms, because we can't determine if the device is not moving. This effectively
1695 // turns off normal execution of device idling, although it is still possible to
1696 // manually poke it by pretending like the alarm is going off.
1697 return;
1698 }
1699 mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07001700 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001701 mNextLightAlarmTime, mLightAlarmIntent);
Kevin Gabayan89ecf822015-05-18 12:10:07 -07001702 }
1703
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001704 private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
1705 ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
1706 outAppIds.clear();
1707 for (int i=0; i<systemApps.size(); i++) {
1708 outAppIds.put(systemApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001709 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001710 for (int i=0; i<userApps.size(); i++) {
1711 outAppIds.put(userApps.valueAt(i), true);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001712 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001713 int size = outAppIds.size();
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001714 int[] appids = new int[size];
1715 for (int i = 0; i < size; i++) {
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001716 appids[i] = outAppIds.keyAt(i);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001717 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001718 return appids;
1719 }
1720
1721 private void updateWhitelistAppIdsLocked() {
1722 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
1723 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
1724 mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
1725 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001726 if (mLocalPowerManager != null) {
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001727 if (DEBUG) {
1728 Slog.d(TAG, "Setting wakelock whitelist to "
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001729 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001730 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07001731 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001732 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001733 }
1734
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001735 private void updateTempWhitelistAppIdsLocked() {
1736 final int size = mTempWhitelistAppIdEndTimes.size();
1737 if (mTempWhitelistAppIdArray.length != size) {
1738 mTempWhitelistAppIdArray = new int[size];
1739 }
1740 for (int i = 0; i < size; i++) {
1741 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
1742 }
1743 if (mLocalPowerManager != null) {
1744 if (DEBUG) {
1745 Slog.d(TAG, "Setting wakelock temp whitelist to "
1746 + Arrays.toString(mTempWhitelistAppIdArray));
1747 }
1748 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
1749 }
1750 }
1751
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001752 private void reportPowerSaveWhitelistChangedLocked() {
1753 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
1754 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Xiaohui Chene4de5a02015-09-22 15:33:31 -07001755 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001756 }
1757
1758 private void reportTempWhitelistChangedLocked() {
1759 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
1760 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Xiaohui Chene4de5a02015-09-22 15:33:31 -07001761 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001762 }
1763
1764 void readConfigFileLocked() {
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07001765 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001766 mPowerSaveWhitelistUserApps.clear();
1767 FileInputStream stream;
1768 try {
1769 stream = mConfigFile.openRead();
1770 } catch (FileNotFoundException e) {
1771 return;
1772 }
1773 try {
1774 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001775 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001776 readConfigFileLocked(parser);
1777 } catch (XmlPullParserException e) {
1778 } finally {
1779 try {
1780 stream.close();
1781 } catch (IOException e) {
1782 }
1783 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001784 }
1785
1786 private void readConfigFileLocked(XmlPullParser parser) {
1787 final PackageManager pm = getContext().getPackageManager();
1788
1789 try {
1790 int type;
1791 while ((type = parser.next()) != XmlPullParser.START_TAG
1792 && type != XmlPullParser.END_DOCUMENT) {
1793 ;
1794 }
1795
1796 if (type != XmlPullParser.START_TAG) {
1797 throw new IllegalStateException("no start tag found");
1798 }
1799
1800 int outerDepth = parser.getDepth();
1801 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1802 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1803 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1804 continue;
1805 }
1806
1807 String tagName = parser.getName();
1808 if (tagName.equals("wl")) {
1809 String name = parser.getAttributeValue(null, "n");
1810 if (name != null) {
1811 try {
Dianne Hackborn1b79ad72015-10-12 10:59:47 -07001812 ApplicationInfo ai = pm.getApplicationInfo(name,
1813 PackageManager.GET_UNINSTALLED_PACKAGES
1814 | PackageManager.GET_DISABLED_COMPONENTS
1815 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001816 mPowerSaveWhitelistUserApps.put(ai.packageName,
1817 UserHandle.getAppId(ai.uid));
1818 } catch (PackageManager.NameNotFoundException e) {
1819 }
1820 }
1821 } else {
1822 Slog.w(TAG, "Unknown element under <config>: "
1823 + parser.getName());
1824 XmlUtils.skipCurrentTag(parser);
1825 }
1826 }
1827
1828 } catch (IllegalStateException e) {
1829 Slog.w(TAG, "Failed parsing config " + e);
1830 } catch (NullPointerException e) {
1831 Slog.w(TAG, "Failed parsing config " + e);
1832 } catch (NumberFormatException e) {
1833 Slog.w(TAG, "Failed parsing config " + e);
1834 } catch (XmlPullParserException e) {
1835 Slog.w(TAG, "Failed parsing config " + e);
1836 } catch (IOException e) {
1837 Slog.w(TAG, "Failed parsing config " + e);
1838 } catch (IndexOutOfBoundsException e) {
1839 Slog.w(TAG, "Failed parsing config " + e);
1840 }
1841 }
1842
1843 void writeConfigFileLocked() {
1844 mHandler.removeMessages(MSG_WRITE_CONFIG);
1845 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
1846 }
1847
1848 void handleWriteConfigFile() {
1849 final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
1850
1851 try {
1852 synchronized (this) {
1853 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001854 out.setOutput(memStream, StandardCharsets.UTF_8.name());
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001855 writeConfigFileLocked(out);
1856 }
1857 } catch (IOException e) {
1858 }
1859
1860 synchronized (mConfigFile) {
1861 FileOutputStream stream = null;
1862 try {
1863 stream = mConfigFile.startWrite();
1864 memStream.writeTo(stream);
1865 stream.flush();
1866 FileUtils.sync(stream);
1867 stream.close();
1868 mConfigFile.finishWrite(stream);
1869 } catch (IOException e) {
1870 Slog.w(TAG, "Error writing config file", e);
1871 mConfigFile.failWrite(stream);
1872 }
1873 }
1874 }
1875
1876 void writeConfigFileLocked(XmlSerializer out) throws IOException {
1877 out.startDocument(null, true);
1878 out.startTag(null, "config");
1879 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
1880 String name = mPowerSaveWhitelistUserApps.keyAt(i);
1881 out.startTag(null, "wl");
1882 out.attribute(null, "n", name);
1883 out.endTag(null, "wl");
1884 }
1885 out.endTag(null, "config");
1886 out.endDocument();
1887 }
1888
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001889 static void dumpHelp(PrintWriter pw) {
1890 pw.println("Device idle controller (deviceidle) commands:");
1891 pw.println(" help");
1892 pw.println(" Print this help text.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001893 pw.println(" step");
1894 pw.println(" Immediately step to next state, without waiting for alarm.");
Dianne Hackborn4a503b12015-08-06 22:19:06 -07001895 pw.println(" force-idle");
1896 pw.println(" Force directly into idle mode, regardless of other device state.");
1897 pw.println(" Use \"step\" to get out.");
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07001898 pw.println(" disable");
1899 pw.println(" Completely disable device idle mode.");
1900 pw.println(" enable");
1901 pw.println(" Re-enable device idle mode after it had previously been disabled.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001902 pw.println(" enabled");
1903 pw.println(" Print 1 if device idle mode is currently enabled, else 0.");
Dianne Hackborn1b139682015-07-06 15:13:37 -07001904 pw.println(" whitelist");
1905 pw.println(" Print currently whitelisted apps.");
Dianne Hackborn92617032015-06-19 15:32:19 -07001906 pw.println(" whitelist [package ...]");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001907 pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001908 pw.println(" tempwhitelist [-u] [package ..]");
Dianne Hackborn92617032015-06-19 15:32:19 -07001909 pw.println(" Temporarily place packages in whitelist for 10 seconds.");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001910 }
1911
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001912 class Shell extends ShellCommand {
1913 int userId = UserHandle.USER_SYSTEM;
1914
1915 @Override
1916 public int onCommand(String cmd) {
1917 return onShellCommand(this, cmd);
1918 }
1919
1920 @Override
1921 public void onHelp() {
1922 PrintWriter pw = getOutPrintWriter();
1923 dumpHelp(pw);
1924 }
1925 }
1926
1927 int onShellCommand(Shell shell, String cmd) {
1928 PrintWriter pw = shell.getOutPrintWriter();
1929 if ("step".equals(cmd)) {
1930 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1931 null);
1932 synchronized (this) {
1933 long token = Binder.clearCallingIdentity();
1934 try {
1935 exitForceIdleLocked();
1936 stepIdleStateLocked();
Dianne Hackborn08c47a52015-10-15 12:38:14 -07001937 pw.print("Stepped to: ");
1938 pw.println(stateToString(mState));
1939 } finally {
1940 Binder.restoreCallingIdentity(token);
1941 }
1942 }
1943 } else if ("light-step".equals(cmd)) {
1944 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1945 null);
1946 synchronized (this) {
1947 long token = Binder.clearCallingIdentity();
1948 try {
1949 exitForceIdleLocked();
1950 stepLightIdleStateLocked();
1951 pw.print("Stepped to: "); pw.println(lightStateToString(mLightState));
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07001952 } finally {
1953 Binder.restoreCallingIdentity(token);
1954 }
1955 }
1956 } else if ("force-idle".equals(cmd)) {
1957 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1958 null);
1959 synchronized (this) {
1960 long token = Binder.clearCallingIdentity();
1961 try {
1962 if (!mEnabled) {
1963 pw.println("Unable to go idle; not enabled");
1964 return -1;
1965 }
1966 mForceIdle = true;
1967 becomeInactiveIfAppropriateLocked();
1968 int curState = mState;
1969 while (curState != STATE_IDLE) {
1970 stepIdleStateLocked();
1971 if (curState == mState) {
1972 pw.print("Unable to go idle; stopped at ");
1973 pw.println(stateToString(mState));
1974 exitForceIdleLocked();
1975 return -1;
1976 }
1977 curState = mState;
1978 }
1979 pw.println("Now forced in to idle mode");
1980 } finally {
1981 Binder.restoreCallingIdentity(token);
1982 }
1983 }
1984 } else if ("disable".equals(cmd)) {
1985 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1986 null);
1987 synchronized (this) {
1988 long token = Binder.clearCallingIdentity();
1989 try {
1990 if (mEnabled) {
1991 mEnabled = false;
1992 becomeActiveLocked("disabled", Process.myUid());
1993 pw.println("Idle mode disabled");
1994 }
1995 } finally {
1996 Binder.restoreCallingIdentity(token);
1997 }
1998 }
1999 } else if ("enable".equals(cmd)) {
2000 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2001 null);
2002 synchronized (this) {
2003 long token = Binder.clearCallingIdentity();
2004 try {
2005 exitForceIdleLocked();
2006 if (!mEnabled) {
2007 mEnabled = true;
2008 becomeInactiveIfAppropriateLocked();
2009 pw.println("Idle mode enabled");
2010 }
2011 } finally {
2012 Binder.restoreCallingIdentity(token);
2013 }
2014 }
2015 } else if ("enabled".equals(cmd)) {
2016 synchronized (this) {
2017 pw.println(mEnabled ? "1" : " 0");
2018 }
2019 } else if ("whitelist".equals(cmd)) {
2020 long token = Binder.clearCallingIdentity();
2021 try {
2022 String arg = shell.getNextArg();
2023 if (arg != null) {
2024 getContext().enforceCallingOrSelfPermission(
2025 android.Manifest.permission.DEVICE_POWER, null);
2026 do {
2027 if (arg.length() < 1 || (arg.charAt(0) != '-'
2028 && arg.charAt(0) != '+')) {
2029 pw.println("Package must be prefixed with + or -: " + arg);
2030 return -1;
2031 }
2032 char op = arg.charAt(0);
2033 String pkg = arg.substring(1);
2034 if (op == '+') {
2035 if (addPowerSaveWhitelistAppInternal(pkg)) {
2036 pw.println("Added: " + pkg);
2037 } else {
2038 pw.println("Unknown package: " + pkg);
2039 }
2040 } else {
2041 if (removePowerSaveWhitelistAppInternal(pkg)) {
2042 pw.println("Removed: " + pkg);
2043 }
2044 }
2045 } while ((arg=shell.getNextArg()) != null);
2046 } else {
2047 synchronized (this) {
2048 for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
2049 pw.print("system-excidle,");
2050 pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
2051 pw.print(",");
2052 pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
2053 }
2054 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
2055 pw.print("system,");
2056 pw.print(mPowerSaveWhitelistApps.keyAt(j));
2057 pw.print(",");
2058 pw.println(mPowerSaveWhitelistApps.valueAt(j));
2059 }
2060 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
2061 pw.print("user,");
2062 pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
2063 pw.print(",");
2064 pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
2065 }
2066 }
2067 }
2068 } finally {
2069 Binder.restoreCallingIdentity(token);
2070 }
2071 } else if ("tempwhitelist".equals(cmd)) {
2072 String opt;
2073 while ((opt=shell.getNextOption()) != null) {
2074 if ("-u".equals(opt)) {
2075 opt = shell.getNextArg();
2076 if (opt == null) {
2077 pw.println("-u requires a user number");
2078 return -1;
2079 }
2080 shell.userId = Integer.parseInt(opt);
2081 }
2082 }
2083 String arg = shell.getNextArg();
2084 if (arg != null) {
2085 try {
2086 addPowerSaveTempWhitelistAppChecked(arg, 10000L, shell.userId, "shell");
2087 } catch (RemoteException re) {
2088 pw.println("Failed: " + re);
2089 }
2090 } else {
2091 pw.println("At least one package name must be specified");
2092 return -1;
2093 }
2094 } else {
2095 return shell.handleDefaultCommands(cmd);
2096 }
2097 return 0;
2098 }
2099
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002100 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2101 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
2102 != PackageManager.PERMISSION_GRANTED) {
2103 pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
2104 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2105 + " without permission " + android.Manifest.permission.DUMP);
2106 return;
2107 }
2108
2109 if (args != null) {
Xiaohui Chen7c696362015-09-16 09:56:14 -07002110 int userId = UserHandle.USER_SYSTEM;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002111 for (int i=0; i<args.length; i++) {
2112 String arg = args[i];
2113 if ("-h".equals(arg)) {
2114 dumpHelp(pw);
2115 return;
Amith Yamasaniaf575b92015-05-29 15:35:26 -07002116 } else if ("-u".equals(arg)) {
2117 i++;
2118 if (i < args.length) {
2119 arg = args[i];
2120 userId = Integer.parseInt(arg);
2121 }
Dianne Hackborn8d66b3f2015-05-08 17:21:48 -07002122 } else if ("-a".equals(arg)) {
2123 // Ignore, we always dump all.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002124 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
2125 pw.println("Unknown option: " + arg);
2126 return;
2127 } else {
Dianne Hackborn9461b6f2015-10-07 17:33:16 -07002128 Shell shell = new Shell();
2129 shell.userId = userId;
2130 String[] newArgs = new String[args.length-i];
2131 System.arraycopy(args, i, newArgs, 0, args.length-i);
2132 shell.exec(mBinderService, null, fd, null, newArgs, new ResultReceiver(null));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002133 return;
2134 }
2135 }
2136 }
2137
2138 synchronized (this) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002139 mConstants.dump(pw);
2140
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002141 int size = mPowerSaveWhitelistAppsExceptIdle.size();
2142 if (size > 0) {
2143 pw.println(" Whitelist (except idle) system apps:");
2144 for (int i = 0; i < size; i++) {
2145 pw.print(" ");
2146 pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
2147 }
2148 }
2149 size = mPowerSaveWhitelistApps.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002150 if (size > 0) {
2151 pw.println(" Whitelist system apps:");
2152 for (int i = 0; i < size; i++) {
2153 pw.print(" ");
2154 pw.println(mPowerSaveWhitelistApps.keyAt(i));
2155 }
2156 }
2157 size = mPowerSaveWhitelistUserApps.size();
2158 if (size > 0) {
2159 pw.println(" Whitelist user apps:");
2160 for (int i = 0; i < size; i++) {
2161 pw.print(" ");
2162 pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
2163 }
2164 }
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002165 size = mPowerSaveWhitelistExceptIdleAppIds.size();
2166 if (size > 0) {
2167 pw.println(" Whitelist (except idle) all app ids:");
2168 for (int i = 0; i < size; i++) {
2169 pw.print(" ");
2170 pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
2171 pw.println();
2172 }
2173 }
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002174 size = mPowerSaveWhitelistAllAppIds.size();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002175 if (size > 0) {
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002176 pw.println(" Whitelist all app ids:");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002177 for (int i = 0; i < size; i++) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002178 pw.print(" ");
Dianne Hackborn3b16cf42015-07-01 15:05:04 -07002179 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002180 pw.println();
2181 }
2182 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002183 size = mTempWhitelistAppIdEndTimes.size();
2184 if (size > 0) {
2185 pw.println(" Temp whitelist schedule:");
2186 final long timeNow = SystemClock.elapsedRealtime();
2187 for (int i = 0; i < size; i++) {
2188 pw.print(" UID=");
2189 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
2190 pw.print(": ");
Dianne Hackbornfd854ee2015-07-13 18:00:37 -07002191 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
2192 TimeUtils.formatDuration(entry.first.value, timeNow, pw);
2193 pw.print(" - ");
2194 pw.println(entry.second);
Dianne Hackborna750a632015-06-16 17:18:23 -07002195 }
2196 }
2197 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
2198 if (size > 0) {
2199 pw.println(" Temp whitelist app ids:");
2200 for (int i = 0; i < size; i++) {
2201 pw.print(" ");
2202 pw.print(mTempWhitelistAppIdArray[i]);
2203 pw.println();
2204 }
2205 }
Adam Lesinski31c05d12015-06-09 17:34:04 -07002206
Dianne Hackborn92617032015-06-19 15:32:19 -07002207 pw.print(" mEnabled="); pw.println(mEnabled);
Dianne Hackborn4a503b12015-08-06 22:19:06 -07002208 pw.print(" mForceIdle="); pw.println(mForceIdle);
Nick Vaccaro20feaea2015-09-17 17:22:44 -07002209 pw.print(" mMotionSensor="); pw.println(mMotionSensor);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002210 pw.print(" mCurDisplay="); pw.println(mCurDisplay);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002211 pw.print(" mScreenOn="); pw.println(mScreenOn);
2212 pw.print(" mCharging="); pw.println(mCharging);
Nick Vaccaro20feaea2015-09-17 17:22:44 -07002213 pw.print(" mMotionActive="); pw.println(mMotionListener.active);
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002214 pw.print(" mNotMoving="); pw.println(mNotMoving);
Joe LaPenna23d681b2015-08-27 15:12:11 -07002215 pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
2216 pw.print(mHasGps); pw.print(" mHasNetwork=");
2217 pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
Dianne Hackborn42df4fb2015-08-14 16:43:14 -07002218 if (mLastGenericLocation != null) {
2219 pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation);
2220 }
2221 if (mLastGpsLocation != null) {
2222 pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation);
2223 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002224 pw.print(" mState="); pw.print(stateToString(mState));
2225 pw.print(" mLightState=");
2226 pw.println(lightStateToString(mLightState));
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002227 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
2228 pw.println();
2229 if (mNextAlarmTime != 0) {
2230 pw.print(" mNextAlarmTime=");
2231 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
2232 pw.println();
2233 }
2234 if (mNextIdlePendingDelay != 0) {
2235 pw.print(" mNextIdlePendingDelay=");
2236 TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
2237 pw.println();
2238 }
2239 if (mNextIdleDelay != 0) {
2240 pw.print(" mNextIdleDelay=");
2241 TimeUtils.formatDuration(mNextIdleDelay, pw);
2242 pw.println();
2243 }
Dianne Hackborn08c47a52015-10-15 12:38:14 -07002244 if (mNextLightAlarmTime != 0) {
2245 pw.print(" mNextLightAlarmTime=");
2246 TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
2247 pw.println();
2248 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002249 }
2250 }
2251}