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