• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
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  
17  package com.android.server;
18  
19  import android.Manifest;
20  import android.app.ActivityManagerNative;
21  import android.app.AlarmManager;
22  import android.content.BroadcastReceiver;
23  import android.content.ContentResolver;
24  import android.content.Context;
25  import android.content.Intent;
26  import android.content.IntentFilter;
27  import android.content.pm.ApplicationInfo;
28  import android.content.pm.PackageManager;
29  import android.content.pm.PackageManager.NameNotFoundException;
30  import android.database.ContentObserver;
31  import android.hardware.Sensor;
32  import android.hardware.SensorManager;
33  import android.hardware.SensorEvent;
34  import android.hardware.SensorEventListener;
35  import android.hardware.TriggerEvent;
36  import android.hardware.TriggerEventListener;
37  import android.hardware.display.DisplayManager;
38  import android.location.LocationRequest;
39  import android.location.Location;
40  import android.location.LocationListener;
41  import android.location.LocationManager;
42  import android.net.ConnectivityManager;
43  import android.net.INetworkPolicyManager;
44  import android.net.NetworkInfo;
45  import android.net.Uri;
46  import android.os.BatteryStats;
47  import android.os.Binder;
48  import android.os.Bundle;
49  import android.os.Environment;
50  import android.os.FileUtils;
51  import android.os.Handler;
52  import android.os.IBinder;
53  import android.os.IDeviceIdleController;
54  import android.os.IMaintenanceActivityListener;
55  import android.os.Looper;
56  import android.os.Message;
57  import android.os.PowerManager;
58  import android.os.PowerManagerInternal;
59  import android.os.Process;
60  import android.os.RemoteCallbackList;
61  import android.os.RemoteException;
62  import android.os.ResultReceiver;
63  import android.os.ServiceManager;
64  import android.os.ShellCommand;
65  import android.os.SystemClock;
66  import android.os.UserHandle;
67  import android.provider.Settings;
68  import android.util.ArrayMap;
69  import android.util.ArraySet;
70  import android.util.KeyValueListParser;
71  import android.util.MutableLong;
72  import android.util.Pair;
73  import android.util.Slog;
74  import android.util.SparseArray;
75  import android.util.SparseBooleanArray;
76  import android.util.TimeUtils;
77  import android.util.Xml;
78  import android.view.Display;
79  
80  import com.android.internal.app.IBatteryStats;
81  import com.android.internal.os.AtomicFile;
82  import com.android.internal.os.BackgroundThread;
83  import com.android.internal.util.FastXmlSerializer;
84  import com.android.internal.util.XmlUtils;
85  import com.android.server.am.BatteryStatsService;
86  
87  import org.xmlpull.v1.XmlPullParser;
88  import org.xmlpull.v1.XmlPullParserException;
89  import org.xmlpull.v1.XmlSerializer;
90  
91  import java.io.ByteArrayOutputStream;
92  import java.io.File;
93  import java.io.FileDescriptor;
94  import java.io.FileInputStream;
95  import java.io.FileNotFoundException;
96  import java.io.FileOutputStream;
97  import java.io.IOException;
98  import java.io.PrintWriter;
99  import java.nio.charset.StandardCharsets;
100  import java.util.Arrays;
101  
102  /**
103   * Keeps track of device idleness and drives low power mode based on that.
104   */
105  public class DeviceIdleController extends SystemService
106          implements AnyMotionDetector.DeviceIdleCallback {
107      private static final String TAG = "DeviceIdleController";
108  
109      private static final boolean DEBUG = false;
110  
111      private static final boolean COMPRESS_TIME = false;
112  
113      private static final int EVENT_BUFFER_SIZE = 100;
114  
115      private AlarmManager mAlarmManager;
116      private IBatteryStats mBatteryStats;
117      private PowerManagerInternal mLocalPowerManager;
118      private PowerManager mPowerManager;
119      private ConnectivityService mConnectivityService;
120      private AlarmManagerService.LocalService mLocalAlarmManager;
121      private INetworkPolicyManager mNetworkPolicyManager;
122      private DisplayManager mDisplayManager;
123      private SensorManager mSensorManager;
124      private Sensor mMotionSensor;
125      private LocationManager mLocationManager;
126      private LocationRequest mLocationRequest;
127      private Intent mIdleIntent;
128      private Intent mLightIdleIntent;
129      private Display mCurDisplay;
130      private AnyMotionDetector mAnyMotionDetector;
131      private boolean mLightEnabled;
132      private boolean mDeepEnabled;
133      private boolean mForceIdle;
134      private boolean mNetworkConnected;
135      private boolean mScreenOn;
136      private boolean mCharging;
137      private boolean mNotMoving;
138      private boolean mLocating;
139      private boolean mLocated;
140      private boolean mHasGps;
141      private boolean mHasNetworkLocation;
142      private Location mLastGenericLocation;
143      private Location mLastGpsLocation;
144  
145      /** Device is currently active. */
146      private static final int STATE_ACTIVE = 0;
147      /** Device is inactive (screen off, no motion) and we are waiting to for idle. */
148      private static final int STATE_INACTIVE = 1;
149      /** Device is past the initial inactive period, and waiting for the next idle period. */
150      private static final int STATE_IDLE_PENDING = 2;
151      /** Device is currently sensing motion. */
152      private static final int STATE_SENSING = 3;
153      /** Device is currently finding location (and may still be sensing). */
154      private static final int STATE_LOCATING = 4;
155      /** Device is in the idle state, trying to stay asleep as much as possible. */
156      private static final int STATE_IDLE = 5;
157      /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
158      private static final int STATE_IDLE_MAINTENANCE = 6;
stateToString(int state)159      private static String stateToString(int state) {
160          switch (state) {
161              case STATE_ACTIVE: return "ACTIVE";
162              case STATE_INACTIVE: return "INACTIVE";
163              case STATE_IDLE_PENDING: return "IDLE_PENDING";
164              case STATE_SENSING: return "SENSING";
165              case STATE_LOCATING: return "LOCATING";
166              case STATE_IDLE: return "IDLE";
167              case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
168              default: return Integer.toString(state);
169          }
170      }
171  
172      /** Device is currently active. */
173      private static final int LIGHT_STATE_ACTIVE = 0;
174      /** Device is inactive (screen off) and we are waiting to for the first light idle. */
175      private static final int LIGHT_STATE_INACTIVE = 1;
176      /** Device is about to go idle for the first time, wait for current work to complete. */
177      private static final int LIGHT_STATE_PRE_IDLE = 3;
178      /** Device is in the light idle state, trying to stay asleep as much as possible. */
179      private static final int LIGHT_STATE_IDLE = 4;
180      /** Device is in the light idle state, we want to go in to idle maintenance but are
181       * waiting for network connectivity before doing so. */
182      private static final int LIGHT_STATE_WAITING_FOR_NETWORK = 5;
183      /** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
184      private static final int LIGHT_STATE_IDLE_MAINTENANCE = 6;
185      /** Device light idle state is overriden, now applying deep doze state. */
186      private static final int LIGHT_STATE_OVERRIDE = 7;
lightStateToString(int state)187      private static String lightStateToString(int state) {
188          switch (state) {
189              case LIGHT_STATE_ACTIVE: return "ACTIVE";
190              case LIGHT_STATE_INACTIVE: return "INACTIVE";
191              case LIGHT_STATE_PRE_IDLE: return "PRE_IDLE";
192              case LIGHT_STATE_IDLE: return "IDLE";
193              case LIGHT_STATE_WAITING_FOR_NETWORK: return "WAITING_FOR_NETWORK";
194              case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
195              case LIGHT_STATE_OVERRIDE: return "OVERRIDE";
196              default: return Integer.toString(state);
197          }
198      }
199  
200      private int mState;
201      private int mLightState;
202  
203      private long mInactiveTimeout;
204      private long mNextAlarmTime;
205      private long mNextIdlePendingDelay;
206      private long mNextIdleDelay;
207      private long mNextLightIdleDelay;
208      private long mNextLightAlarmTime;
209      private long mNextSensingTimeoutAlarmTime;
210      private long mCurIdleBudget;
211      private long mMaintenanceStartTime;
212  
213      private int mActiveIdleOpCount;
214      private PowerManager.WakeLock mActiveIdleWakeLock; // held when there are operations in progress
215      private PowerManager.WakeLock mGoingIdleWakeLock;  // held when we are going idle so hardware
216                                                         // (especially NetworkPolicyManager) can shut
217                                                         // down.
218      private boolean mJobsActive;
219      private boolean mAlarmsActive;
220      private boolean mReportedMaintenanceActivity;
221  
222      public final AtomicFile mConfigFile;
223  
224      private final RemoteCallbackList<IMaintenanceActivityListener> mMaintenanceActivityListeners =
225              new RemoteCallbackList<IMaintenanceActivityListener>();
226  
227      /**
228       * Package names the system has white-listed to opt out of power save restrictions,
229       * except for device idle mode.
230       */
231      private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
232  
233      /**
234       * Package names the system has white-listed to opt out of power save restrictions for
235       * all modes.
236       */
237      private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
238  
239      /**
240       * Package names the user has white-listed to opt out of power save restrictions.
241       */
242      private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
243  
244      /**
245       * App IDs of built-in system apps that have been white-listed except for idle modes.
246       */
247      private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
248              = new SparseBooleanArray();
249  
250      /**
251       * App IDs of built-in system apps that have been white-listed.
252       */
253      private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
254  
255      /**
256       * App IDs that have been white-listed to opt out of power save restrictions, except
257       * for device idle modes.
258       */
259      private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
260  
261      /**
262       * Current app IDs that are in the complete power save white list, but shouldn't be
263       * excluded from idle modes.  This array can be shared with others because it will not be
264       * modified once set.
265       */
266      private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
267  
268      /**
269       * App IDs that have been white-listed to opt out of power save restrictions.
270       */
271      private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
272  
273      /**
274       * Current app IDs that are in the complete power save white list.  This array can
275       * be shared with others because it will not be modified once set.
276       */
277      private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
278  
279      /**
280       * App IDs that have been white-listed by the user to opt out of power save restrictions.
281       */
282      private final SparseBooleanArray mPowerSaveWhitelistUserAppIds = new SparseBooleanArray();
283  
284      /**
285       * Current app IDs that are in the user power save white list.  This array can
286       * be shared with others because it will not be modified once set.
287       */
288      private int[] mPowerSaveWhitelistUserAppIdArray = new int[0];
289  
290      /**
291       * List of end times for UIDs that are temporarily marked as being allowed to access
292       * the network and acquire wakelocks. Times are in milliseconds.
293       */
294      private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
295              = new SparseArray<>();
296  
297      /**
298       * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
299       */
300      Runnable mNetworkPolicyTempWhitelistCallback;
301  
302      /**
303       * Current app IDs of temporarily whitelist apps for high-priority messages.
304       */
305      private int[] mTempWhitelistAppIdArray = new int[0];
306  
307      private static final int EVENT_NULL = 0;
308      private static final int EVENT_NORMAL = 1;
309      private static final int EVENT_LIGHT_IDLE = 2;
310      private static final int EVENT_LIGHT_MAINTENANCE = 3;
311      private static final int EVENT_DEEP_IDLE = 4;
312      private static final int EVENT_DEEP_MAINTENANCE = 5;
313  
314      private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
315      private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
316  
addEvent(int cmd)317      private void addEvent(int cmd) {
318          if (mEventCmds[0] != cmd) {
319              System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1);
320              System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1);
321              mEventCmds[0] = cmd;
322              mEventTimes[0] = SystemClock.elapsedRealtime();
323          }
324      }
325  
326      private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
327          @Override public void onReceive(Context context, Intent intent) {
328              switch (intent.getAction()) {
329                  case ConnectivityManager.CONNECTIVITY_ACTION: {
330                      updateConnectivityState(intent);
331                  } break;
332                  case Intent.ACTION_BATTERY_CHANGED: {
333                      synchronized (DeviceIdleController.this) {
334                          int plugged = intent.getIntExtra("plugged", 0);
335                          updateChargingLocked(plugged != 0);
336                      }
337                  } break;
338                  case Intent.ACTION_PACKAGE_REMOVED: {
339                      if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
340                          Uri data = intent.getData();
341                          String ssp;
342                          if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
343                              removePowerSaveWhitelistAppInternal(ssp);
344                          }
345                      }
346                  } break;
347              }
348          }
349      };
350  
351      private final AlarmManager.OnAlarmListener mLightAlarmListener
352              = new AlarmManager.OnAlarmListener() {
353          @Override
354          public void onAlarm() {
355              synchronized (DeviceIdleController.this) {
356                  stepLightIdleStateLocked("s:alarm");
357              }
358          }
359      };
360  
361      private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener
362              = new AlarmManager.OnAlarmListener() {
363          @Override
364          public void onAlarm() {
365              if (mState == STATE_SENSING) {
366                  synchronized (DeviceIdleController.this) {
367                      becomeInactiveIfAppropriateLocked();
368                  }
369              }
370          }
371      };
372  
373      private final AlarmManager.OnAlarmListener mDeepAlarmListener
374              = new AlarmManager.OnAlarmListener() {
375          @Override
376          public void onAlarm() {
377              synchronized (DeviceIdleController.this) {
378                  stepIdleStateLocked("s:alarm");
379              }
380          }
381      };
382  
383      private final BroadcastReceiver mIdleStartedDoneReceiver = new BroadcastReceiver() {
384          @Override public void onReceive(Context context, Intent intent) {
385              // When coming out of a deep idle, we will add in some delay before we allow
386              // the system to settle down and finish the maintenance window.  This is
387              // to give a chance for any pending work to be scheduled.
388              if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
389                  mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP,
390                          mConstants.MIN_DEEP_MAINTENANCE_TIME);
391              } else {
392                  mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP,
393                          mConstants.MIN_LIGHT_MAINTENANCE_TIME);
394              }
395          }
396      };
397  
398      private final DisplayManager.DisplayListener mDisplayListener
399              = new DisplayManager.DisplayListener() {
400          @Override public void onDisplayAdded(int displayId) {
401          }
402  
403          @Override public void onDisplayRemoved(int displayId) {
404          }
405  
406          @Override public void onDisplayChanged(int displayId) {
407              if (displayId == Display.DEFAULT_DISPLAY) {
408                  synchronized (DeviceIdleController.this) {
409                      updateDisplayLocked();
410                  }
411              }
412          }
413      };
414  
415      private final class MotionListener extends TriggerEventListener
416              implements SensorEventListener {
417  
418          boolean active = false;
419  
420          @Override
onTrigger(TriggerEvent event)421          public void onTrigger(TriggerEvent event) {
422              synchronized (DeviceIdleController.this) {
423                  active = false;
424                  motionLocked();
425              }
426          }
427  
428          @Override
onSensorChanged(SensorEvent event)429          public void onSensorChanged(SensorEvent event) {
430              synchronized (DeviceIdleController.this) {
431                  mSensorManager.unregisterListener(this, mMotionSensor);
432                  active = false;
433                  motionLocked();
434              }
435          }
436  
437          @Override
onAccuracyChanged(Sensor sensor, int accuracy)438          public void onAccuracyChanged(Sensor sensor, int accuracy) {}
439  
registerLocked()440          public boolean registerLocked() {
441              boolean success;
442              if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
443                  success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
444              } else {
445                  success = mSensorManager.registerListener(
446                          mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL);
447              }
448              if (success) {
449                  active = true;
450              } else {
451                  Slog.e(TAG, "Unable to register for " + mMotionSensor);
452              }
453              return success;
454          }
455  
unregisterLocked()456          public void unregisterLocked() {
457              if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
458                  mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor);
459              } else {
460                  mSensorManager.unregisterListener(mMotionListener);
461              }
462              active = false;
463          }
464      }
465      private final MotionListener mMotionListener = new MotionListener();
466  
467      private final LocationListener mGenericLocationListener = new LocationListener() {
468          @Override
469          public void onLocationChanged(Location location) {
470              synchronized (DeviceIdleController.this) {
471                  receivedGenericLocationLocked(location);
472              }
473          }
474  
475          @Override
476          public void onStatusChanged(String provider, int status, Bundle extras) {
477          }
478  
479          @Override
480          public void onProviderEnabled(String provider) {
481          }
482  
483          @Override
484          public void onProviderDisabled(String provider) {
485          }
486      };
487  
488      private final LocationListener mGpsLocationListener = new LocationListener() {
489          @Override
490          public void onLocationChanged(Location location) {
491              synchronized (DeviceIdleController.this) {
492                  receivedGpsLocationLocked(location);
493              }
494          }
495  
496          @Override
497          public void onStatusChanged(String provider, int status, Bundle extras) {
498          }
499  
500          @Override
501          public void onProviderEnabled(String provider) {
502          }
503  
504          @Override
505          public void onProviderDisabled(String provider) {
506          }
507      };
508  
509      /**
510       * All times are in milliseconds. These constants are kept synchronized with the system
511       * global Settings. Any access to this class or its fields should be done while
512       * holding the DeviceIdleController lock.
513       */
514      private final class Constants extends ContentObserver {
515          // Key names stored in the settings value.
516          private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
517                  = "light_after_inactive_to";
518          private static final String KEY_LIGHT_PRE_IDLE_TIMEOUT = "light_pre_idle_to";
519          private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
520          private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
521          private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
522          private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
523                  = "light_idle_maintenance_min_budget";
524          private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
525                  = "light_idle_maintenance_max_budget";
526          private static final String KEY_MIN_LIGHT_MAINTENANCE_TIME = "min_light_maintenance_time";
527          private static final String KEY_MIN_DEEP_MAINTENANCE_TIME = "min_deep_maintenance_time";
528          private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
529          private static final String KEY_SENSING_TIMEOUT = "sensing_to";
530          private static final String KEY_LOCATING_TIMEOUT = "locating_to";
531          private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
532          private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
533          private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
534          private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
535          private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
536          private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
537          private static final String KEY_IDLE_TIMEOUT = "idle_to";
538          private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
539          private static final String KEY_IDLE_FACTOR = "idle_factor";
540          private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
541          private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
542                  "max_temp_app_whitelist_duration";
543          private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
544                  "mms_temp_app_whitelist_duration";
545          private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
546                  "sms_temp_app_whitelist_duration";
547          private static final String KEY_NOTIFICATION_WHITELIST_DURATION =
548                  "notification_whitelist_duration";
549  
550          /**
551           * This is the time, after becoming inactive, that we go in to the first
552           * light-weight idle mode.
553           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
554           * @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
555           */
556          public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
557  
558          /**
559           * This is amount of time we will wait from the point where we decide we would
560           * like to go idle until we actually do, while waiting for jobs and other current
561           * activity to finish.
562           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
563           * @see #KEY_LIGHT_PRE_IDLE_TIMEOUT
564           */
565          public long LIGHT_PRE_IDLE_TIMEOUT;
566  
567          /**
568           * This is the initial time that we will run in idle maintenance mode.
569           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
570           * @see #KEY_LIGHT_IDLE_TIMEOUT
571           */
572          public long LIGHT_IDLE_TIMEOUT;
573  
574          /**
575           * Scaling factor to apply to the light idle mode time each time we complete a cycle.
576           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
577           * @see #KEY_LIGHT_IDLE_FACTOR
578           */
579          public float LIGHT_IDLE_FACTOR;
580  
581          /**
582           * This is the maximum time we will run in idle maintenence mode.
583           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
584           * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
585           */
586          public long LIGHT_MAX_IDLE_TIMEOUT;
587  
588          /**
589           * This is the minimum amount of time we want to make available for maintenance mode
590           * when lightly idling.  That is, we will always have at least this amount of time
591           * available maintenance before timing out and cutting off maintenance mode.
592           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
593           * @see #KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
594           */
595          public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
596  
597          /**
598           * This is the maximum amount of time we want to make available for maintenance mode
599           * when lightly idling.  That is, if the system isn't using up its minimum maintenance
600           * budget and this time is being added to the budget reserve, this is the maximum
601           * reserve size we will allow to grow and thus the maximum amount of time we will
602           * allow for the maintenance window.
603           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
604           * @see #KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
605           */
606          public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
607  
608          /**
609           * This is the minimum amount of time that we will stay in maintenance mode after
610           * a light doze.  We have this minimum to allow various things to respond to switching
611           * in to maintenance mode and scheduling their work -- otherwise we may
612           * see there is nothing to do (no jobs pending) and go out of maintenance
613           * mode immediately.
614           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
615           * @see #KEY_MIN_LIGHT_MAINTENANCE_TIME
616           */
617          public long MIN_LIGHT_MAINTENANCE_TIME;
618  
619          /**
620           * This is the minimum amount of time that we will stay in maintenance mode after
621           * a full doze.  We have this minimum to allow various things to respond to switching
622           * in to maintenance mode and scheduling their work -- otherwise we may
623           * see there is nothing to do (no jobs pending) and go out of maintenance
624           * mode immediately.
625           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
626           * @see #KEY_MIN_DEEP_MAINTENANCE_TIME
627           */
628          public long MIN_DEEP_MAINTENANCE_TIME;
629  
630          /**
631           * This is the time, after becoming inactive, at which we start looking at the
632           * motion sensor to determine if the device is being left alone.  We don't do this
633           * immediately after going inactive just because we don't want to be continually running
634           * the motion sensor whenever the screen is off.
635           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
636           * @see #KEY_INACTIVE_TIMEOUT
637           */
638          public long INACTIVE_TIMEOUT;
639  
640          /**
641           * If we don't receive a callback from AnyMotion in this amount of time +
642           * {@link #LOCATING_TIMEOUT}, we will change from
643           * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
644           * will be ignored.
645           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
646           * @see #KEY_SENSING_TIMEOUT
647           */
648          public long SENSING_TIMEOUT;
649  
650          /**
651           * This is how long we will wait to try to get a good location fix before going in to
652           * idle mode.
653           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
654           * @see #KEY_LOCATING_TIMEOUT
655           */
656          public long LOCATING_TIMEOUT;
657  
658          /**
659           * The desired maximum accuracy (in meters) we consider the location to be good enough to go
660           * on to idle.  We will be trying to get an accuracy fix at least this good or until
661           * {@link #LOCATING_TIMEOUT} expires.
662           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
663           * @see #KEY_LOCATION_ACCURACY
664           */
665          public float LOCATION_ACCURACY;
666  
667          /**
668           * This is the time, after seeing motion, that we wait after becoming inactive from
669           * that until we start looking for motion again.
670           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
671           * @see #KEY_MOTION_INACTIVE_TIMEOUT
672           */
673          public long MOTION_INACTIVE_TIMEOUT;
674  
675          /**
676           * This is the time, after the inactive timeout elapses, that we will wait looking
677           * for motion until we truly consider the device to be idle.
678           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
679           * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
680           */
681          public long IDLE_AFTER_INACTIVE_TIMEOUT;
682  
683          /**
684           * This is the initial time, after being idle, that we will allow ourself to be back
685           * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
686           * idle.
687           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
688           * @see #KEY_IDLE_PENDING_TIMEOUT
689           */
690          public long IDLE_PENDING_TIMEOUT;
691  
692          /**
693           * Maximum pending idle timeout (time spent running) we will be allowed to use.
694           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
695           * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
696           */
697          public long MAX_IDLE_PENDING_TIMEOUT;
698  
699          /**
700           * Scaling factor to apply to current pending idle timeout each time we cycle through
701           * that state.
702           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
703           * @see #KEY_IDLE_PENDING_FACTOR
704           */
705          public float IDLE_PENDING_FACTOR;
706  
707          /**
708           * This is the initial time that we want to sit in the idle state before waking up
709           * again to return to pending idle and allowing normal work to run.
710           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
711           * @see #KEY_IDLE_TIMEOUT
712           */
713          public long IDLE_TIMEOUT;
714  
715          /**
716           * Maximum idle duration we will be allowed to use.
717           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
718           * @see #KEY_MAX_IDLE_TIMEOUT
719           */
720          public long MAX_IDLE_TIMEOUT;
721  
722          /**
723           * Scaling factor to apply to current idle timeout each time we cycle through that state.
724            * @see Settings.Global#DEVICE_IDLE_CONSTANTS
725           * @see #KEY_IDLE_FACTOR
726           */
727          public float IDLE_FACTOR;
728  
729          /**
730           * This is the minimum time we will allow until the next upcoming alarm for us to
731           * actually go in to idle mode.
732           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
733           * @see #KEY_MIN_TIME_TO_ALARM
734           */
735          public long MIN_TIME_TO_ALARM;
736  
737          /**
738           * Max amount of time to temporarily whitelist an app when it receives a high priority
739           * tickle.
740           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
741           * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
742           */
743          public long MAX_TEMP_APP_WHITELIST_DURATION;
744  
745          /**
746           * Amount of time we would like to whitelist an app that is receiving an MMS.
747           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
748           * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
749           */
750          public long MMS_TEMP_APP_WHITELIST_DURATION;
751  
752          /**
753           * Amount of time we would like to whitelist an app that is receiving an SMS.
754           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
755           * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
756           */
757          public long SMS_TEMP_APP_WHITELIST_DURATION;
758  
759          /**
760           * Amount of time we would like to whitelist an app that is handling a
761           * {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}.
762           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
763           * @see #KEY_NOTIFICATION_WHITELIST_DURATION
764           */
765          public long NOTIFICATION_WHITELIST_DURATION;
766  
767          private final ContentResolver mResolver;
768          private final boolean mHasWatch;
769          private final KeyValueListParser mParser = new KeyValueListParser(',');
770  
Constants(Handler handler, ContentResolver resolver)771          public Constants(Handler handler, ContentResolver resolver) {
772              super(handler);
773              mResolver = resolver;
774              mHasWatch = getContext().getPackageManager().hasSystemFeature(
775                      PackageManager.FEATURE_WATCH);
776              mResolver.registerContentObserver(Settings.Global.getUriFor(
777                      mHasWatch ? Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH
778                                : Settings.Global.DEVICE_IDLE_CONSTANTS),
779                      false, this);
780              updateConstants();
781          }
782  
783          @Override
onChange(boolean selfChange, Uri uri)784          public void onChange(boolean selfChange, Uri uri) {
785              updateConstants();
786          }
787  
updateConstants()788          private void updateConstants() {
789              synchronized (DeviceIdleController.this) {
790                  try {
791                      mParser.setString(Settings.Global.getString(mResolver,
792                              mHasWatch ? Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH
793                                        : Settings.Global.DEVICE_IDLE_CONSTANTS));
794                  } catch (IllegalArgumentException e) {
795                      // Failed to parse the settings string, log this and move on
796                      // with defaults.
797                      Slog.e(TAG, "Bad device idle settings", e);
798                  }
799  
800                  LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(
801                          KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
802                          !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
803                  LIGHT_PRE_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_PRE_IDLE_TIMEOUT,
804                          !COMPRESS_TIME ? 10 * 60 * 1000L : 30 * 1000L);
805                  LIGHT_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_TIMEOUT,
806                          !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
807                  LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR,
808                          2f);
809                  LIGHT_MAX_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_MAX_IDLE_TIMEOUT,
810                          !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
811                  LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getLong(
812                          KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
813                          !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
814                  LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getLong(
815                          KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET,
816                          !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
817                  MIN_LIGHT_MAINTENANCE_TIME = mParser.getLong(
818                          KEY_MIN_LIGHT_MAINTENANCE_TIME,
819                          !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L);
820                  MIN_DEEP_MAINTENANCE_TIME = mParser.getLong(
821                          KEY_MIN_DEEP_MAINTENANCE_TIME,
822                          !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L);
823                  long inactiveTimeoutDefault = (mHasWatch ? 15 : 30) * 60 * 1000L;
824                  INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
825                          !COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10));
826                  SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
827                          !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
828                  LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
829                          !DEBUG ? 30 * 1000L : 15 * 1000L);
830                  LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
831                  MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
832                          !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
833                  long idleAfterInactiveTimeout = (mHasWatch ? 15 : 30) * 60 * 1000L;
834                  IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
835                          !COMPRESS_TIME ? idleAfterInactiveTimeout
836                                         : (idleAfterInactiveTimeout / 10));
837                  IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
838                          !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
839                  MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
840                          !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
841                  IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
842                          2f);
843                  IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
844                          !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
845                  MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
846                          !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
847                  IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
848                          2f);
849                  MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
850                          !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
851                  MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
852                          KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
853                  MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
854                          KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
855                  SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
856                          KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
857                  NOTIFICATION_WHITELIST_DURATION = mParser.getLong(
858                          KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L);
859              }
860          }
861  
dump(PrintWriter pw)862          void dump(PrintWriter pw) {
863              pw.println("  Settings:");
864  
865              pw.print("    "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
866              TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw);
867              pw.println();
868  
869              pw.print("    "); pw.print(KEY_LIGHT_PRE_IDLE_TIMEOUT); pw.print("=");
870              TimeUtils.formatDuration(LIGHT_PRE_IDLE_TIMEOUT, pw);
871              pw.println();
872  
873              pw.print("    "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
874              TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
875              pw.println();
876  
877              pw.print("    "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("=");
878              pw.print(LIGHT_IDLE_FACTOR);
879              pw.println();
880  
881              pw.print("    "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT); pw.print("=");
882              TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT, pw);
883              pw.println();
884  
885              pw.print("    "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); pw.print("=");
886              TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, pw);
887              pw.println();
888  
889              pw.print("    "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET); pw.print("=");
890              TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, pw);
891              pw.println();
892  
893              pw.print("    "); pw.print(KEY_MIN_LIGHT_MAINTENANCE_TIME); pw.print("=");
894              TimeUtils.formatDuration(MIN_LIGHT_MAINTENANCE_TIME, pw);
895              pw.println();
896  
897              pw.print("    "); pw.print(KEY_MIN_DEEP_MAINTENANCE_TIME); pw.print("=");
898              TimeUtils.formatDuration(MIN_DEEP_MAINTENANCE_TIME, pw);
899              pw.println();
900  
901              pw.print("    "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
902              TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
903              pw.println();
904  
905              pw.print("    "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
906              TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
907              pw.println();
908  
909              pw.print("    "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
910              TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
911              pw.println();
912  
913              pw.print("    "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
914              pw.print(LOCATION_ACCURACY); pw.print("m");
915              pw.println();
916  
917              pw.print("    "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
918              TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
919              pw.println();
920  
921              pw.print("    "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
922              TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
923              pw.println();
924  
925              pw.print("    "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
926              TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
927              pw.println();
928  
929              pw.print("    "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
930              TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
931              pw.println();
932  
933              pw.print("    "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
934              pw.println(IDLE_PENDING_FACTOR);
935  
936              pw.print("    "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
937              TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
938              pw.println();
939  
940              pw.print("    "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
941              TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
942              pw.println();
943  
944              pw.print("    "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
945              pw.println(IDLE_FACTOR);
946  
947              pw.print("    "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
948              TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
949              pw.println();
950  
951              pw.print("    "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
952              TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
953              pw.println();
954  
955              pw.print("    "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
956              TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
957              pw.println();
958  
959              pw.print("    "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
960              TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
961              pw.println();
962  
963              pw.print("    "); pw.print(KEY_NOTIFICATION_WHITELIST_DURATION); pw.print("=");
964              TimeUtils.formatDuration(NOTIFICATION_WHITELIST_DURATION, pw);
965              pw.println();
966          }
967      }
968  
969      private Constants mConstants;
970  
971      @Override
onAnyMotionResult(int result)972      public void onAnyMotionResult(int result) {
973          if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
974          if (result != AnyMotionDetector.RESULT_UNKNOWN) {
975              synchronized (this) {
976                  cancelSensingTimeoutAlarmLocked();
977              }
978          }
979          if ((result == AnyMotionDetector.RESULT_MOVED) ||
980              (result == AnyMotionDetector.RESULT_UNKNOWN)) {
981              synchronized (this) {
982                  handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
983              }
984          } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
985              if (mState == STATE_SENSING) {
986                  // If we are currently sensing, it is time to move to locating.
987                  synchronized (this) {
988                      mNotMoving = true;
989                      stepIdleStateLocked("s:stationary");
990                  }
991              } else if (mState == STATE_LOCATING) {
992                  // If we are currently locating, note that we are not moving and step
993                  // if we have located the position.
994                  synchronized (this) {
995                      mNotMoving = true;
996                      if (mLocated) {
997                          stepIdleStateLocked("s:stationary");
998                      }
999                  }
1000              }
1001          }
1002      }
1003  
1004      private static final int MSG_WRITE_CONFIG = 1;
1005      private static final int MSG_REPORT_IDLE_ON = 2;
1006      private static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
1007      private static final int MSG_REPORT_IDLE_OFF = 4;
1008      private static final int MSG_REPORT_ACTIVE = 5;
1009      private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
1010      private static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
1011      private static final int MSG_FINISH_IDLE_OP = 8;
1012  
1013      final class MyHandler extends Handler {
MyHandler(Looper looper)1014          MyHandler(Looper looper) {
1015              super(looper);
1016          }
1017  
handleMessage(Message msg)1018          @Override public void handleMessage(Message msg) {
1019              if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
1020              switch (msg.what) {
1021                  case MSG_WRITE_CONFIG: {
1022                      // Does not hold a wakelock. Just let this happen whenever.
1023                      handleWriteConfigFile();
1024                  } break;
1025                  case MSG_REPORT_IDLE_ON:
1026                  case MSG_REPORT_IDLE_ON_LIGHT: {
1027                      // mGoingIdleWakeLock is held at this point
1028                      EventLogTags.writeDeviceIdleOnStart();
1029                      final boolean deepChanged;
1030                      final boolean lightChanged;
1031                      if (msg.what == MSG_REPORT_IDLE_ON) {
1032                          deepChanged = mLocalPowerManager.setDeviceIdleMode(true);
1033                          lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1034                      } else {
1035                          deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1036                          lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
1037                      }
1038                      try {
1039                          mNetworkPolicyManager.setDeviceIdleMode(true);
1040                          mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON
1041                                  ? BatteryStats.DEVICE_IDLE_MODE_DEEP
1042                                  : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
1043                      } catch (RemoteException e) {
1044                      }
1045                      if (deepChanged) {
1046                          getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1047                      }
1048                      if (lightChanged) {
1049                          getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1050                      }
1051                      EventLogTags.writeDeviceIdleOnComplete();
1052                      mGoingIdleWakeLock.release();
1053                  } break;
1054                  case MSG_REPORT_IDLE_OFF: {
1055                      // mActiveIdleWakeLock is held at this point
1056                      EventLogTags.writeDeviceIdleOffStart("unknown");
1057                      final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1058                      final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1059                      try {
1060                          mNetworkPolicyManager.setDeviceIdleMode(false);
1061                          mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1062                                  null, Process.myUid());
1063                      } catch (RemoteException e) {
1064                      }
1065                      if (deepChanged) {
1066                          incActiveIdleOps();
1067                          getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL,
1068                                  null, mIdleStartedDoneReceiver, null, 0, null, null);
1069                      }
1070                      if (lightChanged) {
1071                          incActiveIdleOps();
1072                          getContext().sendOrderedBroadcastAsUser(mLightIdleIntent, UserHandle.ALL,
1073                                  null, mIdleStartedDoneReceiver, null, 0, null, null);
1074                      }
1075                      // Always start with one active op for the message being sent here.
1076                      // Now we are done!
1077                      decActiveIdleOps();
1078                      EventLogTags.writeDeviceIdleOffComplete();
1079                  } break;
1080                  case MSG_REPORT_ACTIVE: {
1081                      // The device is awake at this point, so no wakelock necessary.
1082                      String activeReason = (String)msg.obj;
1083                      int activeUid = msg.arg1;
1084                      EventLogTags.writeDeviceIdleOffStart(
1085                              activeReason != null ? activeReason : "unknown");
1086                      final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1087                      final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1088                      try {
1089                          mNetworkPolicyManager.setDeviceIdleMode(false);
1090                          mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1091                                  activeReason, activeUid);
1092                      } catch (RemoteException e) {
1093                      }
1094                      if (deepChanged) {
1095                          getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1096                      }
1097                      if (lightChanged) {
1098                          getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1099                      }
1100                      EventLogTags.writeDeviceIdleOffComplete();
1101                  } break;
1102                  case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
1103                      // TODO: What is keeping the device awake at this point? Does it need to be?
1104                      int uid = msg.arg1;
1105                      checkTempAppWhitelistTimeout(uid);
1106                  } break;
1107                  case MSG_REPORT_MAINTENANCE_ACTIVITY: {
1108                      // TODO: What is keeping the device awake at this point? Does it need to be?
1109                      boolean active = (msg.arg1 == 1);
1110                      final int size = mMaintenanceActivityListeners.beginBroadcast();
1111                      try {
1112                          for (int i = 0; i < size; i++) {
1113                              try {
1114                                  mMaintenanceActivityListeners.getBroadcastItem(i)
1115                                          .onMaintenanceActivityChanged(active);
1116                              } catch (RemoteException ignored) {
1117                              }
1118                          }
1119                      } finally {
1120                          mMaintenanceActivityListeners.finishBroadcast();
1121                      }
1122                  } break;
1123                  case MSG_FINISH_IDLE_OP: {
1124                      // mActiveIdleWakeLock is held at this point
1125                      decActiveIdleOps();
1126                  } break;
1127              }
1128          }
1129      }
1130  
1131      final MyHandler mHandler;
1132  
1133      BinderService mBinderService;
1134  
1135      private final class BinderService extends IDeviceIdleController.Stub {
addPowerSaveWhitelistApp(String name)1136          @Override public void addPowerSaveWhitelistApp(String name) {
1137              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1138                      null);
1139              long ident = Binder.clearCallingIdentity();
1140              try {
1141                  addPowerSaveWhitelistAppInternal(name);
1142              } finally {
1143                  Binder.restoreCallingIdentity(ident);
1144              }
1145          }
1146  
removePowerSaveWhitelistApp(String name)1147          @Override public void removePowerSaveWhitelistApp(String name) {
1148              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1149                      null);
1150              long ident = Binder.clearCallingIdentity();
1151              try {
1152                  removePowerSaveWhitelistAppInternal(name);
1153              } finally {
1154                  Binder.restoreCallingIdentity(ident);
1155              }
1156          }
1157  
getSystemPowerWhitelistExceptIdle()1158          @Override public String[] getSystemPowerWhitelistExceptIdle() {
1159              return getSystemPowerWhitelistExceptIdleInternal();
1160          }
1161  
getSystemPowerWhitelist()1162          @Override public String[] getSystemPowerWhitelist() {
1163              return getSystemPowerWhitelistInternal();
1164          }
1165  
getUserPowerWhitelist()1166          @Override public String[] getUserPowerWhitelist() {
1167              return getUserPowerWhitelistInternal();
1168          }
1169  
getFullPowerWhitelistExceptIdle()1170          @Override public String[] getFullPowerWhitelistExceptIdle() {
1171              return getFullPowerWhitelistExceptIdleInternal();
1172          }
1173  
getFullPowerWhitelist()1174          @Override public String[] getFullPowerWhitelist() {
1175              return getFullPowerWhitelistInternal();
1176          }
1177  
getAppIdWhitelistExceptIdle()1178          @Override public int[] getAppIdWhitelistExceptIdle() {
1179              return getAppIdWhitelistExceptIdleInternal();
1180          }
1181  
getAppIdWhitelist()1182          @Override public int[] getAppIdWhitelist() {
1183              return getAppIdWhitelistInternal();
1184          }
1185  
getAppIdUserWhitelist()1186          @Override public int[] getAppIdUserWhitelist() {
1187              return getAppIdUserWhitelistInternal();
1188          }
1189  
getAppIdTempWhitelist()1190          @Override public int[] getAppIdTempWhitelist() {
1191              return getAppIdTempWhitelistInternal();
1192          }
1193  
isPowerSaveWhitelistExceptIdleApp(String name)1194          @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
1195              return isPowerSaveWhitelistExceptIdleAppInternal(name);
1196          }
1197  
isPowerSaveWhitelistApp(String name)1198          @Override public boolean isPowerSaveWhitelistApp(String name) {
1199              return isPowerSaveWhitelistAppInternal(name);
1200          }
1201  
addPowerSaveTempWhitelistApp(String packageName, long duration, int userId, String reason)1202          @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
1203                  int userId, String reason) throws RemoteException {
1204              addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1205          }
1206  
addPowerSaveTempWhitelistAppForMms(String packageName, int userId, String reason)1207          @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
1208                  int userId, String reason) throws RemoteException {
1209              long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
1210              addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1211              return duration;
1212          }
1213  
addPowerSaveTempWhitelistAppForSms(String packageName, int userId, String reason)1214          @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
1215                  int userId, String reason) throws RemoteException {
1216              long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
1217              addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1218              return duration;
1219          }
1220  
exitIdle(String reason)1221          @Override public void exitIdle(String reason) {
1222              getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1223                      null);
1224              long ident = Binder.clearCallingIdentity();
1225              try {
1226                  exitIdleInternal(reason);
1227              } finally {
1228                  Binder.restoreCallingIdentity(ident);
1229              }
1230          }
1231  
registerMaintenanceActivityListener( IMaintenanceActivityListener listener)1232          @Override public boolean registerMaintenanceActivityListener(
1233                  IMaintenanceActivityListener listener) {
1234              return DeviceIdleController.this.registerMaintenanceActivityListener(listener);
1235          }
1236  
unregisterMaintenanceActivityListener( IMaintenanceActivityListener listener)1237          @Override public void unregisterMaintenanceActivityListener(
1238                  IMaintenanceActivityListener listener) {
1239              DeviceIdleController.this.unregisterMaintenanceActivityListener(listener);
1240          }
1241  
dump(FileDescriptor fd, PrintWriter pw, String[] args)1242          @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1243              DeviceIdleController.this.dump(fd, pw, args);
1244          }
1245  
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver)1246          @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
1247                  FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
1248              (new Shell()).exec(this, in, out, err, args, resultReceiver);
1249          }
1250      }
1251  
1252      public final class LocalService {
addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync, String reason)1253          public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
1254                  String reason) {
1255              addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
1256          }
1257  
getNotificationWhitelistDuration()1258          public long getNotificationWhitelistDuration() {
1259              return mConstants.NOTIFICATION_WHITELIST_DURATION;
1260          }
1261  
setNetworkPolicyTempWhitelistCallback(Runnable callback)1262          public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
1263              setNetworkPolicyTempWhitelistCallbackInternal(callback);
1264          }
1265  
setJobsActive(boolean active)1266          public void setJobsActive(boolean active) {
1267              DeviceIdleController.this.setJobsActive(active);
1268          }
1269  
1270          // Up-call from alarm manager.
setAlarmsActive(boolean active)1271          public void setAlarmsActive(boolean active) {
1272              DeviceIdleController.this.setAlarmsActive(active);
1273          }
1274  
1275          /**
1276           * Returns the array of app ids whitelisted by user. Take care not to
1277           * modify this, as it is a reference to the original copy. But the reference
1278           * can change when the list changes, so it needs to be re-acquired when
1279           * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent.
1280           */
getPowerSaveWhitelistUserAppIds()1281          public int[] getPowerSaveWhitelistUserAppIds() {
1282              return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
1283          }
1284      }
1285  
DeviceIdleController(Context context)1286      public DeviceIdleController(Context context) {
1287          super(context);
1288          mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
1289          mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
1290      }
1291  
getPowerSaveWhitelistUserAppIds()1292      int[] getPowerSaveWhitelistUserAppIds() {
1293          synchronized (this) {
1294              return mPowerSaveWhitelistUserAppIdArray;
1295          }
1296      }
1297  
getSystemDir()1298      private static File getSystemDir() {
1299          return new File(Environment.getDataDirectory(), "system");
1300      }
1301  
1302      @Override
onStart()1303      public void onStart() {
1304          final PackageManager pm = getContext().getPackageManager();
1305  
1306          synchronized (this) {
1307              mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean(
1308                      com.android.internal.R.bool.config_enableAutoPowerModes);
1309              SystemConfig sysConfig = SystemConfig.getInstance();
1310              ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
1311              for (int i=0; i<allowPowerExceptIdle.size(); i++) {
1312                  String pkg = allowPowerExceptIdle.valueAt(i);
1313                  try {
1314                      ApplicationInfo ai = pm.getApplicationInfo(pkg,
1315                              PackageManager.MATCH_SYSTEM_ONLY);
1316                      int appid = UserHandle.getAppId(ai.uid);
1317                      mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
1318                      mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
1319                  } catch (PackageManager.NameNotFoundException e) {
1320                  }
1321              }
1322              ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
1323              for (int i=0; i<allowPower.size(); i++) {
1324                  String pkg = allowPower.valueAt(i);
1325                  try {
1326                      ApplicationInfo ai = pm.getApplicationInfo(pkg,
1327                              PackageManager.MATCH_SYSTEM_ONLY);
1328                      int appid = UserHandle.getAppId(ai.uid);
1329                      // These apps are on both the whitelist-except-idle as well
1330                      // as the full whitelist, so they apply in all cases.
1331                      mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
1332                      mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
1333                      mPowerSaveWhitelistApps.put(ai.packageName, appid);
1334                      mPowerSaveWhitelistSystemAppIds.put(appid, true);
1335                  } catch (PackageManager.NameNotFoundException e) {
1336                  }
1337              }
1338  
1339              mConstants = new Constants(mHandler, getContext().getContentResolver());
1340  
1341              readConfigFileLocked();
1342              updateWhitelistAppIdsLocked();
1343  
1344              mNetworkConnected = true;
1345              mScreenOn = true;
1346              // Start out assuming we are charging.  If we aren't, we will at least get
1347              // a battery update the next time the level drops.
1348              mCharging = true;
1349              mState = STATE_ACTIVE;
1350              mLightState = LIGHT_STATE_ACTIVE;
1351              mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
1352          }
1353  
1354          mBinderService = new BinderService();
1355          publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);
1356          publishLocalService(LocalService.class, new LocalService());
1357      }
1358  
1359      @Override
onBootPhase(int phase)1360      public void onBootPhase(int phase) {
1361          if (phase == PHASE_SYSTEM_SERVICES_READY) {
1362              synchronized (this) {
1363                  mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
1364                  mBatteryStats = BatteryStatsService.getService();
1365                  mLocalPowerManager = getLocalService(PowerManagerInternal.class);
1366                  mPowerManager = getContext().getSystemService(PowerManager.class);
1367                  mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1368                          "deviceidle_maint");
1369                  mActiveIdleWakeLock.setReferenceCounted(false);
1370                  mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1371                          "deviceidle_going_idle");
1372                  mGoingIdleWakeLock.setReferenceCounted(true);
1373                  mConnectivityService = (ConnectivityService)ServiceManager.getService(
1374                          Context.CONNECTIVITY_SERVICE);
1375                  mLocalAlarmManager = getLocalService(AlarmManagerService.LocalService.class);
1376                  mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
1377                          ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
1378                  mDisplayManager = (DisplayManager) getContext().getSystemService(
1379                          Context.DISPLAY_SERVICE);
1380                  mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
1381                  int sigMotionSensorId = getContext().getResources().getInteger(
1382                          com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
1383                  if (sigMotionSensorId > 0) {
1384                      mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
1385                  }
1386                  if (mMotionSensor == null && getContext().getResources().getBoolean(
1387                          com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
1388                      mMotionSensor = mSensorManager.getDefaultSensor(
1389                              Sensor.TYPE_WRIST_TILT_GESTURE, true);
1390                  }
1391                  if (mMotionSensor == null) {
1392                      // As a last ditch, fall back to SMD.
1393                      mMotionSensor = mSensorManager.getDefaultSensor(
1394                              Sensor.TYPE_SIGNIFICANT_MOTION, true);
1395                  }
1396  
1397                  if (getContext().getResources().getBoolean(
1398                          com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
1399                      mLocationManager = (LocationManager) getContext().getSystemService(
1400                              Context.LOCATION_SERVICE);
1401                      mLocationRequest = new LocationRequest()
1402                          .setQuality(LocationRequest.ACCURACY_FINE)
1403                          .setInterval(0)
1404                          .setFastestInterval(0)
1405                          .setNumUpdates(1);
1406                  }
1407  
1408                  float angleThreshold = getContext().getResources().getInteger(
1409                          com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
1410                  mAnyMotionDetector = new AnyMotionDetector(
1411                          (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
1412                          mHandler, mSensorManager, this, angleThreshold);
1413  
1414                  mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
1415                  mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1416                          | Intent.FLAG_RECEIVER_FOREGROUND);
1417                  mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
1418                  mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1419                          | Intent.FLAG_RECEIVER_FOREGROUND);
1420  
1421                  IntentFilter filter = new IntentFilter();
1422                  filter.addAction(Intent.ACTION_BATTERY_CHANGED);
1423                  getContext().registerReceiver(mReceiver, filter);
1424  
1425                  filter = new IntentFilter();
1426                  filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
1427                  filter.addDataScheme("package");
1428                  getContext().registerReceiver(mReceiver, filter);
1429  
1430                  filter = new IntentFilter();
1431                  filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
1432                  getContext().registerReceiver(mReceiver, filter);
1433  
1434                  mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
1435                  mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
1436                  mDisplayManager.registerDisplayListener(mDisplayListener, null);
1437                  updateDisplayLocked();
1438              }
1439              updateConnectivityState(null);
1440          }
1441      }
1442  
addPowerSaveWhitelistAppInternal(String name)1443      public boolean addPowerSaveWhitelistAppInternal(String name) {
1444          synchronized (this) {
1445              try {
1446                  ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
1447                          PackageManager.MATCH_UNINSTALLED_PACKAGES);
1448                  if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
1449                      reportPowerSaveWhitelistChangedLocked();
1450                      updateWhitelistAppIdsLocked();
1451                      writeConfigFileLocked();
1452                  }
1453                  return true;
1454              } catch (PackageManager.NameNotFoundException e) {
1455                  return false;
1456              }
1457          }
1458      }
1459  
removePowerSaveWhitelistAppInternal(String name)1460      public boolean removePowerSaveWhitelistAppInternal(String name) {
1461          synchronized (this) {
1462              if (mPowerSaveWhitelistUserApps.remove(name) != null) {
1463                  reportPowerSaveWhitelistChangedLocked();
1464                  updateWhitelistAppIdsLocked();
1465                  writeConfigFileLocked();
1466                  return true;
1467              }
1468          }
1469          return false;
1470      }
1471  
getPowerSaveWhitelistAppInternal(String name)1472      public boolean getPowerSaveWhitelistAppInternal(String name) {
1473          synchronized (this) {
1474              return mPowerSaveWhitelistUserApps.containsKey(name);
1475          }
1476      }
1477  
getSystemPowerWhitelistExceptIdleInternal()1478      public String[] getSystemPowerWhitelistExceptIdleInternal() {
1479          synchronized (this) {
1480              int size = mPowerSaveWhitelistAppsExceptIdle.size();
1481              String[] apps = new String[size];
1482              for (int i = 0; i < size; i++) {
1483                  apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1484              }
1485              return apps;
1486          }
1487      }
1488  
getSystemPowerWhitelistInternal()1489      public String[] getSystemPowerWhitelistInternal() {
1490          synchronized (this) {
1491              int size = mPowerSaveWhitelistApps.size();
1492              String[] apps = new String[size];
1493              for (int i = 0; i < size; i++) {
1494                  apps[i] = mPowerSaveWhitelistApps.keyAt(i);
1495              }
1496              return apps;
1497          }
1498      }
1499  
getUserPowerWhitelistInternal()1500      public String[] getUserPowerWhitelistInternal() {
1501          synchronized (this) {
1502              int size = mPowerSaveWhitelistUserApps.size();
1503              String[] apps = new String[size];
1504              for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1505                  apps[i] = mPowerSaveWhitelistUserApps.keyAt(i);
1506              }
1507              return apps;
1508          }
1509      }
1510  
getFullPowerWhitelistExceptIdleInternal()1511      public String[] getFullPowerWhitelistExceptIdleInternal() {
1512          synchronized (this) {
1513              int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
1514              String[] apps = new String[size];
1515              int cur = 0;
1516              for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
1517                  apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1518                  cur++;
1519              }
1520              for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1521                  apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1522                  cur++;
1523              }
1524              return apps;
1525          }
1526      }
1527  
getFullPowerWhitelistInternal()1528      public String[] getFullPowerWhitelistInternal() {
1529          synchronized (this) {
1530              int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
1531              String[] apps = new String[size];
1532              int cur = 0;
1533              for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
1534                  apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
1535                  cur++;
1536              }
1537              for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1538                  apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1539                  cur++;
1540              }
1541              return apps;
1542          }
1543      }
1544  
isPowerSaveWhitelistExceptIdleAppInternal(String packageName)1545      public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
1546          synchronized (this) {
1547              return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
1548                      || mPowerSaveWhitelistUserApps.containsKey(packageName);
1549          }
1550      }
1551  
isPowerSaveWhitelistAppInternal(String packageName)1552      public boolean isPowerSaveWhitelistAppInternal(String packageName) {
1553          synchronized (this) {
1554              return mPowerSaveWhitelistApps.containsKey(packageName)
1555                      || mPowerSaveWhitelistUserApps.containsKey(packageName);
1556          }
1557      }
1558  
getAppIdWhitelistExceptIdleInternal()1559      public int[] getAppIdWhitelistExceptIdleInternal() {
1560          synchronized (this) {
1561              return mPowerSaveWhitelistExceptIdleAppIdArray;
1562          }
1563      }
1564  
getAppIdWhitelistInternal()1565      public int[] getAppIdWhitelistInternal() {
1566          synchronized (this) {
1567              return mPowerSaveWhitelistAllAppIdArray;
1568          }
1569      }
1570  
getAppIdUserWhitelistInternal()1571      public int[] getAppIdUserWhitelistInternal() {
1572          synchronized (this) {
1573              return mPowerSaveWhitelistUserAppIdArray;
1574          }
1575      }
1576  
getAppIdTempWhitelistInternal()1577      public int[] getAppIdTempWhitelistInternal() {
1578          synchronized (this) {
1579              return mTempWhitelistAppIdArray;
1580          }
1581      }
1582  
addPowerSaveTempWhitelistAppChecked(String packageName, long duration, int userId, String reason)1583      void addPowerSaveTempWhitelistAppChecked(String packageName, long duration,
1584              int userId, String reason) throws RemoteException {
1585          getContext().enforceCallingPermission(
1586                  Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
1587                  "No permission to change device idle whitelist");
1588          final int callingUid = Binder.getCallingUid();
1589          userId = ActivityManagerNative.getDefault().handleIncomingUser(
1590                  Binder.getCallingPid(),
1591                  callingUid,
1592                  userId,
1593                  /*allowAll=*/ false,
1594                  /*requireFull=*/ false,
1595                  "addPowerSaveTempWhitelistApp", null);
1596          final long token = Binder.clearCallingIdentity();
1597          try {
1598              addPowerSaveTempWhitelistAppInternal(callingUid,
1599                      packageName, duration, userId, true, reason);
1600          } finally {
1601              Binder.restoreCallingIdentity(token);
1602          }
1603      }
1604  
1605      /**
1606       * Adds an app to the temporary whitelist and resets the endTime for granting the
1607       * app an exemption to access network and acquire wakelocks.
1608       */
addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName, long duration, int userId, boolean sync, String reason)1609      void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
1610              long duration, int userId, boolean sync, String reason) {
1611          try {
1612              int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId);
1613              int appId = UserHandle.getAppId(uid);
1614              addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
1615          } catch (NameNotFoundException e) {
1616          }
1617      }
1618  
1619      /**
1620       * Adds an app to the temporary whitelist and resets the endTime for granting the
1621       * app an exemption to access network and acquire wakelocks.
1622       */
addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId, long duration, boolean sync, String reason)1623      void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
1624              long duration, boolean sync, String reason) {
1625          final long timeNow = SystemClock.elapsedRealtime();
1626          Runnable networkPolicyTempWhitelistCallback = null;
1627          synchronized (this) {
1628              int callingAppId = UserHandle.getAppId(callingUid);
1629              if (callingAppId >= Process.FIRST_APPLICATION_UID) {
1630                  if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
1631                      throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
1632                              + " is not on whitelist");
1633                  }
1634              }
1635              duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
1636              Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
1637              final boolean newEntry = entry == null;
1638              // Set the new end time
1639              if (newEntry) {
1640                  entry = new Pair<>(new MutableLong(0), reason);
1641                  mTempWhitelistAppIdEndTimes.put(appId, entry);
1642              }
1643              entry.first.value = timeNow + duration;
1644              if (DEBUG) {
1645                  Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist. New entry: " + newEntry);
1646              }
1647              if (newEntry) {
1648                  // No pending timeout for the app id, post a delayed message
1649                  try {
1650                      mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
1651                              reason, appId);
1652                  } catch (RemoteException e) {
1653                  }
1654                  postTempActiveTimeoutMessage(appId, duration);
1655                  updateTempWhitelistAppIdsLocked();
1656                  if (mNetworkPolicyTempWhitelistCallback != null) {
1657                      if (!sync) {
1658                          mHandler.post(mNetworkPolicyTempWhitelistCallback);
1659                      } else {
1660                          networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
1661                      }
1662                  }
1663                  reportTempWhitelistChangedLocked();
1664              }
1665          }
1666          if (networkPolicyTempWhitelistCallback != null) {
1667              networkPolicyTempWhitelistCallback.run();
1668          }
1669      }
1670  
setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback)1671      public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
1672          synchronized (this) {
1673              mNetworkPolicyTempWhitelistCallback = callback;
1674          }
1675      }
1676  
postTempActiveTimeoutMessage(int uid, long delay)1677      private void postTempActiveTimeoutMessage(int uid, long delay) {
1678          if (DEBUG) {
1679              Slog.d(TAG, "postTempActiveTimeoutMessage: uid=" + uid + ", delay=" + delay);
1680          }
1681          mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
1682                  delay);
1683      }
1684  
checkTempAppWhitelistTimeout(int uid)1685      void checkTempAppWhitelistTimeout(int uid) {
1686          final long timeNow = SystemClock.elapsedRealtime();
1687          if (DEBUG) {
1688              Slog.d(TAG, "checkTempAppWhitelistTimeout: uid=" + uid + ", timeNow=" + timeNow);
1689          }
1690          synchronized (this) {
1691              Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
1692              if (entry == null) {
1693                  // Nothing to do
1694                  return;
1695              }
1696              if (timeNow >= entry.first.value) {
1697                  mTempWhitelistAppIdEndTimes.delete(uid);
1698                  if (DEBUG) {
1699                      Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
1700                  }
1701                  updateTempWhitelistAppIdsLocked();
1702                  if (mNetworkPolicyTempWhitelistCallback != null) {
1703                      mHandler.post(mNetworkPolicyTempWhitelistCallback);
1704                  }
1705                  reportTempWhitelistChangedLocked();
1706                  try {
1707                      mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
1708                              entry.second, uid);
1709                  } catch (RemoteException e) {
1710                  }
1711              } else {
1712                  // Need more time
1713                  if (DEBUG) {
1714                      Slog.d(TAG, "Time to remove UID " + uid + ": " + entry.first.value);
1715                  }
1716                  postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
1717              }
1718          }
1719      }
1720  
exitIdleInternal(String reason)1721      public void exitIdleInternal(String reason) {
1722          synchronized (this) {
1723              becomeActiveLocked(reason, Binder.getCallingUid());
1724          }
1725      }
1726  
updateConnectivityState(Intent connIntent)1727      void updateConnectivityState(Intent connIntent) {
1728          ConnectivityService cm;
1729          synchronized (this) {
1730              cm = mConnectivityService;
1731          }
1732          if (cm == null) {
1733              return;
1734          }
1735          // Note: can't call out to ConnectivityService with our lock held.
1736          NetworkInfo ni = cm.getActiveNetworkInfo();
1737          synchronized (this) {
1738              boolean conn;
1739              if (ni == null) {
1740                  conn = false;
1741              } else {
1742                  if (connIntent == null) {
1743                      conn = ni.isConnected();
1744                  } else {
1745                      final int networkType =
1746                              connIntent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
1747                                      ConnectivityManager.TYPE_NONE);
1748                      if (ni.getType() != networkType) {
1749                          return;
1750                      }
1751                      conn = !connIntent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
1752                              false);
1753                  }
1754              }
1755              if (conn != mNetworkConnected) {
1756                  mNetworkConnected = conn;
1757                  if (conn && mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
1758                      stepLightIdleStateLocked("network");
1759                  }
1760              }
1761          }
1762      }
1763  
updateDisplayLocked()1764      void updateDisplayLocked() {
1765          mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
1766          // We consider any situation where the display is showing something to be it on,
1767          // because if there is anything shown we are going to be updating it at some
1768          // frequency so can't be allowed to go into deep sleeps.
1769          boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
1770          if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
1771          if (!screenOn && mScreenOn) {
1772              mScreenOn = false;
1773              if (!mForceIdle) {
1774                  becomeInactiveIfAppropriateLocked();
1775              }
1776          } else if (screenOn) {
1777              mScreenOn = true;
1778              if (!mForceIdle) {
1779                  becomeActiveLocked("screen", Process.myUid());
1780              }
1781          }
1782      }
1783  
updateChargingLocked(boolean charging)1784      void updateChargingLocked(boolean charging) {
1785          if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
1786          if (!charging && mCharging) {
1787              mCharging = false;
1788              if (!mForceIdle) {
1789                  becomeInactiveIfAppropriateLocked();
1790              }
1791          } else if (charging) {
1792              mCharging = charging;
1793              if (!mForceIdle) {
1794                  becomeActiveLocked("charging", Process.myUid());
1795              }
1796          }
1797      }
1798  
scheduleReportActiveLocked(String activeReason, int activeUid)1799      void scheduleReportActiveLocked(String activeReason, int activeUid) {
1800          Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
1801          mHandler.sendMessage(msg);
1802      }
1803  
becomeActiveLocked(String activeReason, int activeUid)1804      void becomeActiveLocked(String activeReason, int activeUid) {
1805          if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
1806          if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
1807              EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
1808              EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
1809              scheduleReportActiveLocked(activeReason, activeUid);
1810              mState = STATE_ACTIVE;
1811              mLightState = LIGHT_STATE_ACTIVE;
1812              mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
1813              mCurIdleBudget = 0;
1814              mMaintenanceStartTime = 0;
1815              resetIdleManagementLocked();
1816              resetLightIdleManagementLocked();
1817              addEvent(EVENT_NORMAL);
1818          }
1819      }
1820  
becomeInactiveIfAppropriateLocked()1821      void becomeInactiveIfAppropriateLocked() {
1822          if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
1823          if ((!mScreenOn && !mCharging) || mForceIdle) {
1824              // Screen has turned off; we are now going to become inactive and start
1825              // waiting to see if we will ultimately go idle.
1826              if (mState == STATE_ACTIVE && mDeepEnabled) {
1827                  mState = STATE_INACTIVE;
1828                  if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
1829                  resetIdleManagementLocked();
1830                  scheduleAlarmLocked(mInactiveTimeout, false);
1831                  EventLogTags.writeDeviceIdle(mState, "no activity");
1832              }
1833              if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
1834                  mLightState = LIGHT_STATE_INACTIVE;
1835                  if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
1836                  resetLightIdleManagementLocked();
1837                  scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
1838                  EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
1839              }
1840          }
1841      }
1842  
resetIdleManagementLocked()1843      void resetIdleManagementLocked() {
1844          mNextIdlePendingDelay = 0;
1845          mNextIdleDelay = 0;
1846          mNextLightIdleDelay = 0;
1847          cancelAlarmLocked();
1848          cancelSensingTimeoutAlarmLocked();
1849          cancelLocatingLocked();
1850          stopMonitoringMotionLocked();
1851          mAnyMotionDetector.stop();
1852      }
1853  
resetLightIdleManagementLocked()1854      void resetLightIdleManagementLocked() {
1855          cancelLightAlarmLocked();
1856      }
1857  
exitForceIdleLocked()1858      void exitForceIdleLocked() {
1859          if (mForceIdle) {
1860              mForceIdle = false;
1861              if (mScreenOn || mCharging) {
1862                  becomeActiveLocked("exit-force", Process.myUid());
1863              }
1864          }
1865      }
1866  
stepLightIdleStateLocked(String reason)1867      void stepLightIdleStateLocked(String reason) {
1868          if (mLightState == LIGHT_STATE_OVERRIDE) {
1869              // If we are already in deep device idle mode, then
1870              // there is nothing left to do for light mode.
1871              return;
1872          }
1873  
1874          if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState);
1875          EventLogTags.writeDeviceIdleLightStep();
1876  
1877          switch (mLightState) {
1878              case LIGHT_STATE_INACTIVE:
1879                  mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
1880                  // Reset the upcoming idle delays.
1881                  mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
1882                  mMaintenanceStartTime = 0;
1883                  if (!isOpsInactiveLocked()) {
1884                      // We have some active ops going on...  give them a chance to finish
1885                      // before going in to our first idle.
1886                      mLightState = LIGHT_STATE_PRE_IDLE;
1887                      EventLogTags.writeDeviceIdleLight(mLightState, reason);
1888                      scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT);
1889                      break;
1890                  }
1891                  // Nothing active, fall through to immediately idle.
1892              case LIGHT_STATE_PRE_IDLE:
1893              case LIGHT_STATE_IDLE_MAINTENANCE:
1894                  if (mMaintenanceStartTime != 0) {
1895                      long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime;
1896                      if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
1897                          // We didn't use up all of our minimum budget; add this to the reserve.
1898                          mCurIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET-duration);
1899                      } else {
1900                          // We used more than our minimum budget; this comes out of the reserve.
1901                          mCurIdleBudget -= (duration-mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);
1902                      }
1903                  }
1904                  mMaintenanceStartTime = 0;
1905                  scheduleLightAlarmLocked(mNextLightIdleDelay);
1906                  mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
1907                          (long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
1908                  if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {
1909                      mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
1910                  }
1911                  if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
1912                  mLightState = LIGHT_STATE_IDLE;
1913                  EventLogTags.writeDeviceIdleLight(mLightState, reason);
1914                  addEvent(EVENT_LIGHT_IDLE);
1915                  mGoingIdleWakeLock.acquire();
1916                  mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
1917                  break;
1918              case LIGHT_STATE_IDLE:
1919              case LIGHT_STATE_WAITING_FOR_NETWORK:
1920                  if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
1921                      // We have been idling long enough, now it is time to do some work.
1922                      mActiveIdleOpCount = 1;
1923                      mActiveIdleWakeLock.acquire();
1924                      mMaintenanceStartTime = SystemClock.elapsedRealtime();
1925                      if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
1926                          mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
1927                      } else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
1928                          mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
1929                      }
1930                      scheduleLightAlarmLocked(mCurIdleBudget);
1931                      if (DEBUG) Slog.d(TAG,
1932                              "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
1933                      mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
1934                      EventLogTags.writeDeviceIdleLight(mLightState, reason);
1935                      addEvent(EVENT_LIGHT_MAINTENANCE);
1936                      mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1937                  } else {
1938                      // We'd like to do maintenance, but currently don't have network
1939                      // connectivity...  let's try to wait until the network comes back.
1940                      // We'll only wait for another full idle period, however, and then give up.
1941                      scheduleLightAlarmLocked(mNextLightIdleDelay);
1942                      if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK.");
1943                      mLightState = LIGHT_STATE_WAITING_FOR_NETWORK;
1944                      EventLogTags.writeDeviceIdleLight(mLightState, reason);
1945                  }
1946                  break;
1947          }
1948      }
1949  
stepIdleStateLocked(String reason)1950      void stepIdleStateLocked(String reason) {
1951          if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
1952          EventLogTags.writeDeviceIdleStep();
1953  
1954          final long now = SystemClock.elapsedRealtime();
1955          if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
1956              // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
1957              if (mState != STATE_ACTIVE) {
1958                  becomeActiveLocked("alarm", Process.myUid());
1959                  becomeInactiveIfAppropriateLocked();
1960              }
1961              return;
1962          }
1963  
1964          switch (mState) {
1965              case STATE_INACTIVE:
1966                  // We have now been inactive long enough, it is time to start looking
1967                  // for motion and sleep some more while doing so.
1968                  startMonitoringMotionLocked();
1969                  scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
1970                  // Reset the upcoming idle delays.
1971                  mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
1972                  mNextIdleDelay = mConstants.IDLE_TIMEOUT;
1973                  mState = STATE_IDLE_PENDING;
1974                  if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
1975                  EventLogTags.writeDeviceIdle(mState, reason);
1976                  break;
1977              case STATE_IDLE_PENDING:
1978                  mState = STATE_SENSING;
1979                  if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
1980                  EventLogTags.writeDeviceIdle(mState, reason);
1981                  scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
1982                  cancelLocatingLocked();
1983                  mNotMoving = false;
1984                  mLocated = false;
1985                  mLastGenericLocation = null;
1986                  mLastGpsLocation = null;
1987                  mAnyMotionDetector.checkForAnyMotion();
1988                  break;
1989              case STATE_SENSING:
1990                  cancelSensingTimeoutAlarmLocked();
1991                  mState = STATE_LOCATING;
1992                  if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
1993                  EventLogTags.writeDeviceIdle(mState, reason);
1994                  scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
1995                  if (mLocationManager != null
1996                          && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
1997                      mLocationManager.requestLocationUpdates(mLocationRequest,
1998                              mGenericLocationListener, mHandler.getLooper());
1999                      mLocating = true;
2000                  } else {
2001                      mHasNetworkLocation = false;
2002                  }
2003                  if (mLocationManager != null
2004                          && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
2005                      mHasGps = true;
2006                      mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
2007                              mGpsLocationListener, mHandler.getLooper());
2008                      mLocating = true;
2009                  } else {
2010                      mHasGps = false;
2011                  }
2012                  // If we have a location provider, we're all set, the listeners will move state
2013                  // forward.
2014                  if (mLocating) {
2015                      break;
2016                  }
2017  
2018                  // Otherwise, we have to move from locating into idle maintenance.
2019              case STATE_LOCATING:
2020                  cancelAlarmLocked();
2021                  cancelLocatingLocked();
2022                  mAnyMotionDetector.stop();
2023  
2024              case STATE_IDLE_MAINTENANCE:
2025                  scheduleAlarmLocked(mNextIdleDelay, true);
2026                  if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
2027                          " ms.");
2028                  mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
2029                  if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
2030                  mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
2031                  if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
2032                      mNextIdleDelay = mConstants.IDLE_TIMEOUT;
2033                  }
2034                  mState = STATE_IDLE;
2035                  if (mLightState != LIGHT_STATE_OVERRIDE) {
2036                      mLightState = LIGHT_STATE_OVERRIDE;
2037                      cancelLightAlarmLocked();
2038                  }
2039                  EventLogTags.writeDeviceIdle(mState, reason);
2040                  addEvent(EVENT_DEEP_IDLE);
2041                  mGoingIdleWakeLock.acquire();
2042                  mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
2043                  break;
2044              case STATE_IDLE:
2045                  // We have been idling long enough, now it is time to do some work.
2046                  mActiveIdleOpCount = 1;
2047                  mActiveIdleWakeLock.acquire();
2048                  scheduleAlarmLocked(mNextIdlePendingDelay, false);
2049                  if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
2050                          "Next alarm in " + mNextIdlePendingDelay + " ms.");
2051                  mMaintenanceStartTime = SystemClock.elapsedRealtime();
2052                  mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
2053                          (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
2054                  if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
2055                      mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
2056                  }
2057                  mState = STATE_IDLE_MAINTENANCE;
2058                  EventLogTags.writeDeviceIdle(mState, reason);
2059                  addEvent(EVENT_DEEP_MAINTENANCE);
2060                  mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
2061                  break;
2062          }
2063      }
2064  
incActiveIdleOps()2065      void incActiveIdleOps() {
2066          synchronized (this) {
2067              mActiveIdleOpCount++;
2068          }
2069      }
2070  
decActiveIdleOps()2071      void decActiveIdleOps() {
2072          synchronized (this) {
2073              mActiveIdleOpCount--;
2074              if (mActiveIdleOpCount <= 0) {
2075                  exitMaintenanceEarlyIfNeededLocked();
2076                  mActiveIdleWakeLock.release();
2077              }
2078          }
2079      }
2080  
setJobsActive(boolean active)2081      void setJobsActive(boolean active) {
2082          synchronized (this) {
2083              mJobsActive = active;
2084              reportMaintenanceActivityIfNeededLocked();
2085              if (!active) {
2086                  exitMaintenanceEarlyIfNeededLocked();
2087              }
2088          }
2089      }
2090  
setAlarmsActive(boolean active)2091      void setAlarmsActive(boolean active) {
2092          synchronized (this) {
2093              mAlarmsActive = active;
2094              if (!active) {
2095                  exitMaintenanceEarlyIfNeededLocked();
2096              }
2097          }
2098      }
2099  
registerMaintenanceActivityListener(IMaintenanceActivityListener listener)2100      boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener) {
2101          synchronized (this) {
2102              mMaintenanceActivityListeners.register(listener);
2103              return mReportedMaintenanceActivity;
2104          }
2105      }
2106  
unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener)2107      void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener) {
2108          synchronized (this) {
2109              mMaintenanceActivityListeners.unregister(listener);
2110          }
2111      }
2112  
reportMaintenanceActivityIfNeededLocked()2113      void reportMaintenanceActivityIfNeededLocked() {
2114          boolean active = mJobsActive;
2115          if (active == mReportedMaintenanceActivity) {
2116              return;
2117          }
2118          mReportedMaintenanceActivity = active;
2119          Message msg = mHandler.obtainMessage(MSG_REPORT_MAINTENANCE_ACTIVITY,
2120                  mReportedMaintenanceActivity ? 1 : 0, 0);
2121          mHandler.sendMessage(msg);
2122      }
2123  
isOpsInactiveLocked()2124      boolean isOpsInactiveLocked() {
2125          return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
2126      }
2127  
exitMaintenanceEarlyIfNeededLocked()2128      void exitMaintenanceEarlyIfNeededLocked() {
2129          if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE
2130                  || mLightState == LIGHT_STATE_PRE_IDLE) {
2131              if (isOpsInactiveLocked()) {
2132                  final long now = SystemClock.elapsedRealtime();
2133                  if (DEBUG) {
2134                      StringBuilder sb = new StringBuilder();
2135                      sb.append("Exit: start=");
2136                      TimeUtils.formatDuration(mMaintenanceStartTime, sb);
2137                      sb.append(" now=");
2138                      TimeUtils.formatDuration(now, sb);
2139                      Slog.d(TAG, sb.toString());
2140                  }
2141                  if (mState == STATE_IDLE_MAINTENANCE) {
2142                      stepIdleStateLocked("s:early");
2143                  } else if (mLightState == LIGHT_STATE_PRE_IDLE) {
2144                      stepLightIdleStateLocked("s:predone");
2145                  } else {
2146                      stepLightIdleStateLocked("s:early");
2147                  }
2148              }
2149          }
2150      }
2151  
motionLocked()2152      void motionLocked() {
2153          if (DEBUG) Slog.d(TAG, "motionLocked()");
2154          // The motion sensor will have been disabled at this point
2155          handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
2156      }
2157  
handleMotionDetectedLocked(long timeout, String type)2158      void handleMotionDetectedLocked(long timeout, String type) {
2159          // The device is not yet active, so we want to go back to the pending idle
2160          // state to wait again for no motion.  Note that we only monitor for motion
2161          // after moving out of the inactive state, so no need to worry about that.
2162          boolean becomeInactive = false;
2163          if (mState != STATE_ACTIVE) {
2164              scheduleReportActiveLocked(type, Process.myUid());
2165              mState = STATE_ACTIVE;
2166              mInactiveTimeout = timeout;
2167              mCurIdleBudget = 0;
2168              mMaintenanceStartTime = 0;
2169              EventLogTags.writeDeviceIdle(mState, type);
2170              addEvent(EVENT_NORMAL);
2171              becomeInactive = true;
2172          }
2173          if (mLightState == LIGHT_STATE_OVERRIDE) {
2174              // We went out of light idle mode because we had started deep idle mode...  let's
2175              // now go back and reset things so we resume light idling if appropriate.
2176              mLightState = STATE_ACTIVE;
2177              EventLogTags.writeDeviceIdleLight(mLightState, type);
2178              becomeInactive = true;
2179          }
2180          if (becomeInactive) {
2181              becomeInactiveIfAppropriateLocked();
2182          }
2183      }
2184  
receivedGenericLocationLocked(Location location)2185      void receivedGenericLocationLocked(Location location) {
2186          if (mState != STATE_LOCATING) {
2187              cancelLocatingLocked();
2188              return;
2189          }
2190          if (DEBUG) Slog.d(TAG, "Generic location: " + location);
2191          mLastGenericLocation = new Location(location);
2192          if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
2193              return;
2194          }
2195          mLocated = true;
2196          if (mNotMoving) {
2197              stepIdleStateLocked("s:location");
2198          }
2199      }
2200  
receivedGpsLocationLocked(Location location)2201      void receivedGpsLocationLocked(Location location) {
2202          if (mState != STATE_LOCATING) {
2203              cancelLocatingLocked();
2204              return;
2205          }
2206          if (DEBUG) Slog.d(TAG, "GPS location: " + location);
2207          mLastGpsLocation = new Location(location);
2208          if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
2209              return;
2210          }
2211          mLocated = true;
2212          if (mNotMoving) {
2213              stepIdleStateLocked("s:gps");
2214          }
2215      }
2216  
startMonitoringMotionLocked()2217      void startMonitoringMotionLocked() {
2218          if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()");
2219          if (mMotionSensor != null && !mMotionListener.active) {
2220              mMotionListener.registerLocked();
2221          }
2222      }
2223  
stopMonitoringMotionLocked()2224      void stopMonitoringMotionLocked() {
2225          if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()");
2226          if (mMotionSensor != null && mMotionListener.active) {
2227              mMotionListener.unregisterLocked();
2228          }
2229      }
2230  
cancelAlarmLocked()2231      void cancelAlarmLocked() {
2232          if (mNextAlarmTime != 0) {
2233              mNextAlarmTime = 0;
2234              mAlarmManager.cancel(mDeepAlarmListener);
2235          }
2236      }
2237  
cancelLightAlarmLocked()2238      void cancelLightAlarmLocked() {
2239          if (mNextLightAlarmTime != 0) {
2240              mNextLightAlarmTime = 0;
2241              mAlarmManager.cancel(mLightAlarmListener);
2242          }
2243      }
2244  
cancelLocatingLocked()2245      void cancelLocatingLocked() {
2246          if (mLocating) {
2247              mLocationManager.removeUpdates(mGenericLocationListener);
2248              mLocationManager.removeUpdates(mGpsLocationListener);
2249              mLocating = false;
2250          }
2251      }
2252  
cancelSensingTimeoutAlarmLocked()2253      void cancelSensingTimeoutAlarmLocked() {
2254          if (mNextSensingTimeoutAlarmTime != 0) {
2255              mNextSensingTimeoutAlarmTime = 0;
2256              mAlarmManager.cancel(mSensingTimeoutAlarmListener);
2257          }
2258      }
2259  
scheduleAlarmLocked(long delay, boolean idleUntil)2260      void scheduleAlarmLocked(long delay, boolean idleUntil) {
2261          if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
2262          if (mMotionSensor == null) {
2263              // If there is no motion sensor on this device, then we won't schedule
2264              // alarms, because we can't determine if the device is not moving.  This effectively
2265              // turns off normal execution of device idling, although it is still possible to
2266              // manually poke it by pretending like the alarm is going off.
2267              return;
2268          }
2269          mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
2270          if (idleUntil) {
2271              mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
2272                      mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
2273          } else {
2274              mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
2275                      mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
2276          }
2277      }
2278  
scheduleLightAlarmLocked(long delay)2279      void scheduleLightAlarmLocked(long delay) {
2280          if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
2281          mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
2282          mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
2283                  mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
2284      }
2285  
scheduleSensingTimeoutAlarmLocked(long delay)2286      void scheduleSensingTimeoutAlarmLocked(long delay) {
2287          if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
2288          mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
2289          mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
2290              "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
2291      }
2292  
buildAppIdArray(ArrayMap<String, Integer> systemApps, ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds)2293      private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
2294              ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
2295          outAppIds.clear();
2296          if (systemApps != null) {
2297              for (int i = 0; i < systemApps.size(); i++) {
2298                  outAppIds.put(systemApps.valueAt(i), true);
2299              }
2300          }
2301          if (userApps != null) {
2302              for (int i = 0; i < userApps.size(); i++) {
2303                  outAppIds.put(userApps.valueAt(i), true);
2304              }
2305          }
2306          int size = outAppIds.size();
2307          int[] appids = new int[size];
2308          for (int i = 0; i < size; i++) {
2309              appids[i] = outAppIds.keyAt(i);
2310          }
2311          return appids;
2312      }
2313  
updateWhitelistAppIdsLocked()2314      private void updateWhitelistAppIdsLocked() {
2315          mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
2316                  mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
2317          mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
2318                  mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
2319          mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
2320                  mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
2321          if (mLocalPowerManager != null) {
2322              if (DEBUG) {
2323                  Slog.d(TAG, "Setting wakelock whitelist to "
2324                          + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
2325              }
2326              mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
2327          }
2328          if (mLocalAlarmManager != null) {
2329              if (DEBUG) {
2330                  Slog.d(TAG, "Setting alarm whitelist to "
2331                          + Arrays.toString(mPowerSaveWhitelistUserAppIdArray));
2332              }
2333              mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
2334          }
2335      }
2336  
updateTempWhitelistAppIdsLocked()2337      private void updateTempWhitelistAppIdsLocked() {
2338          final int size = mTempWhitelistAppIdEndTimes.size();
2339          if (mTempWhitelistAppIdArray.length != size) {
2340              mTempWhitelistAppIdArray = new int[size];
2341          }
2342          for (int i = 0; i < size; i++) {
2343              mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
2344          }
2345          if (mLocalPowerManager != null) {
2346              if (DEBUG) {
2347                  Slog.d(TAG, "Setting wakelock temp whitelist to "
2348                          + Arrays.toString(mTempWhitelistAppIdArray));
2349              }
2350              mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
2351          }
2352      }
2353  
reportPowerSaveWhitelistChangedLocked()2354      private void reportPowerSaveWhitelistChangedLocked() {
2355          Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
2356          intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2357          getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
2358      }
2359  
reportTempWhitelistChangedLocked()2360      private void reportTempWhitelistChangedLocked() {
2361          Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
2362          intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2363          getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
2364      }
2365  
readConfigFileLocked()2366      void readConfigFileLocked() {
2367          if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
2368          mPowerSaveWhitelistUserApps.clear();
2369          FileInputStream stream;
2370          try {
2371              stream = mConfigFile.openRead();
2372          } catch (FileNotFoundException e) {
2373              return;
2374          }
2375          try {
2376              XmlPullParser parser = Xml.newPullParser();
2377              parser.setInput(stream, StandardCharsets.UTF_8.name());
2378              readConfigFileLocked(parser);
2379          } catch (XmlPullParserException e) {
2380          } finally {
2381              try {
2382                  stream.close();
2383              } catch (IOException e) {
2384              }
2385          }
2386      }
2387  
readConfigFileLocked(XmlPullParser parser)2388      private void readConfigFileLocked(XmlPullParser parser) {
2389          final PackageManager pm = getContext().getPackageManager();
2390  
2391          try {
2392              int type;
2393              while ((type = parser.next()) != XmlPullParser.START_TAG
2394                      && type != XmlPullParser.END_DOCUMENT) {
2395                  ;
2396              }
2397  
2398              if (type != XmlPullParser.START_TAG) {
2399                  throw new IllegalStateException("no start tag found");
2400              }
2401  
2402              int outerDepth = parser.getDepth();
2403              while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2404                      && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2405                  if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2406                      continue;
2407                  }
2408  
2409                  String tagName = parser.getName();
2410                  if (tagName.equals("wl")) {
2411                      String name = parser.getAttributeValue(null, "n");
2412                      if (name != null) {
2413                          try {
2414                              ApplicationInfo ai = pm.getApplicationInfo(name,
2415                                      PackageManager.MATCH_UNINSTALLED_PACKAGES);
2416                              mPowerSaveWhitelistUserApps.put(ai.packageName,
2417                                      UserHandle.getAppId(ai.uid));
2418                          } catch (PackageManager.NameNotFoundException e) {
2419                          }
2420                      }
2421                  } else {
2422                      Slog.w(TAG, "Unknown element under <config>: "
2423                              + parser.getName());
2424                      XmlUtils.skipCurrentTag(parser);
2425                  }
2426              }
2427  
2428          } catch (IllegalStateException e) {
2429              Slog.w(TAG, "Failed parsing config " + e);
2430          } catch (NullPointerException e) {
2431              Slog.w(TAG, "Failed parsing config " + e);
2432          } catch (NumberFormatException e) {
2433              Slog.w(TAG, "Failed parsing config " + e);
2434          } catch (XmlPullParserException e) {
2435              Slog.w(TAG, "Failed parsing config " + e);
2436          } catch (IOException e) {
2437              Slog.w(TAG, "Failed parsing config " + e);
2438          } catch (IndexOutOfBoundsException e) {
2439              Slog.w(TAG, "Failed parsing config " + e);
2440          }
2441      }
2442  
writeConfigFileLocked()2443      void writeConfigFileLocked() {
2444          mHandler.removeMessages(MSG_WRITE_CONFIG);
2445          mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
2446      }
2447  
handleWriteConfigFile()2448      void handleWriteConfigFile() {
2449          final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
2450  
2451          try {
2452              synchronized (this) {
2453                  XmlSerializer out = new FastXmlSerializer();
2454                  out.setOutput(memStream, StandardCharsets.UTF_8.name());
2455                  writeConfigFileLocked(out);
2456              }
2457          } catch (IOException e) {
2458          }
2459  
2460          synchronized (mConfigFile) {
2461              FileOutputStream stream = null;
2462              try {
2463                  stream = mConfigFile.startWrite();
2464                  memStream.writeTo(stream);
2465                  stream.flush();
2466                  FileUtils.sync(stream);
2467                  stream.close();
2468                  mConfigFile.finishWrite(stream);
2469              } catch (IOException e) {
2470                  Slog.w(TAG, "Error writing config file", e);
2471                  mConfigFile.failWrite(stream);
2472              }
2473          }
2474      }
2475  
writeConfigFileLocked(XmlSerializer out)2476      void writeConfigFileLocked(XmlSerializer out) throws IOException {
2477          out.startDocument(null, true);
2478          out.startTag(null, "config");
2479          for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
2480              String name = mPowerSaveWhitelistUserApps.keyAt(i);
2481              out.startTag(null, "wl");
2482              out.attribute(null, "n", name);
2483              out.endTag(null, "wl");
2484          }
2485          out.endTag(null, "config");
2486          out.endDocument();
2487      }
2488  
dumpHelp(PrintWriter pw)2489      static void dumpHelp(PrintWriter pw) {
2490          pw.println("Device idle controller (deviceidle) commands:");
2491          pw.println("  help");
2492          pw.println("    Print this help text.");
2493          pw.println("  step [light|deep]");
2494          pw.println("    Immediately step to next state, without waiting for alarm.");
2495          pw.println("  force-idle [light|deep]");
2496          pw.println("    Force directly into idle mode, regardless of other device state.");
2497          pw.println("  force-inactive");
2498          pw.println("    Force to be inactive, ready to freely step idle states.");
2499          pw.println("  unforce");
2500          pw.println("    Resume normal functioning after force-idle or force-inactive.");
2501          pw.println("  get [light|deep|force|screen|charging|network]");
2502          pw.println("    Retrieve the current given state.");
2503          pw.println("  disable [light|deep|all]");
2504          pw.println("    Completely disable device idle mode.");
2505          pw.println("  enable [light|deep|all]");
2506          pw.println("    Re-enable device idle mode after it had previously been disabled.");
2507          pw.println("  enabled [light|deep|all]");
2508          pw.println("    Print 1 if device idle mode is currently enabled, else 0.");
2509          pw.println("  whitelist");
2510          pw.println("    Print currently whitelisted apps.");
2511          pw.println("  whitelist [package ...]");
2512          pw.println("    Add (prefix with +) or remove (prefix with -) packages.");
2513          pw.println("  tempwhitelist");
2514          pw.println("    Print packages that are temporarily whitelisted.");
2515          pw.println("  tempwhitelist [-u] [package ..]");
2516          pw.println("    Temporarily place packages in whitelist for 10 seconds.");
2517      }
2518  
2519      class Shell extends ShellCommand {
2520          int userId = UserHandle.USER_SYSTEM;
2521  
2522          @Override
onCommand(String cmd)2523          public int onCommand(String cmd) {
2524              return onShellCommand(this, cmd);
2525          }
2526  
2527          @Override
onHelp()2528          public void onHelp() {
2529              PrintWriter pw = getOutPrintWriter();
2530              dumpHelp(pw);
2531          }
2532      }
2533  
onShellCommand(Shell shell, String cmd)2534      int onShellCommand(Shell shell, String cmd) {
2535          PrintWriter pw = shell.getOutPrintWriter();
2536          if ("step".equals(cmd)) {
2537              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2538                      null);
2539              synchronized (this) {
2540                  long token = Binder.clearCallingIdentity();
2541                  String arg = shell.getNextArg();
2542                  try {
2543                      if (arg == null || "deep".equals(arg)) {
2544                          stepIdleStateLocked("s:shell");
2545                          pw.print("Stepped to deep: ");
2546                          pw.println(stateToString(mState));
2547                      } else if ("light".equals(arg)) {
2548                          stepLightIdleStateLocked("s:shell");
2549                          pw.print("Stepped to light: "); pw.println(lightStateToString(mLightState));
2550                      } else {
2551                          pw.println("Unknown idle mode: " + arg);
2552                      }
2553                  } finally {
2554                      Binder.restoreCallingIdentity(token);
2555                  }
2556              }
2557          } else if ("force-idle".equals(cmd)) {
2558              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2559                      null);
2560              synchronized (this) {
2561                  long token = Binder.clearCallingIdentity();
2562                  String arg = shell.getNextArg();
2563                  try {
2564                      if (arg == null || "deep".equals(arg)) {
2565                          if (!mDeepEnabled) {
2566                              pw.println("Unable to go deep idle; not enabled");
2567                              return -1;
2568                          }
2569                          mForceIdle = true;
2570                          becomeInactiveIfAppropriateLocked();
2571                          int curState = mState;
2572                          while (curState != STATE_IDLE) {
2573                              stepIdleStateLocked("s:shell");
2574                              if (curState == mState) {
2575                                  pw.print("Unable to go deep idle; stopped at ");
2576                                  pw.println(stateToString(mState));
2577                                  exitForceIdleLocked();
2578                                  return -1;
2579                              }
2580                              curState = mState;
2581                          }
2582                          pw.println("Now forced in to deep idle mode");
2583                      } else if ("light".equals(arg)) {
2584                          mForceIdle = true;
2585                          becomeInactiveIfAppropriateLocked();
2586                          int curLightState = mLightState;
2587                          while (curLightState != LIGHT_STATE_IDLE) {
2588                              stepIdleStateLocked("s:shell");
2589                              if (curLightState == mLightState) {
2590                                  pw.print("Unable to go light idle; stopped at ");
2591                                  pw.println(lightStateToString(mLightState));
2592                                  exitForceIdleLocked();
2593                                  return -1;
2594                              }
2595                              curLightState = mLightState;
2596                          }
2597                          pw.println("Now forced in to light idle mode");
2598                      } else {
2599                          pw.println("Unknown idle mode: " + arg);
2600                      }
2601                  } finally {
2602                      Binder.restoreCallingIdentity(token);
2603                  }
2604              }
2605          } else if ("force-inactive".equals(cmd)) {
2606              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2607                      null);
2608              synchronized (this) {
2609                  long token = Binder.clearCallingIdentity();
2610                  try {
2611                      mForceIdle = true;
2612                      becomeInactiveIfAppropriateLocked();
2613                      pw.print("Light state: ");
2614                      pw.print(lightStateToString(mLightState));
2615                      pw.print(", deep state: ");
2616                      pw.println(stateToString(mState));
2617                  } finally {
2618                      Binder.restoreCallingIdentity(token);
2619                  }
2620              }
2621          } else if ("unforce".equals(cmd)) {
2622              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2623                      null);
2624              synchronized (this) {
2625                  long token = Binder.clearCallingIdentity();
2626                  try {
2627                      exitForceIdleLocked();
2628                      pw.print("Light state: ");
2629                      pw.print(lightStateToString(mLightState));
2630                      pw.print(", deep state: ");
2631                      pw.println(stateToString(mState));
2632                  } finally {
2633                      Binder.restoreCallingIdentity(token);
2634                  }
2635              }
2636          } else if ("get".equals(cmd)) {
2637              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2638                      null);
2639              synchronized (this) {
2640                  String arg = shell.getNextArg();
2641                  if (arg != null) {
2642                      long token = Binder.clearCallingIdentity();
2643                      try {
2644                          switch (arg) {
2645                              case "light": pw.println(lightStateToString(mLightState)); break;
2646                              case "deep": pw.println(stateToString(mState)); break;
2647                              case "force": pw.println(mForceIdle); break;
2648                              case "screen": pw.println(mScreenOn); break;
2649                              case "charging": pw.println(mCharging); break;
2650                              case "network": pw.println(mNetworkConnected); break;
2651                              default: pw.println("Unknown get option: " + arg); break;
2652                          }
2653                      } finally {
2654                          Binder.restoreCallingIdentity(token);
2655                      }
2656                  } else {
2657                      pw.println("Argument required");
2658                  }
2659              }
2660          } else if ("disable".equals(cmd)) {
2661              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2662                      null);
2663              synchronized (this) {
2664                  long token = Binder.clearCallingIdentity();
2665                  String arg = shell.getNextArg();
2666                  try {
2667                      boolean becomeActive = false;
2668                      boolean valid = false;
2669                      if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
2670                          valid = true;
2671                          if (mDeepEnabled) {
2672                              mDeepEnabled = false;
2673                              becomeActive = true;
2674                              pw.println("Deep idle mode disabled");
2675                          }
2676                      }
2677                      if (arg == null || "light".equals(arg) || "all".equals(arg)) {
2678                          valid = true;
2679                          if (mLightEnabled) {
2680                              mLightEnabled = false;
2681                              becomeActive = true;
2682                              pw.println("Light idle mode disabled");
2683                          }
2684                      }
2685                      if (becomeActive) {
2686                          becomeActiveLocked((arg == null ? "all" : arg) + "-disabled",
2687                                  Process.myUid());
2688                      }
2689                      if (!valid) {
2690                          pw.println("Unknown idle mode: " + arg);
2691                      }
2692                  } finally {
2693                      Binder.restoreCallingIdentity(token);
2694                  }
2695              }
2696          } else if ("enable".equals(cmd)) {
2697              getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2698                      null);
2699              synchronized (this) {
2700                  long token = Binder.clearCallingIdentity();
2701                  String arg = shell.getNextArg();
2702                  try {
2703                      boolean becomeInactive = false;
2704                      boolean valid = false;
2705                      if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
2706                          valid = true;
2707                          if (!mDeepEnabled) {
2708                              mDeepEnabled = true;
2709                              becomeInactive = true;
2710                              pw.println("Deep idle mode enabled");
2711                          }
2712                      }
2713                      if (arg == null || "light".equals(arg) || "all".equals(arg)) {
2714                          valid = true;
2715                          if (!mLightEnabled) {
2716                              mLightEnabled = true;
2717                              becomeInactive = true;
2718                              pw.println("Light idle mode enable");
2719                          }
2720                      }
2721                      if (becomeInactive) {
2722                          becomeInactiveIfAppropriateLocked();
2723                      }
2724                      if (!valid) {
2725                          pw.println("Unknown idle mode: " + arg);
2726                      }
2727                  } finally {
2728                      Binder.restoreCallingIdentity(token);
2729                  }
2730              }
2731          } else if ("enabled".equals(cmd)) {
2732              synchronized (this) {
2733                  String arg = shell.getNextArg();
2734                  if (arg == null || "all".equals(arg)) {
2735                      pw.println(mDeepEnabled && mLightEnabled ? "1" : 0);
2736                  } else if ("deep".equals(arg)) {
2737                      pw.println(mDeepEnabled ? "1" : 0);
2738                  } else if ("light".equals(arg)) {
2739                      pw.println(mLightEnabled ? "1" : 0);
2740                  } else {
2741                      pw.println("Unknown idle mode: " + arg);
2742                  }
2743              }
2744          } else if ("whitelist".equals(cmd)) {
2745              String arg = shell.getNextArg();
2746              if (arg != null) {
2747                  getContext().enforceCallingOrSelfPermission(
2748                          android.Manifest.permission.DEVICE_POWER, null);
2749                  long token = Binder.clearCallingIdentity();
2750                  try {
2751                      do {
2752                          if (arg.length() < 1 || (arg.charAt(0) != '-'
2753                                  && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
2754                              pw.println("Package must be prefixed with +, -, or =: " + arg);
2755                              return -1;
2756                          }
2757                          char op = arg.charAt(0);
2758                          String pkg = arg.substring(1);
2759                          if (op == '+') {
2760                              if (addPowerSaveWhitelistAppInternal(pkg)) {
2761                                  pw.println("Added: " + pkg);
2762                              } else {
2763                                  pw.println("Unknown package: " + pkg);
2764                              }
2765                          } else if (op == '-') {
2766                              if (removePowerSaveWhitelistAppInternal(pkg)) {
2767                                  pw.println("Removed: " + pkg);
2768                              }
2769                          } else {
2770                              pw.println(getPowerSaveWhitelistAppInternal(pkg));
2771                          }
2772                      } while ((arg=shell.getNextArg()) != null);
2773                  } finally {
2774                      Binder.restoreCallingIdentity(token);
2775                  }
2776              } else {
2777                  synchronized (this) {
2778                      for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
2779                          pw.print("system-excidle,");
2780                          pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
2781                          pw.print(",");
2782                          pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
2783                      }
2784                      for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
2785                          pw.print("system,");
2786                          pw.print(mPowerSaveWhitelistApps.keyAt(j));
2787                          pw.print(",");
2788                          pw.println(mPowerSaveWhitelistApps.valueAt(j));
2789                      }
2790                      for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
2791                          pw.print("user,");
2792                          pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
2793                          pw.print(",");
2794                          pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
2795                      }
2796                  }
2797              }
2798          } else if ("tempwhitelist".equals(cmd)) {
2799              String opt;
2800              while ((opt=shell.getNextOption()) != null) {
2801                  if ("-u".equals(opt)) {
2802                      opt = shell.getNextArg();
2803                      if (opt == null) {
2804                          pw.println("-u requires a user number");
2805                          return -1;
2806                      }
2807                      shell.userId = Integer.parseInt(opt);
2808                  }
2809              }
2810              String arg = shell.getNextArg();
2811              if (arg != null) {
2812                  try {
2813                      addPowerSaveTempWhitelistAppChecked(arg, 10000L, shell.userId, "shell");
2814                  } catch (RemoteException re) {
2815                      pw.println("Failed: " + re);
2816                  }
2817              } else {
2818                  dumpTempWhitelistSchedule(pw, false);
2819              }
2820          } else {
2821              return shell.handleDefaultCommands(cmd);
2822          }
2823          return 0;
2824      }
2825  
dump(FileDescriptor fd, PrintWriter pw, String[] args)2826      void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2827          if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
2828                  != PackageManager.PERMISSION_GRANTED) {
2829              pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
2830                      + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2831                      + " without permission " + android.Manifest.permission.DUMP);
2832              return;
2833          }
2834  
2835          if (args != null) {
2836              int userId = UserHandle.USER_SYSTEM;
2837              for (int i=0; i<args.length; i++) {
2838                  String arg = args[i];
2839                  if ("-h".equals(arg)) {
2840                      dumpHelp(pw);
2841                      return;
2842                  } else if ("-u".equals(arg)) {
2843                      i++;
2844                      if (i < args.length) {
2845                          arg = args[i];
2846                          userId = Integer.parseInt(arg);
2847                      }
2848                  } else if ("-a".equals(arg)) {
2849                      // Ignore, we always dump all.
2850                  } else if (arg.length() > 0 && arg.charAt(0) == '-'){
2851                      pw.println("Unknown option: " + arg);
2852                      return;
2853                  } else {
2854                      Shell shell = new Shell();
2855                      shell.userId = userId;
2856                      String[] newArgs = new String[args.length-i];
2857                      System.arraycopy(args, i, newArgs, 0, args.length-i);
2858                      shell.exec(mBinderService, null, fd, null, newArgs, new ResultReceiver(null));
2859                      return;
2860                  }
2861              }
2862          }
2863  
2864          synchronized (this) {
2865              mConstants.dump(pw);
2866  
2867              if (mEventCmds[0] != EVENT_NULL) {
2868                  pw.println("  Idling history:");
2869                  long now = SystemClock.elapsedRealtime();
2870                  for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) {
2871                      int cmd = mEventCmds[i];
2872                      if (cmd == EVENT_NULL) {
2873                          continue;
2874                      }
2875                      String label;
2876                      switch (mEventCmds[i]) {
2877                          case EVENT_NORMAL:              label = "     normal"; break;
2878                          case EVENT_LIGHT_IDLE:          label = " light-idle"; break;
2879                          case EVENT_LIGHT_MAINTENANCE:   label = "light-maint"; break;
2880                          case EVENT_DEEP_IDLE:           label = "  deep-idle"; break;
2881                          case EVENT_DEEP_MAINTENANCE:    label = " deep-maint"; break;
2882                          default:                        label = "         ??"; break;
2883                      }
2884                      pw.print("    ");
2885                      pw.print(label);
2886                      pw.print(": ");
2887                      TimeUtils.formatDuration(mEventTimes[i], now, pw);;
2888                      pw.println();
2889                  }
2890              }
2891  
2892              int size = mPowerSaveWhitelistAppsExceptIdle.size();
2893              if (size > 0) {
2894                  pw.println("  Whitelist (except idle) system apps:");
2895                  for (int i = 0; i < size; i++) {
2896                      pw.print("    ");
2897                      pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
2898                  }
2899              }
2900              size = mPowerSaveWhitelistApps.size();
2901              if (size > 0) {
2902                  pw.println("  Whitelist system apps:");
2903                  for (int i = 0; i < size; i++) {
2904                      pw.print("    ");
2905                      pw.println(mPowerSaveWhitelistApps.keyAt(i));
2906                  }
2907              }
2908              size = mPowerSaveWhitelistUserApps.size();
2909              if (size > 0) {
2910                  pw.println("  Whitelist user apps:");
2911                  for (int i = 0; i < size; i++) {
2912                      pw.print("    ");
2913                      pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
2914                  }
2915              }
2916              size = mPowerSaveWhitelistExceptIdleAppIds.size();
2917              if (size > 0) {
2918                  pw.println("  Whitelist (except idle) all app ids:");
2919                  for (int i = 0; i < size; i++) {
2920                      pw.print("    ");
2921                      pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
2922                      pw.println();
2923                  }
2924              }
2925              size = mPowerSaveWhitelistUserAppIds.size();
2926              if (size > 0) {
2927                  pw.println("  Whitelist user app ids:");
2928                  for (int i = 0; i < size; i++) {
2929                      pw.print("    ");
2930                      pw.print(mPowerSaveWhitelistUserAppIds.keyAt(i));
2931                      pw.println();
2932                  }
2933              }
2934              size = mPowerSaveWhitelistAllAppIds.size();
2935              if (size > 0) {
2936                  pw.println("  Whitelist all app ids:");
2937                  for (int i = 0; i < size; i++) {
2938                      pw.print("    ");
2939                      pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
2940                      pw.println();
2941                  }
2942              }
2943              dumpTempWhitelistSchedule(pw, true);
2944  
2945              size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
2946              if (size > 0) {
2947                  pw.println("  Temp whitelist app ids:");
2948                  for (int i = 0; i < size; i++) {
2949                      pw.print("    ");
2950                      pw.print(mTempWhitelistAppIdArray[i]);
2951                      pw.println();
2952                  }
2953              }
2954  
2955              pw.print("  mLightEnabled="); pw.print(mLightEnabled);
2956              pw.print("  mDeepEnabled="); pw.println(mDeepEnabled);
2957              pw.print("  mForceIdle="); pw.println(mForceIdle);
2958              pw.print("  mMotionSensor="); pw.println(mMotionSensor);
2959              pw.print("  mCurDisplay="); pw.println(mCurDisplay);
2960              pw.print("  mScreenOn="); pw.println(mScreenOn);
2961              pw.print("  mNetworkConnected="); pw.println(mNetworkConnected);
2962              pw.print("  mCharging="); pw.println(mCharging);
2963              pw.print("  mMotionActive="); pw.println(mMotionListener.active);
2964              pw.print("  mNotMoving="); pw.println(mNotMoving);
2965              pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
2966                      pw.print(mHasGps); pw.print(" mHasNetwork=");
2967                      pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
2968              if (mLastGenericLocation != null) {
2969                  pw.print("  mLastGenericLocation="); pw.println(mLastGenericLocation);
2970              }
2971              if (mLastGpsLocation != null) {
2972                  pw.print("  mLastGpsLocation="); pw.println(mLastGpsLocation);
2973              }
2974              pw.print("  mState="); pw.print(stateToString(mState));
2975              pw.print(" mLightState=");
2976              pw.println(lightStateToString(mLightState));
2977              pw.print("  mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
2978              pw.println();
2979              if (mActiveIdleOpCount != 0) {
2980                  pw.print("  mActiveIdleOpCount="); pw.println(mActiveIdleOpCount);
2981              }
2982              if (mNextAlarmTime != 0) {
2983                  pw.print("  mNextAlarmTime=");
2984                  TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
2985                  pw.println();
2986              }
2987              if (mNextIdlePendingDelay != 0) {
2988                  pw.print("  mNextIdlePendingDelay=");
2989                  TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
2990                  pw.println();
2991              }
2992              if (mNextIdleDelay != 0) {
2993                  pw.print("  mNextIdleDelay=");
2994                  TimeUtils.formatDuration(mNextIdleDelay, pw);
2995                  pw.println();
2996              }
2997              if (mNextLightIdleDelay != 0) {
2998                  pw.print("  mNextIdleDelay=");
2999                  TimeUtils.formatDuration(mNextLightIdleDelay, pw);
3000                  pw.println();
3001              }
3002              if (mNextLightAlarmTime != 0) {
3003                  pw.print("  mNextLightAlarmTime=");
3004                  TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
3005                  pw.println();
3006              }
3007              if (mCurIdleBudget != 0) {
3008                  pw.print("  mCurIdleBudget=");
3009                  TimeUtils.formatDuration(mCurIdleBudget, pw);
3010                  pw.println();
3011              }
3012              if (mMaintenanceStartTime != 0) {
3013                  pw.print("  mMaintenanceStartTime=");
3014                  TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw);
3015                  pw.println();
3016              }
3017              if (mJobsActive) {
3018                  pw.print("  mJobsActive="); pw.println(mJobsActive);
3019              }
3020              if (mAlarmsActive) {
3021                  pw.print("  mAlarmsActive="); pw.println(mAlarmsActive);
3022              }
3023          }
3024      }
3025  
dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle)3026      void dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle) {
3027          final int size = mTempWhitelistAppIdEndTimes.size();
3028          if (size > 0) {
3029              String prefix = "";
3030              if (printTitle) {
3031                  pw.println("  Temp whitelist schedule:");
3032                  prefix = "    ";
3033              }
3034              final long timeNow = SystemClock.elapsedRealtime();
3035              for (int i = 0; i < size; i++) {
3036                  pw.print(prefix);
3037                  pw.print("UID=");
3038                  pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
3039                  pw.print(": ");
3040                  Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
3041                  TimeUtils.formatDuration(entry.first.value, timeNow, pw);
3042                  pw.print(" - ");
3043                  pw.println(entry.second);
3044              }
3045          }
3046      }
3047   }
3048