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.SensorEvent;
34 import android.hardware.SensorEventListener;
35 import android.hardware.SensorManager;
36 import android.hardware.TriggerEvent;
37 import android.hardware.TriggerEventListener;
38 import android.location.Location;
39 import android.location.LocationListener;
40 import android.location.LocationManager;
41 import android.location.LocationRequest;
42 import android.net.ConnectivityManager;
43 import android.net.INetworkPolicyManager;
44 import android.net.NetworkInfo;
45 import android.net.Uri;
46 import android.os.BatteryManager;
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.PowerManager.ServiceType;
59 import android.os.PowerManagerInternal;
60 import android.os.Process;
61 import android.os.RemoteCallbackList;
62 import android.os.RemoteException;
63 import android.os.ResultReceiver;
64 import android.os.ServiceManager;
65 import android.os.ShellCallback;
66 import android.os.ShellCommand;
67 import android.os.SystemClock;
68 import android.os.UserHandle;
69 import android.provider.Settings;
70 import android.util.ArrayMap;
71 import android.util.ArraySet;
72 import android.util.KeyValueListParser;
73 import android.util.MutableLong;
74 import android.util.Pair;
75 import android.util.Slog;
76 import android.util.SparseArray;
77 import android.util.SparseBooleanArray;
78 import android.util.TimeUtils;
79 import android.util.Xml;
80 
81 import com.android.internal.annotations.GuardedBy;
82 import com.android.internal.annotations.VisibleForTesting;
83 import com.android.internal.app.IBatteryStats;
84 import com.android.internal.os.AtomicFile;
85 import com.android.internal.os.BackgroundThread;
86 import com.android.internal.util.DumpUtils;
87 import com.android.internal.util.FastXmlSerializer;
88 import com.android.internal.util.XmlUtils;
89 import com.android.server.am.BatteryStatsService;
90 import com.android.server.deviceidle.ConstraintController;
91 import com.android.server.deviceidle.DeviceIdleConstraintTracker;
92 import com.android.server.deviceidle.IDeviceIdleConstraint;
93 import com.android.server.deviceidle.TvConstraintController;
94 import com.android.server.net.NetworkPolicyManagerInternal;
95 import com.android.server.wm.ActivityTaskManagerInternal;
96 
97 import org.xmlpull.v1.XmlPullParser;
98 import org.xmlpull.v1.XmlPullParserException;
99 import org.xmlpull.v1.XmlSerializer;
100 
101 import java.io.ByteArrayOutputStream;
102 import java.io.File;
103 import java.io.FileDescriptor;
104 import java.io.FileInputStream;
105 import java.io.FileNotFoundException;
106 import java.io.FileOutputStream;
107 import java.io.IOException;
108 import java.io.PrintWriter;
109 import java.nio.charset.StandardCharsets;
110 import java.util.Arrays;
111 import java.util.stream.Collectors;
112 
113 /**
114  * Keeps track of device idleness and drives low power mode based on that.
115  *
116  * Test: atest com.android.server.DeviceIdleControllerTest
117  *
118  * Current idling state machine (as of Android Q). This can be visualized using Graphviz:
119    <pre>
120 
121    digraph {
122      subgraph deep {
123        label="deep";
124 
125        STATE_ACTIVE [label="STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon"]
126        STATE_INACTIVE [label="STATE_INACTIVE\nScreen off AND Not charging"]
127        STATE_QUICK_DOZE_DELAY [
128          label="STATE_QUICK_DOZE_DELAY\n"
129              + "Screen off AND Not charging\n"
130              + "Location, motion detection, and significant motion monitoring turned off"
131        ]
132        STATE_IDLE_PENDING [
133          label="STATE_IDLE_PENDING\nSignificant motion monitoring turned on"
134        ]
135        STATE_SENSING [label="STATE_SENSING\nMonitoring for ANY motion"]
136        STATE_LOCATING [
137          label="STATE_LOCATING\nRequesting location, motion monitoring still on"
138        ]
139        STATE_IDLE [
140          label="STATE_IDLE\nLocation and motion detection turned off\n"
141              + "Significant motion monitoring state unchanged"
142        ]
143        STATE_IDLE_MAINTENANCE [label="STATE_IDLE_MAINTENANCE\n"]
144 
145        STATE_ACTIVE -> STATE_INACTIVE [
146          label="becomeInactiveIfAppropriateLocked() AND Quick Doze not enabled"
147        ]
148        STATE_ACTIVE -> STATE_QUICK_DOZE_DELAY [
149          label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
150        ]
151 
152        STATE_INACTIVE -> STATE_ACTIVE [
153          label="handleMotionDetectedLocked(), becomeActiveLocked()"
154        ]
155        STATE_INACTIVE -> STATE_IDLE_PENDING [label="stepIdleStateLocked()"]
156        STATE_INACTIVE -> STATE_QUICK_DOZE_DELAY [
157          label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
158        ]
159 
160        STATE_IDLE_PENDING -> STATE_ACTIVE [
161          label="handleMotionDetectedLocked(), becomeActiveLocked()"
162        ]
163        STATE_IDLE_PENDING -> STATE_SENSING [label="stepIdleStateLocked()"]
164        STATE_IDLE_PENDING -> STATE_QUICK_DOZE_DELAY [
165          label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
166        ]
167 
168        STATE_SENSING -> STATE_ACTIVE [
169          label="handleMotionDetectedLocked(), becomeActiveLocked()"
170        ]
171        STATE_SENSING -> STATE_LOCATING [label="stepIdleStateLocked()"]
172        STATE_SENSING -> STATE_QUICK_DOZE_DELAY [
173          label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
174        ]
175        STATE_SENSING -> STATE_IDLE [
176          label="stepIdleStateLocked()\n"
177              + "No Location Manager OR (no Network provider AND no GPS provider)"
178        ]
179 
180        STATE_LOCATING -> STATE_ACTIVE [
181          label="handleMotionDetectedLocked(), becomeActiveLocked()"
182        ]
183        STATE_LOCATING -> STATE_QUICK_DOZE_DELAY [
184          label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
185        ]
186        STATE_LOCATING -> STATE_IDLE [label="stepIdleStateLocked()"]
187 
188        STATE_QUICK_DOZE_DELAY -> STATE_ACTIVE [
189          label="handleMotionDetectedLocked(), becomeActiveLocked()"
190        ]
191        STATE_QUICK_DOZE_DELAY -> STATE_IDLE [label="stepIdleStateLocked()"]
192 
193        STATE_IDLE -> STATE_ACTIVE [label="handleMotionDetectedLocked(), becomeActiveLocked()"]
194        STATE_IDLE -> STATE_IDLE_MAINTENANCE [label="stepIdleStateLocked()"]
195 
196        STATE_IDLE_MAINTENANCE -> STATE_ACTIVE [
197          label="handleMotionDetectedLocked(), becomeActiveLocked()"
198        ]
199        STATE_IDLE_MAINTENANCE -> STATE_IDLE [
200          label="stepIdleStateLocked(), exitMaintenanceEarlyIfNeededLocked()"
201        ]
202      }
203 
204      subgraph light {
205        label="light"
206 
207        LIGHT_STATE_ACTIVE [
208          label="LIGHT_STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon"
209        ]
210        LIGHT_STATE_INACTIVE [label="LIGHT_STATE_INACTIVE\nScreen off AND Not charging"]
211        LIGHT_STATE_PRE_IDLE [
212          label="LIGHT_STATE_PRE_IDLE\n"
213              + "Delay going into LIGHT_STATE_IDLE due to some running jobs or alarms"
214        ]
215        LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n"]
216        LIGHT_STATE_WAITING_FOR_NETWORK [
217          label="LIGHT_STATE_WAITING_FOR_NETWORK\n"
218              + "Coming out of LIGHT_STATE_IDLE, waiting for network"
219        ]
220        LIGHT_STATE_IDLE_MAINTENANCE [label="LIGHT_STATE_IDLE_MAINTENANCE\n"]
221        LIGHT_STATE_OVERRIDE [
222          label="LIGHT_STATE_OVERRIDE\nDevice in deep doze, light no longer changing states"
223        ]
224 
225        LIGHT_STATE_ACTIVE -> LIGHT_STATE_INACTIVE [
226          label="becomeInactiveIfAppropriateLocked()"
227        ]
228        LIGHT_STATE_ACTIVE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
229 
230        LIGHT_STATE_INACTIVE -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
231        LIGHT_STATE_INACTIVE -> LIGHT_STATE_PRE_IDLE [label="active jobs"]
232        LIGHT_STATE_INACTIVE -> LIGHT_STATE_IDLE [label="no active jobs"]
233        LIGHT_STATE_INACTIVE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
234 
235        LIGHT_STATE_PRE_IDLE -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
236        LIGHT_STATE_PRE_IDLE -> LIGHT_STATE_IDLE [
237          label="stepLightIdleStateLocked(), exitMaintenanceEarlyIfNeededLocked()"
238        ]
239        LIGHT_STATE_PRE_IDLE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
240 
241        LIGHT_STATE_IDLE -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
242        LIGHT_STATE_IDLE -> LIGHT_STATE_WAITING_FOR_NETWORK [label="no network"]
243        LIGHT_STATE_IDLE -> LIGHT_STATE_IDLE_MAINTENANCE
244        LIGHT_STATE_IDLE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
245 
246        LIGHT_STATE_WAITING_FOR_NETWORK -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
247        LIGHT_STATE_WAITING_FOR_NETWORK -> LIGHT_STATE_IDLE_MAINTENANCE
248        LIGHT_STATE_WAITING_FOR_NETWORK -> LIGHT_STATE_OVERRIDE [
249          label="deep goes to STATE_IDLE"
250        ]
251 
252        LIGHT_STATE_IDLE_MAINTENANCE -> LIGHT_STATE_ACTIVE [label="becomeActiveLocked()"]
253        LIGHT_STATE_IDLE_MAINTENANCE -> LIGHT_STATE_IDLE [
254          label="stepLightIdleStateLocked(), exitMaintenanceEarlyIfNeededLocked()"
255        ]
256        LIGHT_STATE_IDLE_MAINTENANCE -> LIGHT_STATE_OVERRIDE [label="deep goes to STATE_IDLE"]
257 
258        LIGHT_STATE_OVERRIDE -> LIGHT_STATE_ACTIVE [
259          label="handleMotionDetectedLocked(), becomeActiveLocked()"
260        ]
261      }
262    }
263    </pre>
264  */
265 public class DeviceIdleController extends SystemService
266         implements AnyMotionDetector.DeviceIdleCallback {
267     private static final String TAG = "DeviceIdleController";
268 
269     private static final boolean DEBUG = false;
270 
271     private static final boolean COMPRESS_TIME = false;
272 
273     private static final int EVENT_BUFFER_SIZE = 100;
274 
275     private AlarmManager mAlarmManager;
276     private AlarmManagerInternal mLocalAlarmManager;
277     private IBatteryStats mBatteryStats;
278     private ActivityManagerInternal mLocalActivityManager;
279     private ActivityTaskManagerInternal mLocalActivityTaskManager;
280     private PowerManagerInternal mLocalPowerManager;
281     private PowerManager mPowerManager;
282     private INetworkPolicyManager mNetworkPolicyManager;
283     private SensorManager mSensorManager;
284     private final boolean mUseMotionSensor;
285     private Sensor mMotionSensor;
286     private LocationRequest mLocationRequest;
287     private Intent mIdleIntent;
288     private Intent mLightIdleIntent;
289     private AnyMotionDetector mAnyMotionDetector;
290     private final AppStateTracker mAppStateTracker;
291     private boolean mLightEnabled;
292     private boolean mDeepEnabled;
293     private boolean mQuickDozeActivated;
294     private boolean mForceIdle;
295     private boolean mNetworkConnected;
296     private boolean mScreenOn;
297     private boolean mCharging;
298     private boolean mNotMoving;
299     private boolean mLocating;
300     private boolean mLocated;
301     private boolean mHasGps;
302     private boolean mHasNetworkLocation;
303     private Location mLastGenericLocation;
304     private Location mLastGpsLocation;
305     // Current locked state of the screen
306     private boolean mScreenLocked;
307     private int mNumBlockingConstraints = 0;
308 
309     /**
310      * Constraints are the "handbrakes" that stop the device from moving into a lower state until
311      * every one is released at the same time.
312      *
313      * @see #registerDeviceIdleConstraintInternal(IDeviceIdleConstraint, String, int)
314      */
315     private final ArrayMap<IDeviceIdleConstraint, DeviceIdleConstraintTracker>
316             mConstraints = new ArrayMap<>();
317     private ConstraintController mConstraintController;
318 
319     /** Device is currently active. */
320     @VisibleForTesting
321     static final int STATE_ACTIVE = 0;
322     /** Device is inactive (screen off, no motion) and we are waiting to for idle. */
323     @VisibleForTesting
324     static final int STATE_INACTIVE = 1;
325     /** Device is past the initial inactive period, and waiting for the next idle period. */
326     @VisibleForTesting
327     static final int STATE_IDLE_PENDING = 2;
328     /** Device is currently sensing motion. */
329     @VisibleForTesting
330     static final int STATE_SENSING = 3;
331     /** Device is currently finding location (and may still be sensing). */
332     @VisibleForTesting
333     static final int STATE_LOCATING = 4;
334     /** Device is in the idle state, trying to stay asleep as much as possible. */
335     @VisibleForTesting
336     static final int STATE_IDLE = 5;
337     /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
338     @VisibleForTesting
339     static final int STATE_IDLE_MAINTENANCE = 6;
340     /**
341      * Device is inactive and should go straight into idle (foregoing motion and location
342      * monitoring), but allow some time for current work to complete first.
343      */
344     @VisibleForTesting
345     static final int STATE_QUICK_DOZE_DELAY = 7;
346 
347     private static final int ACTIVE_REASON_UNKNOWN = 0;
348     private static final int ACTIVE_REASON_MOTION = 1;
349     private static final int ACTIVE_REASON_SCREEN = 2;
350     private static final int ACTIVE_REASON_CHARGING = 3;
351     private static final int ACTIVE_REASON_UNLOCKED = 4;
352     private static final int ACTIVE_REASON_FROM_BINDER_CALL = 5;
353     private static final int ACTIVE_REASON_FORCED = 6;
354     private static final int ACTIVE_REASON_ALARM = 7;
355     @VisibleForTesting
356     static final int SET_IDLE_FACTOR_RESULT_UNINIT = -1;
357     @VisibleForTesting
358     static final int SET_IDLE_FACTOR_RESULT_IGNORED = 0;
359     @VisibleForTesting
360     static final int SET_IDLE_FACTOR_RESULT_OK = 1;
361     @VisibleForTesting
362     static final int SET_IDLE_FACTOR_RESULT_NOT_SUPPORT = 2;
363     @VisibleForTesting
364     static final int SET_IDLE_FACTOR_RESULT_INVALID = 3;
365     @VisibleForTesting
366     static final long MIN_STATE_STEP_ALARM_CHANGE = 60 * 1000;
367     @VisibleForTesting
368     static final float MIN_PRE_IDLE_FACTOR_CHANGE = 0.05f;
369 
370     @VisibleForTesting
stateToString(int state)371     static String stateToString(int state) {
372         switch (state) {
373             case STATE_ACTIVE: return "ACTIVE";
374             case STATE_INACTIVE: return "INACTIVE";
375             case STATE_IDLE_PENDING: return "IDLE_PENDING";
376             case STATE_SENSING: return "SENSING";
377             case STATE_LOCATING: return "LOCATING";
378             case STATE_IDLE: return "IDLE";
379             case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
380             case STATE_QUICK_DOZE_DELAY: return "QUICK_DOZE_DELAY";
381             default: return Integer.toString(state);
382         }
383     }
384 
385     /** Device is currently active. */
386     @VisibleForTesting
387     static final int LIGHT_STATE_ACTIVE = 0;
388     /** Device is inactive (screen off) and we are waiting to for the first light idle. */
389     @VisibleForTesting
390     static final int LIGHT_STATE_INACTIVE = 1;
391     /** Device is about to go idle for the first time, wait for current work to complete. */
392     @VisibleForTesting
393     static final int LIGHT_STATE_PRE_IDLE = 3;
394     /** Device is in the light idle state, trying to stay asleep as much as possible. */
395     @VisibleForTesting
396     static final int LIGHT_STATE_IDLE = 4;
397     /** Device is in the light idle state, we want to go in to idle maintenance but are
398      * waiting for network connectivity before doing so. */
399     @VisibleForTesting
400     static final int LIGHT_STATE_WAITING_FOR_NETWORK = 5;
401     /** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
402     @VisibleForTesting
403     static final int LIGHT_STATE_IDLE_MAINTENANCE = 6;
404     /** Device light idle state is overriden, now applying deep doze state. */
405     @VisibleForTesting
406     static final int LIGHT_STATE_OVERRIDE = 7;
407 
408     @VisibleForTesting
lightStateToString(int state)409     static String lightStateToString(int state) {
410         switch (state) {
411             case LIGHT_STATE_ACTIVE: return "ACTIVE";
412             case LIGHT_STATE_INACTIVE: return "INACTIVE";
413             case LIGHT_STATE_PRE_IDLE: return "PRE_IDLE";
414             case LIGHT_STATE_IDLE: return "IDLE";
415             case LIGHT_STATE_WAITING_FOR_NETWORK: return "WAITING_FOR_NETWORK";
416             case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
417             case LIGHT_STATE_OVERRIDE: return "OVERRIDE";
418             default: return Integer.toString(state);
419         }
420     }
421 
422     private int mState;
423     private int mLightState;
424 
425     private long mInactiveTimeout;
426     private long mNextAlarmTime;
427     private long mNextIdlePendingDelay;
428     private long mNextIdleDelay;
429     private long mNextLightIdleDelay;
430     private long mNextLightAlarmTime;
431     private long mNextSensingTimeoutAlarmTime;
432     private long mCurIdleBudget;
433     private long mMaintenanceStartTime;
434     private long mIdleStartTime;
435 
436     private int mActiveIdleOpCount;
437     private PowerManager.WakeLock mActiveIdleWakeLock; // held when there are operations in progress
438     private PowerManager.WakeLock mGoingIdleWakeLock;  // held when we are going idle so hardware
439                                                        // (especially NetworkPolicyManager) can shut
440                                                        // down.
441     private boolean mJobsActive;
442     private boolean mAlarmsActive;
443     private boolean mReportedMaintenanceActivity;
444 
445     /* Factor to apply to INACTIVE_TIMEOUT and IDLE_AFTER_INACTIVE_TIMEOUT in order to enter
446      * STATE_IDLE faster or slower. Don't apply this to SENSING_TIMEOUT or LOCATING_TIMEOUT because:
447      *   - Both of them are shorter
448      *   - Device sensor might take time be to become be stabilized
449      * Also don't apply the factor if the device is in motion because device motion provides a
450      * stronger signal than a prediction algorithm.
451      */
452     private float mPreIdleFactor;
453     private float mLastPreIdleFactor;
454     private int mActiveReason;
455 
456     public final AtomicFile mConfigFile;
457 
458     private final RemoteCallbackList<IMaintenanceActivityListener> mMaintenanceActivityListeners =
459             new RemoteCallbackList<IMaintenanceActivityListener>();
460 
461     /**
462      * Package names the system has white-listed to opt out of power save restrictions,
463      * except for device idle mode.
464      */
465     private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
466 
467     /**
468      * Package names the user has white-listed using commandline option to opt out of
469      * power save restrictions, except for device idle mode.
470      */
471     private final ArraySet<String> mPowerSaveWhitelistUserAppsExceptIdle = new ArraySet<>();
472 
473     /**
474      * Package names the system has white-listed to opt out of power save restrictions for
475      * all modes.
476      */
477     private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
478 
479     /**
480      * Package names the user has white-listed to opt out of power save restrictions.
481      */
482     private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
483 
484     /**
485      * App IDs of built-in system apps that have been white-listed except for idle modes.
486      */
487     private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
488             = new SparseBooleanArray();
489 
490     /**
491      * App IDs of built-in system apps that have been white-listed.
492      */
493     private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
494 
495     /**
496      * App IDs that have been white-listed to opt out of power save restrictions, except
497      * for device idle modes.
498      */
499     private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
500 
501     /**
502      * Current app IDs that are in the complete power save white list, but shouldn't be
503      * excluded from idle modes.  This array can be shared with others because it will not be
504      * modified once set.
505      */
506     private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
507 
508     /**
509      * App IDs that have been white-listed to opt out of power save restrictions.
510      */
511     private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
512 
513     /**
514      * Current app IDs that are in the complete power save white list.  This array can
515      * be shared with others because it will not be modified once set.
516      */
517     private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
518 
519     /**
520      * App IDs that have been white-listed by the user to opt out of power save restrictions.
521      */
522     private final SparseBooleanArray mPowerSaveWhitelistUserAppIds = new SparseBooleanArray();
523 
524     /**
525      * Current app IDs that are in the user power save white list.  This array can
526      * be shared with others because it will not be modified once set.
527      */
528     private int[] mPowerSaveWhitelistUserAppIdArray = new int[0];
529 
530     /**
531      * List of end times for UIDs that are temporarily marked as being allowed to access
532      * the network and acquire wakelocks. Times are in milliseconds.
533      */
534     private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
535             = new SparseArray<>();
536 
537     private NetworkPolicyManagerInternal mNetworkPolicyManagerInternal;
538 
539     /**
540      * Current app IDs of temporarily whitelist apps for high-priority messages.
541      */
542     private int[] mTempWhitelistAppIdArray = new int[0];
543 
544     /**
545      * Apps in the system whitelist that have been taken out (probably because the user wanted to).
546      * They can be restored back by calling restoreAppToSystemWhitelist(String).
547      */
548     private ArrayMap<String, Integer> mRemovedFromSystemWhitelistApps = new ArrayMap<>();
549 
550     private static final int EVENT_NULL = 0;
551     private static final int EVENT_NORMAL = 1;
552     private static final int EVENT_LIGHT_IDLE = 2;
553     private static final int EVENT_LIGHT_MAINTENANCE = 3;
554     private static final int EVENT_DEEP_IDLE = 4;
555     private static final int EVENT_DEEP_MAINTENANCE = 5;
556 
557     private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
558     private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
559     private final String[] mEventReasons = new String[EVENT_BUFFER_SIZE];
560 
addEvent(int cmd, String reason)561     private void addEvent(int cmd, String reason) {
562         if (mEventCmds[0] != cmd) {
563             System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1);
564             System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1);
565             System.arraycopy(mEventReasons, 0, mEventReasons, 1, EVENT_BUFFER_SIZE - 1);
566             mEventCmds[0] = cmd;
567             mEventTimes[0] = SystemClock.elapsedRealtime();
568             mEventReasons[0] = reason;
569         }
570     }
571 
572     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
573         @Override public void onReceive(Context context, Intent intent) {
574             switch (intent.getAction()) {
575                 case ConnectivityManager.CONNECTIVITY_ACTION: {
576                     updateConnectivityState(intent);
577                 } break;
578                 case Intent.ACTION_BATTERY_CHANGED: {
579                     boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
580                     boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
581                     synchronized (DeviceIdleController.this) {
582                         updateChargingLocked(present && plugged);
583                     }
584                 } break;
585                 case Intent.ACTION_PACKAGE_REMOVED: {
586                     if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
587                         Uri data = intent.getData();
588                         String ssp;
589                         if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
590                             removePowerSaveWhitelistAppInternal(ssp);
591                         }
592                     }
593                 } break;
594             }
595         }
596     };
597 
598     private final AlarmManager.OnAlarmListener mLightAlarmListener
599             = new AlarmManager.OnAlarmListener() {
600         @Override
601         public void onAlarm() {
602             synchronized (DeviceIdleController.this) {
603                 stepLightIdleStateLocked("s:alarm");
604             }
605         }
606     };
607 
608     private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener
609             = new AlarmManager.OnAlarmListener() {
610         @Override
611         public void onAlarm() {
612             if (mState == STATE_SENSING) {
613                 synchronized (DeviceIdleController.this) {
614                     // Restart the device idle progression in case the device moved but the screen
615                     // didn't turn on.
616                     becomeInactiveIfAppropriateLocked();
617                 }
618             }
619         }
620     };
621 
622     @VisibleForTesting
623     final AlarmManager.OnAlarmListener mDeepAlarmListener
624             = new AlarmManager.OnAlarmListener() {
625         @Override
626         public void onAlarm() {
627             synchronized (DeviceIdleController.this) {
628                 stepIdleStateLocked("s:alarm");
629             }
630         }
631     };
632 
633     private final BroadcastReceiver mIdleStartedDoneReceiver = new BroadcastReceiver() {
634         @Override public void onReceive(Context context, Intent intent) {
635             // When coming out of a deep idle, we will add in some delay before we allow
636             // the system to settle down and finish the maintenance window.  This is
637             // to give a chance for any pending work to be scheduled.
638             if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
639                 mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP,
640                         mConstants.MIN_DEEP_MAINTENANCE_TIME);
641             } else {
642                 mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP,
643                         mConstants.MIN_LIGHT_MAINTENANCE_TIME);
644             }
645         }
646     };
647 
648     private final BroadcastReceiver mInteractivityReceiver = new BroadcastReceiver() {
649         @Override
650         public void onReceive(Context context, Intent intent) {
651             synchronized (DeviceIdleController.this) {
652                 updateInteractivityLocked();
653             }
654         }
655     };
656 
657     @VisibleForTesting
658     final class MotionListener extends TriggerEventListener
659             implements SensorEventListener {
660 
661         boolean active = false;
662 
isActive()663         public boolean isActive() {
664             return active;
665         }
666 
667         @Override
onTrigger(TriggerEvent event)668         public void onTrigger(TriggerEvent event) {
669             synchronized (DeviceIdleController.this) {
670                 active = false;
671                 motionLocked();
672             }
673         }
674 
675         @Override
onSensorChanged(SensorEvent event)676         public void onSensorChanged(SensorEvent event) {
677             synchronized (DeviceIdleController.this) {
678                 mSensorManager.unregisterListener(this, mMotionSensor);
679                 active = false;
680                 motionLocked();
681             }
682         }
683 
684         @Override
onAccuracyChanged(Sensor sensor, int accuracy)685         public void onAccuracyChanged(Sensor sensor, int accuracy) {}
686 
registerLocked()687         public boolean registerLocked() {
688             boolean success;
689             if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
690                 success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
691             } else {
692                 success = mSensorManager.registerListener(
693                         mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL);
694             }
695             if (success) {
696                 active = true;
697             } else {
698                 Slog.e(TAG, "Unable to register for " + mMotionSensor);
699             }
700             return success;
701         }
702 
unregisterLocked()703         public void unregisterLocked() {
704             if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
705                 mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor);
706             } else {
707                 mSensorManager.unregisterListener(mMotionListener);
708             }
709             active = false;
710         }
711     }
712     @VisibleForTesting final MotionListener mMotionListener = new MotionListener();
713 
714     private final LocationListener mGenericLocationListener = new LocationListener() {
715         @Override
716         public void onLocationChanged(Location location) {
717             synchronized (DeviceIdleController.this) {
718                 receivedGenericLocationLocked(location);
719             }
720         }
721 
722         @Override
723         public void onStatusChanged(String provider, int status, Bundle extras) {
724         }
725 
726         @Override
727         public void onProviderEnabled(String provider) {
728         }
729 
730         @Override
731         public void onProviderDisabled(String provider) {
732         }
733     };
734 
735     private final LocationListener mGpsLocationListener = new LocationListener() {
736         @Override
737         public void onLocationChanged(Location location) {
738             synchronized (DeviceIdleController.this) {
739                 receivedGpsLocationLocked(location);
740             }
741         }
742 
743         @Override
744         public void onStatusChanged(String provider, int status, Bundle extras) {
745         }
746 
747         @Override
748         public void onProviderEnabled(String provider) {
749         }
750 
751         @Override
752         public void onProviderDisabled(String provider) {
753         }
754     };
755 
756     /**
757      * All times are in milliseconds. These constants are kept synchronized with the system
758      * global Settings. Any access to this class or its fields should be done while
759      * holding the DeviceIdleController lock.
760      */
761     public final class Constants extends ContentObserver {
762         // Key names stored in the settings value.
763         private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
764                 = "light_after_inactive_to";
765         private static final String KEY_LIGHT_PRE_IDLE_TIMEOUT = "light_pre_idle_to";
766         private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
767         private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
768         private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
769         private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
770                 = "light_idle_maintenance_min_budget";
771         private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
772                 = "light_idle_maintenance_max_budget";
773         private static final String KEY_MIN_LIGHT_MAINTENANCE_TIME = "min_light_maintenance_time";
774         private static final String KEY_MIN_DEEP_MAINTENANCE_TIME = "min_deep_maintenance_time";
775         private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
776         private static final String KEY_SENSING_TIMEOUT = "sensing_to";
777         private static final String KEY_LOCATING_TIMEOUT = "locating_to";
778         private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
779         private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
780         private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
781         private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
782         private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
783         private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
784         private static final String KEY_QUICK_DOZE_DELAY_TIMEOUT = "quick_doze_delay_to";
785         private static final String KEY_IDLE_TIMEOUT = "idle_to";
786         private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
787         private static final String KEY_IDLE_FACTOR = "idle_factor";
788         private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
789         private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
790                 "max_temp_app_whitelist_duration";
791         private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
792                 "mms_temp_app_whitelist_duration";
793         private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
794                 "sms_temp_app_whitelist_duration";
795         private static final String KEY_NOTIFICATION_WHITELIST_DURATION =
796                 "notification_whitelist_duration";
797         /**
798          * Whether to wait for the user to unlock the device before causing screen-on to
799          * exit doze. Default = true
800          */
801         private static final String KEY_WAIT_FOR_UNLOCK = "wait_for_unlock";
802         private static final String KEY_PRE_IDLE_FACTOR_LONG =
803                 "pre_idle_factor_long";
804         private static final String KEY_PRE_IDLE_FACTOR_SHORT =
805                 "pre_idle_factor_short";
806 
807         /**
808          * This is the time, after becoming inactive, that we go in to the first
809          * light-weight idle mode.
810          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
811          * @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
812          */
813         public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
814 
815         /**
816          * This is amount of time we will wait from the point where we decide we would
817          * like to go idle until we actually do, while waiting for jobs and other current
818          * activity to finish.
819          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
820          * @see #KEY_LIGHT_PRE_IDLE_TIMEOUT
821          */
822         public long LIGHT_PRE_IDLE_TIMEOUT;
823 
824         /**
825          * This is the initial time that we will run in idle maintenance mode.
826          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
827          * @see #KEY_LIGHT_IDLE_TIMEOUT
828          */
829         public long LIGHT_IDLE_TIMEOUT;
830 
831         /**
832          * Scaling factor to apply to the light idle mode time each time we complete a cycle.
833          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
834          * @see #KEY_LIGHT_IDLE_FACTOR
835          */
836         public float LIGHT_IDLE_FACTOR;
837 
838         /**
839          * This is the maximum time we will run in idle maintenance mode.
840          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
841          * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
842          */
843         public long LIGHT_MAX_IDLE_TIMEOUT;
844 
845         /**
846          * This is the minimum amount of time we want to make available for maintenance mode
847          * when lightly idling.  That is, we will always have at least this amount of time
848          * available maintenance before timing out and cutting off maintenance mode.
849          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
850          * @see #KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
851          */
852         public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
853 
854         /**
855          * This is the maximum amount of time we want to make available for maintenance mode
856          * when lightly idling.  That is, if the system isn't using up its minimum maintenance
857          * budget and this time is being added to the budget reserve, this is the maximum
858          * reserve size we will allow to grow and thus the maximum amount of time we will
859          * allow for the maintenance window.
860          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
861          * @see #KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
862          */
863         public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
864 
865         /**
866          * This is the minimum amount of time that we will stay in maintenance mode after
867          * a light doze.  We have this minimum to allow various things to respond to switching
868          * in to maintenance mode and scheduling their work -- otherwise we may
869          * see there is nothing to do (no jobs pending) and go out of maintenance
870          * mode immediately.
871          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
872          * @see #KEY_MIN_LIGHT_MAINTENANCE_TIME
873          */
874         public long MIN_LIGHT_MAINTENANCE_TIME;
875 
876         /**
877          * This is the minimum amount of time that we will stay in maintenance mode after
878          * a full doze.  We have this minimum to allow various things to respond to switching
879          * in to maintenance mode and scheduling their work -- otherwise we may
880          * see there is nothing to do (no jobs pending) and go out of maintenance
881          * mode immediately.
882          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
883          * @see #KEY_MIN_DEEP_MAINTENANCE_TIME
884          */
885         public long MIN_DEEP_MAINTENANCE_TIME;
886 
887         /**
888          * This is the time, after becoming inactive, at which we start looking at the
889          * motion sensor to determine if the device is being left alone.  We don't do this
890          * immediately after going inactive just because we don't want to be continually running
891          * the motion sensor whenever the screen is off.
892          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
893          * @see #KEY_INACTIVE_TIMEOUT
894          */
895         public long INACTIVE_TIMEOUT;
896 
897         /**
898          * If we don't receive a callback from AnyMotion in this amount of time +
899          * {@link #LOCATING_TIMEOUT}, we will change from
900          * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
901          * will be ignored.
902          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
903          * @see #KEY_SENSING_TIMEOUT
904          */
905         public long SENSING_TIMEOUT;
906 
907         /**
908          * This is how long we will wait to try to get a good location fix before going in to
909          * idle mode.
910          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
911          * @see #KEY_LOCATING_TIMEOUT
912          */
913         public long LOCATING_TIMEOUT;
914 
915         /**
916          * The desired maximum accuracy (in meters) we consider the location to be good enough to go
917          * on to idle.  We will be trying to get an accuracy fix at least this good or until
918          * {@link #LOCATING_TIMEOUT} expires.
919          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
920          * @see #KEY_LOCATION_ACCURACY
921          */
922         public float LOCATION_ACCURACY;
923 
924         /**
925          * This is the time, after seeing motion, that we wait after becoming inactive from
926          * that until we start looking for motion again.
927          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
928          * @see #KEY_MOTION_INACTIVE_TIMEOUT
929          */
930         public long MOTION_INACTIVE_TIMEOUT;
931 
932         /**
933          * This is the time, after the inactive timeout elapses, that we will wait looking
934          * for motion until we truly consider the device to be idle.
935          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
936          * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
937          */
938         public long IDLE_AFTER_INACTIVE_TIMEOUT;
939 
940         /**
941          * This is the initial time, after being idle, that we will allow ourself to be back
942          * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
943          * idle.
944          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
945          * @see #KEY_IDLE_PENDING_TIMEOUT
946          */
947         public long IDLE_PENDING_TIMEOUT;
948 
949         /**
950          * Maximum pending idle timeout (time spent running) we will be allowed to use.
951          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
952          * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
953          */
954         public long MAX_IDLE_PENDING_TIMEOUT;
955 
956         /**
957          * Scaling factor to apply to current pending idle timeout each time we cycle through
958          * that state.
959          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
960          * @see #KEY_IDLE_PENDING_FACTOR
961          */
962         public float IDLE_PENDING_FACTOR;
963 
964         /**
965          * This is amount of time we will wait from the point where we go into
966          * STATE_QUICK_DOZE_DELAY until we actually go into STATE_IDLE, while waiting for jobs
967          * and other current activity to finish.
968          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
969          * @see #KEY_QUICK_DOZE_DELAY_TIMEOUT
970          */
971         public long QUICK_DOZE_DELAY_TIMEOUT;
972 
973         /**
974          * This is the initial time that we want to sit in the idle state before waking up
975          * again to return to pending idle and allowing normal work to run.
976          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
977          * @see #KEY_IDLE_TIMEOUT
978          */
979         public long IDLE_TIMEOUT;
980 
981         /**
982          * Maximum idle duration we will be allowed to use.
983          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
984          * @see #KEY_MAX_IDLE_TIMEOUT
985          */
986         public long MAX_IDLE_TIMEOUT;
987 
988         /**
989          * Scaling factor to apply to current idle timeout each time we cycle through that state.
990           * @see Settings.Global#DEVICE_IDLE_CONSTANTS
991          * @see #KEY_IDLE_FACTOR
992          */
993         public float IDLE_FACTOR;
994 
995         /**
996          * This is the minimum time we will allow until the next upcoming alarm for us to
997          * actually go in to idle mode.
998          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
999          * @see #KEY_MIN_TIME_TO_ALARM
1000          */
1001         public long MIN_TIME_TO_ALARM;
1002 
1003         /**
1004          * Max amount of time to temporarily whitelist an app when it receives a high priority
1005          * tickle.
1006          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1007          * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
1008          */
1009         public long MAX_TEMP_APP_WHITELIST_DURATION;
1010 
1011         /**
1012          * Amount of time we would like to whitelist an app that is receiving an MMS.
1013          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1014          * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
1015          */
1016         public long MMS_TEMP_APP_WHITELIST_DURATION;
1017 
1018         /**
1019          * Amount of time we would like to whitelist an app that is receiving an SMS.
1020          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1021          * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
1022          */
1023         public long SMS_TEMP_APP_WHITELIST_DURATION;
1024 
1025         /**
1026          * Amount of time we would like to whitelist an app that is handling a
1027          * {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}.
1028          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
1029          * @see #KEY_NOTIFICATION_WHITELIST_DURATION
1030          */
1031         public long NOTIFICATION_WHITELIST_DURATION;
1032 
1033         /**
1034          * Pre idle time factor use to make idle delay longer
1035          */
1036         public float PRE_IDLE_FACTOR_LONG;
1037 
1038         /**
1039          * Pre idle time factor use to make idle delay shorter
1040          */
1041         public float PRE_IDLE_FACTOR_SHORT;
1042 
1043         public boolean WAIT_FOR_UNLOCK;
1044 
1045         private final ContentResolver mResolver;
1046         private final boolean mSmallBatteryDevice;
1047         private final KeyValueListParser mParser = new KeyValueListParser(',');
1048 
Constants(Handler handler, ContentResolver resolver)1049         public Constants(Handler handler, ContentResolver resolver) {
1050             super(handler);
1051             mResolver = resolver;
1052             mSmallBatteryDevice = ActivityManager.isSmallBatteryDevice();
1053             mResolver.registerContentObserver(
1054                     Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS),
1055                     false, this);
1056             updateConstants();
1057         }
1058 
1059         @Override
onChange(boolean selfChange, Uri uri)1060         public void onChange(boolean selfChange, Uri uri) {
1061             updateConstants();
1062         }
1063 
updateConstants()1064         private void updateConstants() {
1065             synchronized (DeviceIdleController.this) {
1066                 try {
1067                     mParser.setString(Settings.Global.getString(mResolver,
1068                             Settings.Global.DEVICE_IDLE_CONSTANTS));
1069                 } catch (IllegalArgumentException e) {
1070                     // Failed to parse the settings string, log this and move on
1071                     // with defaults.
1072                     Slog.e(TAG, "Bad device idle settings", e);
1073                 }
1074 
1075                 LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
1076                         KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
1077                         !COMPRESS_TIME ? 3 * 60 * 1000L : 15 * 1000L);
1078                 LIGHT_PRE_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_PRE_IDLE_TIMEOUT,
1079                         !COMPRESS_TIME ? 3 * 60 * 1000L : 30 * 1000L);
1080                 LIGHT_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_IDLE_TIMEOUT,
1081                         !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
1082                 LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR,
1083                         2f);
1084                 LIGHT_MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_MAX_IDLE_TIMEOUT,
1085                         !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
1086                 LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getDurationMillis(
1087                         KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
1088                         !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
1089                 LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getDurationMillis(
1090                         KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET,
1091                         !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
1092                 MIN_LIGHT_MAINTENANCE_TIME = mParser.getDurationMillis(
1093                         KEY_MIN_LIGHT_MAINTENANCE_TIME,
1094                         !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L);
1095                 MIN_DEEP_MAINTENANCE_TIME = mParser.getDurationMillis(
1096                         KEY_MIN_DEEP_MAINTENANCE_TIME,
1097                         !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L);
1098                 long inactiveTimeoutDefault = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
1099                 INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_INACTIVE_TIMEOUT,
1100                         !COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10));
1101                 SENSING_TIMEOUT = mParser.getDurationMillis(KEY_SENSING_TIMEOUT,
1102                         !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L);
1103                 LOCATING_TIMEOUT = mParser.getDurationMillis(KEY_LOCATING_TIMEOUT,
1104                         !COMPRESS_TIME ? 30 * 1000L : 15 * 1000L);
1105                 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
1106                 MOTION_INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_MOTION_INACTIVE_TIMEOUT,
1107                         !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
1108                 long idleAfterInactiveTimeout = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
1109                 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
1110                         KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
1111                         !COMPRESS_TIME ? idleAfterInactiveTimeout
1112                                        : (idleAfterInactiveTimeout / 10));
1113                 IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_PENDING_TIMEOUT,
1114                         !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
1115                 MAX_IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_PENDING_TIMEOUT,
1116                         !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
1117                 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
1118                         2f);
1119                 QUICK_DOZE_DELAY_TIMEOUT = mParser.getDurationMillis(
1120                         KEY_QUICK_DOZE_DELAY_TIMEOUT, !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L);
1121                 IDLE_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_TIMEOUT,
1122                         !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
1123                 MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_TIMEOUT,
1124                         !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
1125                 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
1126                         2f);
1127                 MIN_TIME_TO_ALARM = mParser.getDurationMillis(KEY_MIN_TIME_TO_ALARM,
1128                         !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
1129                 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
1130                         KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
1131                 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
1132                         KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
1133                 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
1134                         KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
1135                 NOTIFICATION_WHITELIST_DURATION = mParser.getDurationMillis(
1136                         KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L);
1137                 WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, true);
1138                 PRE_IDLE_FACTOR_LONG = mParser.getFloat(KEY_PRE_IDLE_FACTOR_LONG, 1.67f);
1139                 PRE_IDLE_FACTOR_SHORT = mParser.getFloat(KEY_PRE_IDLE_FACTOR_SHORT, 0.33f);
1140             }
1141         }
1142 
dump(PrintWriter pw)1143         void dump(PrintWriter pw) {
1144             pw.println("  Settings:");
1145 
1146             pw.print("    "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
1147             TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw);
1148             pw.println();
1149 
1150             pw.print("    "); pw.print(KEY_LIGHT_PRE_IDLE_TIMEOUT); pw.print("=");
1151             TimeUtils.formatDuration(LIGHT_PRE_IDLE_TIMEOUT, pw);
1152             pw.println();
1153 
1154             pw.print("    "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
1155             TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
1156             pw.println();
1157 
1158             pw.print("    "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("=");
1159             pw.print(LIGHT_IDLE_FACTOR);
1160             pw.println();
1161 
1162             pw.print("    "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT); pw.print("=");
1163             TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT, pw);
1164             pw.println();
1165 
1166             pw.print("    "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); pw.print("=");
1167             TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, pw);
1168             pw.println();
1169 
1170             pw.print("    "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET); pw.print("=");
1171             TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, pw);
1172             pw.println();
1173 
1174             pw.print("    "); pw.print(KEY_MIN_LIGHT_MAINTENANCE_TIME); pw.print("=");
1175             TimeUtils.formatDuration(MIN_LIGHT_MAINTENANCE_TIME, pw);
1176             pw.println();
1177 
1178             pw.print("    "); pw.print(KEY_MIN_DEEP_MAINTENANCE_TIME); pw.print("=");
1179             TimeUtils.formatDuration(MIN_DEEP_MAINTENANCE_TIME, pw);
1180             pw.println();
1181 
1182             pw.print("    "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
1183             TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
1184             pw.println();
1185 
1186             pw.print("    "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
1187             TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
1188             pw.println();
1189 
1190             pw.print("    "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
1191             TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
1192             pw.println();
1193 
1194             pw.print("    "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
1195             pw.print(LOCATION_ACCURACY); pw.print("m");
1196             pw.println();
1197 
1198             pw.print("    "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
1199             TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
1200             pw.println();
1201 
1202             pw.print("    "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
1203             TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
1204             pw.println();
1205 
1206             pw.print("    "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
1207             TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
1208             pw.println();
1209 
1210             pw.print("    "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
1211             TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
1212             pw.println();
1213 
1214             pw.print("    "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
1215             pw.println(IDLE_PENDING_FACTOR);
1216 
1217             pw.print("    "); pw.print(KEY_QUICK_DOZE_DELAY_TIMEOUT); pw.print("=");
1218             TimeUtils.formatDuration(QUICK_DOZE_DELAY_TIMEOUT, pw);
1219             pw.println();
1220 
1221             pw.print("    "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
1222             TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
1223             pw.println();
1224 
1225             pw.print("    "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
1226             TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
1227             pw.println();
1228 
1229             pw.print("    "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
1230             pw.println(IDLE_FACTOR);
1231 
1232             pw.print("    "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
1233             TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
1234             pw.println();
1235 
1236             pw.print("    "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
1237             TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
1238             pw.println();
1239 
1240             pw.print("    "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
1241             TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
1242             pw.println();
1243 
1244             pw.print("    "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
1245             TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
1246             pw.println();
1247 
1248             pw.print("    "); pw.print(KEY_NOTIFICATION_WHITELIST_DURATION); pw.print("=");
1249             TimeUtils.formatDuration(NOTIFICATION_WHITELIST_DURATION, pw);
1250             pw.println();
1251 
1252             pw.print("    "); pw.print(KEY_WAIT_FOR_UNLOCK); pw.print("=");
1253             pw.println(WAIT_FOR_UNLOCK);
1254 
1255             pw.print("    "); pw.print(KEY_PRE_IDLE_FACTOR_LONG); pw.print("=");
1256             pw.println(PRE_IDLE_FACTOR_LONG);
1257 
1258             pw.print("    "); pw.print(KEY_PRE_IDLE_FACTOR_SHORT); pw.print("=");
1259             pw.println(PRE_IDLE_FACTOR_SHORT);
1260         }
1261     }
1262 
1263     private Constants mConstants;
1264 
1265     @Override
onAnyMotionResult(int result)1266     public void onAnyMotionResult(int result) {
1267         if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
1268         if (result != AnyMotionDetector.RESULT_UNKNOWN) {
1269             synchronized (this) {
1270                 cancelSensingTimeoutAlarmLocked();
1271             }
1272         }
1273         if ((result == AnyMotionDetector.RESULT_MOVED) ||
1274             (result == AnyMotionDetector.RESULT_UNKNOWN)) {
1275             synchronized (this) {
1276                 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
1277             }
1278         } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
1279             if (mState == STATE_SENSING) {
1280                 // If we are currently sensing, it is time to move to locating.
1281                 synchronized (this) {
1282                     mNotMoving = true;
1283                     stepIdleStateLocked("s:stationary");
1284                 }
1285             } else if (mState == STATE_LOCATING) {
1286                 // If we are currently locating, note that we are not moving and step
1287                 // if we have located the position.
1288                 synchronized (this) {
1289                     mNotMoving = true;
1290                     if (mLocated) {
1291                         stepIdleStateLocked("s:stationary");
1292                     }
1293                 }
1294             }
1295         }
1296     }
1297 
1298     private static final int MSG_WRITE_CONFIG = 1;
1299     private static final int MSG_REPORT_IDLE_ON = 2;
1300     private static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
1301     private static final int MSG_REPORT_IDLE_OFF = 4;
1302     private static final int MSG_REPORT_ACTIVE = 5;
1303     private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
1304     private static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
1305     private static final int MSG_FINISH_IDLE_OP = 8;
1306     private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 9;
1307     private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
1308     private static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
1309     private static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
1310 
1311     final class MyHandler extends Handler {
MyHandler(Looper looper)1312         MyHandler(Looper looper) {
1313             super(looper);
1314         }
1315 
handleMessage(Message msg)1316         @Override public void handleMessage(Message msg) {
1317             if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
1318             switch (msg.what) {
1319                 case MSG_WRITE_CONFIG: {
1320                     // Does not hold a wakelock. Just let this happen whenever.
1321                     handleWriteConfigFile();
1322                 } break;
1323                 case MSG_REPORT_IDLE_ON:
1324                 case MSG_REPORT_IDLE_ON_LIGHT: {
1325                     // mGoingIdleWakeLock is held at this point
1326                     EventLogTags.writeDeviceIdleOnStart();
1327                     final boolean deepChanged;
1328                     final boolean lightChanged;
1329                     if (msg.what == MSG_REPORT_IDLE_ON) {
1330                         deepChanged = mLocalPowerManager.setDeviceIdleMode(true);
1331                         lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1332                     } else {
1333                         deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1334                         lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
1335                     }
1336                     try {
1337                         mNetworkPolicyManager.setDeviceIdleMode(true);
1338                         mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON
1339                                 ? BatteryStats.DEVICE_IDLE_MODE_DEEP
1340                                 : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
1341                     } catch (RemoteException e) {
1342                     }
1343                     if (deepChanged) {
1344                         getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1345                     }
1346                     if (lightChanged) {
1347                         getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1348                     }
1349                     EventLogTags.writeDeviceIdleOnComplete();
1350                     mGoingIdleWakeLock.release();
1351                 } break;
1352                 case MSG_REPORT_IDLE_OFF: {
1353                     // mActiveIdleWakeLock is held at this point
1354                     EventLogTags.writeDeviceIdleOffStart("unknown");
1355                     final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1356                     final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1357                     try {
1358                         mNetworkPolicyManager.setDeviceIdleMode(false);
1359                         mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1360                                 null, Process.myUid());
1361                     } catch (RemoteException e) {
1362                     }
1363                     if (deepChanged) {
1364                         incActiveIdleOps();
1365                         getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL,
1366                                 null, mIdleStartedDoneReceiver, null, 0, null, null);
1367                     }
1368                     if (lightChanged) {
1369                         incActiveIdleOps();
1370                         getContext().sendOrderedBroadcastAsUser(mLightIdleIntent, UserHandle.ALL,
1371                                 null, mIdleStartedDoneReceiver, null, 0, null, null);
1372                     }
1373                     // Always start with one active op for the message being sent here.
1374                     // Now we are done!
1375                     decActiveIdleOps();
1376                     EventLogTags.writeDeviceIdleOffComplete();
1377                 } break;
1378                 case MSG_REPORT_ACTIVE: {
1379                     // The device is awake at this point, so no wakelock necessary.
1380                     String activeReason = (String)msg.obj;
1381                     int activeUid = msg.arg1;
1382                     EventLogTags.writeDeviceIdleOffStart(
1383                             activeReason != null ? activeReason : "unknown");
1384                     final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1385                     final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1386                     try {
1387                         mNetworkPolicyManager.setDeviceIdleMode(false);
1388                         mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1389                                 activeReason, activeUid);
1390                     } catch (RemoteException e) {
1391                     }
1392                     if (deepChanged) {
1393                         getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1394                     }
1395                     if (lightChanged) {
1396                         getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1397                     }
1398                     EventLogTags.writeDeviceIdleOffComplete();
1399                 } break;
1400                 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
1401                     // TODO: What is keeping the device awake at this point? Does it need to be?
1402                     int appId = msg.arg1;
1403                     checkTempAppWhitelistTimeout(appId);
1404                 } break;
1405                 case MSG_REPORT_MAINTENANCE_ACTIVITY: {
1406                     // TODO: What is keeping the device awake at this point? Does it need to be?
1407                     boolean active = (msg.arg1 == 1);
1408                     final int size = mMaintenanceActivityListeners.beginBroadcast();
1409                     try {
1410                         for (int i = 0; i < size; i++) {
1411                             try {
1412                                 mMaintenanceActivityListeners.getBroadcastItem(i)
1413                                         .onMaintenanceActivityChanged(active);
1414                             } catch (RemoteException ignored) {
1415                             }
1416                         }
1417                     } finally {
1418                         mMaintenanceActivityListeners.finishBroadcast();
1419                     }
1420                 } break;
1421                 case MSG_FINISH_IDLE_OP: {
1422                     // mActiveIdleWakeLock is held at this point
1423                     decActiveIdleOps();
1424                 } break;
1425                 case MSG_REPORT_TEMP_APP_WHITELIST_CHANGED: {
1426                     final int appId = msg.arg1;
1427                     final boolean added = (msg.arg2 == 1);
1428                     mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, added);
1429                 } break;
1430                 case MSG_SEND_CONSTRAINT_MONITORING: {
1431                     final IDeviceIdleConstraint constraint = (IDeviceIdleConstraint) msg.obj;
1432                     final boolean monitoring = (msg.arg1 == 1);
1433                     if (monitoring) {
1434                         constraint.startMonitoring();
1435                     } else {
1436                         constraint.stopMonitoring();
1437                     }
1438                 } break;
1439                 case MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR: {
1440                     updatePreIdleFactor();
1441                 } break;
1442                 case MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR: {
1443                     updatePreIdleFactor();
1444                     maybeDoImmediateMaintenance();
1445                 } break;
1446             }
1447         }
1448     }
1449 
1450     final MyHandler mHandler;
1451 
1452     BinderService mBinderService;
1453 
1454     private final class BinderService extends IDeviceIdleController.Stub {
addPowerSaveWhitelistApp(String name)1455         @Override public void addPowerSaveWhitelistApp(String name) {
1456             if (DEBUG) {
1457                 Slog.i(TAG, "addPowerSaveWhitelistApp(name = " + name + ")");
1458             }
1459             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1460                     null);
1461             long ident = Binder.clearCallingIdentity();
1462             try {
1463                 addPowerSaveWhitelistAppInternal(name);
1464             } finally {
1465                 Binder.restoreCallingIdentity(ident);
1466             }
1467         }
1468 
removePowerSaveWhitelistApp(String name)1469         @Override public void removePowerSaveWhitelistApp(String name) {
1470             if (DEBUG) {
1471                 Slog.i(TAG, "removePowerSaveWhitelistApp(name = " + name + ")");
1472             }
1473             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1474                     null);
1475             long ident = Binder.clearCallingIdentity();
1476             try {
1477                 removePowerSaveWhitelistAppInternal(name);
1478             } finally {
1479                 Binder.restoreCallingIdentity(ident);
1480             }
1481         }
1482 
removeSystemPowerWhitelistApp(String name)1483         @Override public void removeSystemPowerWhitelistApp(String name) {
1484             if (DEBUG) {
1485                 Slog.d(TAG, "removeAppFromSystemWhitelist(name = " + name + ")");
1486             }
1487             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1488                     null);
1489             long ident = Binder.clearCallingIdentity();
1490             try {
1491                 removeSystemPowerWhitelistAppInternal(name);
1492             } finally {
1493                 Binder.restoreCallingIdentity(ident);
1494             }
1495         }
1496 
restoreSystemPowerWhitelistApp(String name)1497         @Override public void restoreSystemPowerWhitelistApp(String name) {
1498             if (DEBUG) {
1499                 Slog.d(TAG, "restoreAppToSystemWhitelist(name = " + name + ")");
1500             }
1501             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1502                     null);
1503             long ident = Binder.clearCallingIdentity();
1504             try {
1505                 restoreSystemPowerWhitelistAppInternal(name);
1506             } finally {
1507                 Binder.restoreCallingIdentity(ident);
1508             }
1509         }
1510 
getRemovedSystemPowerWhitelistApps()1511         public String[] getRemovedSystemPowerWhitelistApps() {
1512             return getRemovedSystemPowerWhitelistAppsInternal();
1513         }
1514 
getSystemPowerWhitelistExceptIdle()1515         @Override public String[] getSystemPowerWhitelistExceptIdle() {
1516             return getSystemPowerWhitelistExceptIdleInternal();
1517         }
1518 
getSystemPowerWhitelist()1519         @Override public String[] getSystemPowerWhitelist() {
1520             return getSystemPowerWhitelistInternal();
1521         }
1522 
getUserPowerWhitelist()1523         @Override public String[] getUserPowerWhitelist() {
1524             return getUserPowerWhitelistInternal();
1525         }
1526 
getFullPowerWhitelistExceptIdle()1527         @Override public String[] getFullPowerWhitelistExceptIdle() {
1528             return getFullPowerWhitelistExceptIdleInternal();
1529         }
1530 
getFullPowerWhitelist()1531         @Override public String[] getFullPowerWhitelist() {
1532             return getFullPowerWhitelistInternal();
1533         }
1534 
getAppIdWhitelistExceptIdle()1535         @Override public int[] getAppIdWhitelistExceptIdle() {
1536             return getAppIdWhitelistExceptIdleInternal();
1537         }
1538 
getAppIdWhitelist()1539         @Override public int[] getAppIdWhitelist() {
1540             return getAppIdWhitelistInternal();
1541         }
1542 
getAppIdUserWhitelist()1543         @Override public int[] getAppIdUserWhitelist() {
1544             return getAppIdUserWhitelistInternal();
1545         }
1546 
getAppIdTempWhitelist()1547         @Override public int[] getAppIdTempWhitelist() {
1548             return getAppIdTempWhitelistInternal();
1549         }
1550 
isPowerSaveWhitelistExceptIdleApp(String name)1551         @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
1552             return isPowerSaveWhitelistExceptIdleAppInternal(name);
1553         }
1554 
isPowerSaveWhitelistApp(String name)1555         @Override public boolean isPowerSaveWhitelistApp(String name) {
1556             return isPowerSaveWhitelistAppInternal(name);
1557         }
1558 
addPowerSaveTempWhitelistApp(String packageName, long duration, int userId, String reason)1559         @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
1560                 int userId, String reason) throws RemoteException {
1561             addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1562         }
1563 
addPowerSaveTempWhitelistAppForMms(String packageName, int userId, String reason)1564         @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
1565                 int userId, String reason) throws RemoteException {
1566             long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
1567             addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1568             return duration;
1569         }
1570 
addPowerSaveTempWhitelistAppForSms(String packageName, int userId, String reason)1571         @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
1572                 int userId, String reason) throws RemoteException {
1573             long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
1574             addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1575             return duration;
1576         }
1577 
exitIdle(String reason)1578         @Override public void exitIdle(String reason) {
1579             getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1580                     null);
1581             long ident = Binder.clearCallingIdentity();
1582             try {
1583                 exitIdleInternal(reason);
1584             } finally {
1585                 Binder.restoreCallingIdentity(ident);
1586             }
1587         }
1588 
registerMaintenanceActivityListener( IMaintenanceActivityListener listener)1589         @Override public boolean registerMaintenanceActivityListener(
1590                 IMaintenanceActivityListener listener) {
1591             return DeviceIdleController.this.registerMaintenanceActivityListener(listener);
1592         }
1593 
unregisterMaintenanceActivityListener( IMaintenanceActivityListener listener)1594         @Override public void unregisterMaintenanceActivityListener(
1595                 IMaintenanceActivityListener listener) {
1596             DeviceIdleController.this.unregisterMaintenanceActivityListener(listener);
1597         }
1598 
setPreIdleTimeoutMode(int mode)1599         @Override public int setPreIdleTimeoutMode(int mode) {
1600             getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1601                     null);
1602             long ident = Binder.clearCallingIdentity();
1603             try {
1604                 return DeviceIdleController.this.setPreIdleTimeoutMode(mode);
1605             } finally {
1606                 Binder.restoreCallingIdentity(ident);
1607             }
1608         }
1609 
resetPreIdleTimeoutMode()1610         @Override public void resetPreIdleTimeoutMode() {
1611             getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1612                     null);
1613             long ident = Binder.clearCallingIdentity();
1614             try {
1615                 DeviceIdleController.this.resetPreIdleTimeoutMode();
1616             } finally {
1617                 Binder.restoreCallingIdentity(ident);
1618             }
1619         }
1620 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1621         @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1622             DeviceIdleController.this.dump(fd, pw, args);
1623         }
1624 
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)1625         @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
1626                 FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
1627             (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
1628         }
1629     }
1630 
1631     public class LocalService {
onConstraintStateChanged(IDeviceIdleConstraint constraint, boolean active)1632         public void onConstraintStateChanged(IDeviceIdleConstraint constraint, boolean active) {
1633             synchronized (DeviceIdleController.this) {
1634                 onConstraintStateChangedLocked(constraint, active);
1635             }
1636         }
1637 
registerDeviceIdleConstraint(IDeviceIdleConstraint constraint, String name, @IDeviceIdleConstraint.MinimumState int minState)1638         public void registerDeviceIdleConstraint(IDeviceIdleConstraint constraint, String name,
1639                 @IDeviceIdleConstraint.MinimumState int minState) {
1640             registerDeviceIdleConstraintInternal(constraint, name, minState);
1641         }
1642 
unregisterDeviceIdleConstraint(IDeviceIdleConstraint constraint)1643         public void unregisterDeviceIdleConstraint(IDeviceIdleConstraint constraint) {
1644             unregisterDeviceIdleConstraintInternal(constraint);
1645         }
1646 
exitIdle(String reason)1647         public void exitIdle(String reason) {
1648             exitIdleInternal(reason);
1649         }
1650 
1651         // duration in milliseconds
addPowerSaveTempWhitelistApp(int callingUid, String packageName, long duration, int userId, boolean sync, String reason)1652         public void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
1653                 long duration, int userId, boolean sync, String reason) {
1654             addPowerSaveTempWhitelistAppInternal(callingUid, packageName, duration,
1655                     userId, sync, reason);
1656         }
1657 
1658         // duration in milliseconds
addPowerSaveTempWhitelistAppDirect(int uid, long duration, boolean sync, String reason)1659         public void addPowerSaveTempWhitelistAppDirect(int uid, long duration, boolean sync,
1660                 String reason) {
1661             addPowerSaveTempWhitelistAppDirectInternal(0, uid, duration, sync, reason);
1662         }
1663 
1664         // duration in milliseconds
getNotificationWhitelistDuration()1665         public long getNotificationWhitelistDuration() {
1666             return mConstants.NOTIFICATION_WHITELIST_DURATION;
1667         }
1668 
setJobsActive(boolean active)1669         public void setJobsActive(boolean active) {
1670             DeviceIdleController.this.setJobsActive(active);
1671         }
1672 
1673         // Up-call from alarm manager.
setAlarmsActive(boolean active)1674         public void setAlarmsActive(boolean active) {
1675             DeviceIdleController.this.setAlarmsActive(active);
1676         }
1677 
1678         /** Is the app on any of the power save whitelists, whether system or user? */
isAppOnWhitelist(int appid)1679         public boolean isAppOnWhitelist(int appid) {
1680             return DeviceIdleController.this.isAppOnWhitelistInternal(appid);
1681         }
1682 
1683         /**
1684          * Returns the array of app ids whitelisted by user. Take care not to
1685          * modify this, as it is a reference to the original copy. But the reference
1686          * can change when the list changes, so it needs to be re-acquired when
1687          * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent.
1688          */
getPowerSaveWhitelistUserAppIds()1689         public int[] getPowerSaveWhitelistUserAppIds() {
1690             return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
1691         }
1692 
getPowerSaveTempWhitelistAppIds()1693         public int[] getPowerSaveTempWhitelistAppIds() {
1694             return DeviceIdleController.this.getAppIdTempWhitelistInternal();
1695         }
1696     }
1697 
1698     static class Injector {
1699         private final Context mContext;
1700         private ConnectivityService mConnectivityService;
1701         private Constants mConstants;
1702         private LocationManager mLocationManager;
1703 
Injector(Context ctx)1704         Injector(Context ctx) {
1705             mContext = ctx;
1706         }
1707 
getAlarmManager()1708         AlarmManager getAlarmManager() {
1709             return mContext.getSystemService(AlarmManager.class);
1710         }
1711 
getAnyMotionDetector(Handler handler, SensorManager sm, AnyMotionDetector.DeviceIdleCallback callback, float angleThreshold)1712         AnyMotionDetector getAnyMotionDetector(Handler handler, SensorManager sm,
1713                 AnyMotionDetector.DeviceIdleCallback callback, float angleThreshold) {
1714             return new AnyMotionDetector(getPowerManager(), handler, sm, callback, angleThreshold);
1715         }
1716 
getAppStateTracker(Context ctx, Looper looper)1717         AppStateTracker getAppStateTracker(Context ctx, Looper looper) {
1718             return new AppStateTracker(ctx, looper);
1719         }
1720 
getConnectivityService()1721         ConnectivityService getConnectivityService() {
1722             if (mConnectivityService == null) {
1723                 mConnectivityService = (ConnectivityService) ServiceManager.getService(
1724                         Context.CONNECTIVITY_SERVICE);
1725             }
1726             return mConnectivityService;
1727         }
1728 
getConstants(DeviceIdleController controller, Handler handler, ContentResolver resolver)1729         Constants getConstants(DeviceIdleController controller, Handler handler,
1730                 ContentResolver resolver) {
1731             if (mConstants == null) {
1732                 mConstants = controller.new Constants(handler, resolver);
1733             }
1734             return mConstants;
1735         }
1736 
getLocationManager()1737         LocationManager getLocationManager() {
1738             if (mLocationManager == null) {
1739                 mLocationManager = mContext.getSystemService(LocationManager.class);
1740             }
1741             return mLocationManager;
1742         }
1743 
getHandler(DeviceIdleController controller)1744         MyHandler getHandler(DeviceIdleController controller) {
1745             return controller.new MyHandler(BackgroundThread.getHandler().getLooper());
1746         }
1747 
getPowerManager()1748         PowerManager getPowerManager() {
1749             return mContext.getSystemService(PowerManager.class);
1750         }
1751 
getSensorManager()1752         SensorManager getSensorManager() {
1753             return mContext.getSystemService(SensorManager.class);
1754         }
1755 
getConstraintController(Handler handler, LocalService localService)1756         ConstraintController getConstraintController(Handler handler, LocalService localService) {
1757             if (mContext.getPackageManager()
1758                     .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
1759                 return new TvConstraintController(mContext, handler);
1760             }
1761             return null;
1762         }
1763 
useMotionSensor()1764         boolean useMotionSensor() {
1765             return mContext.getResources().getBoolean(
1766                    com.android.internal.R.bool.config_autoPowerModeUseMotionSensor);
1767         }
1768     }
1769 
1770     private final Injector mInjector;
1771 
1772     private ActivityTaskManagerInternal.ScreenObserver mScreenObserver =
1773             new ActivityTaskManagerInternal.ScreenObserver() {
1774                 @Override
1775                 public void onAwakeStateChanged(boolean isAwake) { }
1776 
1777                 @Override
1778                 public void onKeyguardStateChanged(boolean isShowing) {
1779                     synchronized (DeviceIdleController.this) {
1780                         DeviceIdleController.this.keyguardShowingLocked(isShowing);
1781                     }
1782                 }
1783             };
1784 
DeviceIdleController(Context context, Injector injector)1785     @VisibleForTesting DeviceIdleController(Context context, Injector injector) {
1786         super(context);
1787         mInjector = injector;
1788         mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
1789         mHandler = mInjector.getHandler(this);
1790         mAppStateTracker = mInjector.getAppStateTracker(context, FgThread.get().getLooper());
1791         LocalServices.addService(AppStateTracker.class, mAppStateTracker);
1792         mUseMotionSensor = mInjector.useMotionSensor();
1793     }
1794 
DeviceIdleController(Context context)1795     public DeviceIdleController(Context context) {
1796         this(context, new Injector(context));
1797     }
1798 
isAppOnWhitelistInternal(int appid)1799     boolean isAppOnWhitelistInternal(int appid) {
1800         synchronized (this) {
1801             return Arrays.binarySearch(mPowerSaveWhitelistAllAppIdArray, appid) >= 0;
1802         }
1803     }
1804 
getPowerSaveWhitelistUserAppIds()1805     int[] getPowerSaveWhitelistUserAppIds() {
1806         synchronized (this) {
1807             return mPowerSaveWhitelistUserAppIdArray;
1808         }
1809     }
1810 
getSystemDir()1811     private static File getSystemDir() {
1812         return new File(Environment.getDataDirectory(), "system");
1813     }
1814 
1815     @Override
onStart()1816     public void onStart() {
1817         final PackageManager pm = getContext().getPackageManager();
1818 
1819         synchronized (this) {
1820             mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean(
1821                     com.android.internal.R.bool.config_enableAutoPowerModes);
1822             SystemConfig sysConfig = SystemConfig.getInstance();
1823             ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
1824             for (int i=0; i<allowPowerExceptIdle.size(); i++) {
1825                 String pkg = allowPowerExceptIdle.valueAt(i);
1826                 try {
1827                     ApplicationInfo ai = pm.getApplicationInfo(pkg,
1828                             PackageManager.MATCH_SYSTEM_ONLY);
1829                     int appid = UserHandle.getAppId(ai.uid);
1830                     mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
1831                     mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
1832                 } catch (PackageManager.NameNotFoundException e) {
1833                 }
1834             }
1835             ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
1836             for (int i=0; i<allowPower.size(); i++) {
1837                 String pkg = allowPower.valueAt(i);
1838                 try {
1839                     ApplicationInfo ai = pm.getApplicationInfo(pkg,
1840                             PackageManager.MATCH_SYSTEM_ONLY);
1841                     int appid = UserHandle.getAppId(ai.uid);
1842                     // These apps are on both the whitelist-except-idle as well
1843                     // as the full whitelist, so they apply in all cases.
1844                     mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
1845                     mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
1846                     mPowerSaveWhitelistApps.put(ai.packageName, appid);
1847                     mPowerSaveWhitelistSystemAppIds.put(appid, true);
1848                 } catch (PackageManager.NameNotFoundException e) {
1849                 }
1850             }
1851 
1852             mConstants = mInjector.getConstants(this, mHandler, getContext().getContentResolver());
1853 
1854             readConfigFileLocked();
1855             updateWhitelistAppIdsLocked();
1856 
1857             mNetworkConnected = true;
1858             mScreenOn = true;
1859             mScreenLocked = false;
1860             // Start out assuming we are charging.  If we aren't, we will at least get
1861             // a battery update the next time the level drops.
1862             mCharging = true;
1863             mActiveReason = ACTIVE_REASON_UNKNOWN;
1864             mState = STATE_ACTIVE;
1865             mLightState = LIGHT_STATE_ACTIVE;
1866             mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
1867             mPreIdleFactor = 1.0f;
1868             mLastPreIdleFactor = 1.0f;
1869         }
1870 
1871         mBinderService = new BinderService();
1872         publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);
1873         publishLocalService(LocalService.class, new LocalService());
1874     }
1875 
1876     @Override
onBootPhase(int phase)1877     public void onBootPhase(int phase) {
1878         if (phase == PHASE_SYSTEM_SERVICES_READY) {
1879             synchronized (this) {
1880                 mAlarmManager = mInjector.getAlarmManager();
1881                 mLocalAlarmManager = getLocalService(AlarmManagerInternal.class);
1882                 mBatteryStats = BatteryStatsService.getService();
1883                 mLocalActivityManager = getLocalService(ActivityManagerInternal.class);
1884                 mLocalActivityTaskManager = getLocalService(ActivityTaskManagerInternal.class);
1885                 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
1886                 mPowerManager = mInjector.getPowerManager();
1887                 mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1888                         "deviceidle_maint");
1889                 mActiveIdleWakeLock.setReferenceCounted(false);
1890                 mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1891                         "deviceidle_going_idle");
1892                 mGoingIdleWakeLock.setReferenceCounted(true);
1893                 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
1894                         ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
1895                 mNetworkPolicyManagerInternal = getLocalService(NetworkPolicyManagerInternal.class);
1896                 mSensorManager = mInjector.getSensorManager();
1897 
1898                 if (mUseMotionSensor) {
1899                     int sigMotionSensorId = getContext().getResources().getInteger(
1900                             com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
1901                     if (sigMotionSensorId > 0) {
1902                         mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
1903                     }
1904                     if (mMotionSensor == null && getContext().getResources().getBoolean(
1905                             com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
1906                         mMotionSensor = mSensorManager.getDefaultSensor(
1907                                 Sensor.TYPE_WRIST_TILT_GESTURE, true);
1908                     }
1909                     if (mMotionSensor == null) {
1910                         // As a last ditch, fall back to SMD.
1911                         mMotionSensor = mSensorManager.getDefaultSensor(
1912                                 Sensor.TYPE_SIGNIFICANT_MOTION, true);
1913                     }
1914                 }
1915 
1916                 if (getContext().getResources().getBoolean(
1917                         com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
1918                     mLocationRequest = new LocationRequest()
1919                         .setQuality(LocationRequest.ACCURACY_FINE)
1920                         .setInterval(0)
1921                         .setFastestInterval(0)
1922                         .setNumUpdates(1);
1923                 }
1924 
1925                 mConstraintController = mInjector.getConstraintController(
1926                         mHandler, getLocalService(LocalService.class));
1927                 if (mConstraintController != null) {
1928                     mConstraintController.start();
1929                 }
1930 
1931                 float angleThreshold = getContext().getResources().getInteger(
1932                         com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
1933                 mAnyMotionDetector = mInjector.getAnyMotionDetector(mHandler, mSensorManager, this,
1934                         angleThreshold);
1935 
1936                 mAppStateTracker.onSystemServicesReady();
1937 
1938                 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
1939                 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1940                         | Intent.FLAG_RECEIVER_FOREGROUND);
1941                 mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
1942                 mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1943                         | Intent.FLAG_RECEIVER_FOREGROUND);
1944 
1945                 IntentFilter filter = new IntentFilter();
1946                 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
1947                 getContext().registerReceiver(mReceiver, filter);
1948 
1949                 filter = new IntentFilter();
1950                 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
1951                 filter.addDataScheme("package");
1952                 getContext().registerReceiver(mReceiver, filter);
1953 
1954                 filter = new IntentFilter();
1955                 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
1956                 getContext().registerReceiver(mReceiver, filter);
1957 
1958                 filter = new IntentFilter();
1959                 filter.addAction(Intent.ACTION_SCREEN_OFF);
1960                 filter.addAction(Intent.ACTION_SCREEN_ON);
1961                 getContext().registerReceiver(mInteractivityReceiver, filter);
1962 
1963                 mLocalActivityManager.setDeviceIdleWhitelist(
1964                         mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
1965                 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
1966 
1967                 mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE,
1968                         state -> {
1969                             synchronized (DeviceIdleController.this) {
1970                                 updateQuickDozeFlagLocked(state.batterySaverEnabled);
1971                             }
1972                         });
1973                 updateQuickDozeFlagLocked(
1974                         mLocalPowerManager.getLowPowerState(
1975                                 ServiceType.QUICK_DOZE).batterySaverEnabled);
1976 
1977                 mLocalActivityTaskManager.registerScreenObserver(mScreenObserver);
1978 
1979                 passWhiteListsToForceAppStandbyTrackerLocked();
1980                 updateInteractivityLocked();
1981             }
1982             updateConnectivityState(null);
1983         }
1984     }
1985 
1986     @VisibleForTesting
hasMotionSensor()1987     boolean hasMotionSensor() {
1988         return mUseMotionSensor && mMotionSensor != null;
1989     }
1990 
registerDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint, final String name, final int type)1991     private void registerDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint,
1992             final String name, final int type) {
1993         final int minState;
1994         switch (type) {
1995             case IDeviceIdleConstraint.ACTIVE:
1996                 minState = STATE_ACTIVE;
1997                 break;
1998             case IDeviceIdleConstraint.SENSING_OR_ABOVE:
1999                 minState = STATE_SENSING;
2000                 break;
2001             default:
2002                 Slog.wtf(TAG, "Registering device-idle constraint with invalid type: " + type);
2003                 return;
2004         }
2005         synchronized (this) {
2006             if (mConstraints.containsKey(constraint)) {
2007                 Slog.e(TAG, "Re-registering device-idle constraint: " + constraint + ".");
2008                 return;
2009             }
2010             DeviceIdleConstraintTracker tracker = new DeviceIdleConstraintTracker(name, minState);
2011             mConstraints.put(constraint, tracker);
2012             updateActiveConstraintsLocked();
2013         }
2014     }
2015 
unregisterDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint)2016     private void unregisterDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint) {
2017         synchronized (this) {
2018             // Artifically force the constraint to inactive to unblock anything waiting for it.
2019             onConstraintStateChangedLocked(constraint, /* active= */ false);
2020 
2021             // Let the constraint know that we are not listening to it any more.
2022             setConstraintMonitoringLocked(constraint, /* monitoring= */ false);
2023             mConstraints.remove(constraint);
2024         }
2025     }
2026 
2027     @GuardedBy("this")
onConstraintStateChangedLocked(IDeviceIdleConstraint constraint, boolean active)2028     private void onConstraintStateChangedLocked(IDeviceIdleConstraint constraint, boolean active) {
2029         DeviceIdleConstraintTracker tracker = mConstraints.get(constraint);
2030         if (tracker == null) {
2031             Slog.e(TAG, "device-idle constraint " + constraint + " has not been registered.");
2032             return;
2033         }
2034         if (active != tracker.active && tracker.monitoring) {
2035             tracker.active = active;
2036             mNumBlockingConstraints += (tracker.active ? +1 : -1);
2037             if (mNumBlockingConstraints == 0) {
2038                 if (mState == STATE_ACTIVE) {
2039                     becomeInactiveIfAppropriateLocked();
2040                 } else if (mNextAlarmTime == 0 || mNextAlarmTime < SystemClock.elapsedRealtime()) {
2041                     stepIdleStateLocked("s:" + tracker.name);
2042                 }
2043             }
2044         }
2045     }
2046 
2047     @GuardedBy("this")
setConstraintMonitoringLocked(IDeviceIdleConstraint constraint, boolean monitor)2048     private void setConstraintMonitoringLocked(IDeviceIdleConstraint constraint, boolean monitor) {
2049         DeviceIdleConstraintTracker tracker = mConstraints.get(constraint);
2050         if (tracker.monitoring != monitor) {
2051             tracker.monitoring = monitor;
2052             updateActiveConstraintsLocked();
2053             // We send the callback on a separate thread instead of just relying on oneway as
2054             // the client could be in the system server with us and cause re-entry problems.
2055             mHandler.obtainMessage(MSG_SEND_CONSTRAINT_MONITORING,
2056                     /* monitoring= */ monitor ? 1 : 0,
2057                     /* <not used>= */ -1,
2058                     /* constraint= */ constraint).sendToTarget();
2059         }
2060     }
2061 
2062     @GuardedBy("this")
updateActiveConstraintsLocked()2063     private void updateActiveConstraintsLocked() {
2064         mNumBlockingConstraints = 0;
2065         for (int i = 0; i < mConstraints.size(); i++) {
2066             final IDeviceIdleConstraint constraint = mConstraints.keyAt(i);
2067             final DeviceIdleConstraintTracker tracker = mConstraints.valueAt(i);
2068             final boolean monitoring = (tracker.minState == mState);
2069             if (monitoring != tracker.monitoring) {
2070                 setConstraintMonitoringLocked(constraint, monitoring);
2071                 tracker.active = monitoring;
2072             }
2073             if (tracker.monitoring && tracker.active) {
2074                 mNumBlockingConstraints++;
2075             }
2076         }
2077     }
2078 
addPowerSaveWhitelistAppInternal(String name)2079     public boolean addPowerSaveWhitelistAppInternal(String name) {
2080         synchronized (this) {
2081             try {
2082                 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
2083                         PackageManager.MATCH_ANY_USER);
2084                 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
2085                     reportPowerSaveWhitelistChangedLocked();
2086                     updateWhitelistAppIdsLocked();
2087                     writeConfigFileLocked();
2088                 }
2089                 return true;
2090             } catch (PackageManager.NameNotFoundException e) {
2091                 return false;
2092             }
2093         }
2094     }
2095 
removePowerSaveWhitelistAppInternal(String name)2096     public boolean removePowerSaveWhitelistAppInternal(String name) {
2097         synchronized (this) {
2098             if (mPowerSaveWhitelistUserApps.remove(name) != null) {
2099                 reportPowerSaveWhitelistChangedLocked();
2100                 updateWhitelistAppIdsLocked();
2101                 writeConfigFileLocked();
2102                 return true;
2103             }
2104         }
2105         return false;
2106     }
2107 
getPowerSaveWhitelistAppInternal(String name)2108     public boolean getPowerSaveWhitelistAppInternal(String name) {
2109         synchronized (this) {
2110             return mPowerSaveWhitelistUserApps.containsKey(name);
2111         }
2112     }
2113 
resetSystemPowerWhitelistInternal()2114     void resetSystemPowerWhitelistInternal() {
2115         synchronized (this) {
2116             mPowerSaveWhitelistApps.putAll(mRemovedFromSystemWhitelistApps);
2117             mRemovedFromSystemWhitelistApps.clear();
2118             reportPowerSaveWhitelistChangedLocked();
2119             updateWhitelistAppIdsLocked();
2120             writeConfigFileLocked();
2121         }
2122     }
2123 
restoreSystemPowerWhitelistAppInternal(String name)2124     public boolean restoreSystemPowerWhitelistAppInternal(String name) {
2125         synchronized (this) {
2126             if (!mRemovedFromSystemWhitelistApps.containsKey(name)) {
2127                 return false;
2128             }
2129             mPowerSaveWhitelistApps.put(name, mRemovedFromSystemWhitelistApps.remove(name));
2130             reportPowerSaveWhitelistChangedLocked();
2131             updateWhitelistAppIdsLocked();
2132             writeConfigFileLocked();
2133             return true;
2134         }
2135     }
2136 
removeSystemPowerWhitelistAppInternal(String name)2137     public boolean removeSystemPowerWhitelistAppInternal(String name) {
2138         synchronized (this) {
2139             if (!mPowerSaveWhitelistApps.containsKey(name)) {
2140                 return false;
2141             }
2142             mRemovedFromSystemWhitelistApps.put(name, mPowerSaveWhitelistApps.remove(name));
2143             reportPowerSaveWhitelistChangedLocked();
2144             updateWhitelistAppIdsLocked();
2145             writeConfigFileLocked();
2146             return true;
2147         }
2148     }
2149 
addPowerSaveWhitelistExceptIdleInternal(String name)2150     public boolean addPowerSaveWhitelistExceptIdleInternal(String name) {
2151         synchronized (this) {
2152             try {
2153                 final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
2154                         PackageManager.MATCH_ANY_USER);
2155                 if (mPowerSaveWhitelistAppsExceptIdle.put(name, UserHandle.getAppId(ai.uid))
2156                         == null) {
2157                     mPowerSaveWhitelistUserAppsExceptIdle.add(name);
2158                     reportPowerSaveWhitelistChangedLocked();
2159                     mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
2160                             mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
2161                             mPowerSaveWhitelistExceptIdleAppIds);
2162 
2163                     passWhiteListsToForceAppStandbyTrackerLocked();
2164                 }
2165                 return true;
2166             } catch (PackageManager.NameNotFoundException e) {
2167                 return false;
2168             }
2169         }
2170     }
2171 
resetPowerSaveWhitelistExceptIdleInternal()2172     public void resetPowerSaveWhitelistExceptIdleInternal() {
2173         synchronized (this) {
2174             if (mPowerSaveWhitelistAppsExceptIdle.removeAll(
2175                     mPowerSaveWhitelistUserAppsExceptIdle)) {
2176                 reportPowerSaveWhitelistChangedLocked();
2177                 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
2178                         mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
2179                         mPowerSaveWhitelistExceptIdleAppIds);
2180                 mPowerSaveWhitelistUserAppsExceptIdle.clear();
2181 
2182                 passWhiteListsToForceAppStandbyTrackerLocked();
2183             }
2184         }
2185     }
2186 
getPowerSaveWhitelistExceptIdleInternal(String name)2187     public boolean getPowerSaveWhitelistExceptIdleInternal(String name) {
2188         synchronized (this) {
2189             return mPowerSaveWhitelistAppsExceptIdle.containsKey(name);
2190         }
2191     }
2192 
getSystemPowerWhitelistExceptIdleInternal()2193     public String[] getSystemPowerWhitelistExceptIdleInternal() {
2194         synchronized (this) {
2195             int size = mPowerSaveWhitelistAppsExceptIdle.size();
2196             String[] apps = new String[size];
2197             for (int i = 0; i < size; i++) {
2198                 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
2199             }
2200             return apps;
2201         }
2202     }
2203 
getSystemPowerWhitelistInternal()2204     public String[] getSystemPowerWhitelistInternal() {
2205         synchronized (this) {
2206             int size = mPowerSaveWhitelistApps.size();
2207             String[] apps = new String[size];
2208             for (int i = 0; i < size; i++) {
2209                 apps[i] = mPowerSaveWhitelistApps.keyAt(i);
2210             }
2211             return apps;
2212         }
2213     }
2214 
getRemovedSystemPowerWhitelistAppsInternal()2215     public String[] getRemovedSystemPowerWhitelistAppsInternal() {
2216         synchronized (this) {
2217             int size = mRemovedFromSystemWhitelistApps.size();
2218             final String[] apps = new String[size];
2219             for (int i = 0; i < size; i++) {
2220                 apps[i] = mRemovedFromSystemWhitelistApps.keyAt(i);
2221             }
2222             return apps;
2223         }
2224     }
2225 
getUserPowerWhitelistInternal()2226     public String[] getUserPowerWhitelistInternal() {
2227         synchronized (this) {
2228             int size = mPowerSaveWhitelistUserApps.size();
2229             String[] apps = new String[size];
2230             for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2231                 apps[i] = mPowerSaveWhitelistUserApps.keyAt(i);
2232             }
2233             return apps;
2234         }
2235     }
2236 
getFullPowerWhitelistExceptIdleInternal()2237     public String[] getFullPowerWhitelistExceptIdleInternal() {
2238         synchronized (this) {
2239             int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
2240             String[] apps = new String[size];
2241             int cur = 0;
2242             for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
2243                 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
2244                 cur++;
2245             }
2246             for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2247                 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
2248                 cur++;
2249             }
2250             return apps;
2251         }
2252     }
2253 
getFullPowerWhitelistInternal()2254     public String[] getFullPowerWhitelistInternal() {
2255         synchronized (this) {
2256             int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
2257             String[] apps = new String[size];
2258             int cur = 0;
2259             for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
2260                 apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
2261                 cur++;
2262             }
2263             for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
2264                 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
2265                 cur++;
2266             }
2267             return apps;
2268         }
2269     }
2270 
isPowerSaveWhitelistExceptIdleAppInternal(String packageName)2271     public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
2272         synchronized (this) {
2273             return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
2274                     || mPowerSaveWhitelistUserApps.containsKey(packageName);
2275         }
2276     }
2277 
isPowerSaveWhitelistAppInternal(String packageName)2278     public boolean isPowerSaveWhitelistAppInternal(String packageName) {
2279         synchronized (this) {
2280             return mPowerSaveWhitelistApps.containsKey(packageName)
2281                     || mPowerSaveWhitelistUserApps.containsKey(packageName);
2282         }
2283     }
2284 
getAppIdWhitelistExceptIdleInternal()2285     public int[] getAppIdWhitelistExceptIdleInternal() {
2286         synchronized (this) {
2287             return mPowerSaveWhitelistExceptIdleAppIdArray;
2288         }
2289     }
2290 
getAppIdWhitelistInternal()2291     public int[] getAppIdWhitelistInternal() {
2292         synchronized (this) {
2293             return mPowerSaveWhitelistAllAppIdArray;
2294         }
2295     }
2296 
getAppIdUserWhitelistInternal()2297     public int[] getAppIdUserWhitelistInternal() {
2298         synchronized (this) {
2299             return mPowerSaveWhitelistUserAppIdArray;
2300         }
2301     }
2302 
getAppIdTempWhitelistInternal()2303     public int[] getAppIdTempWhitelistInternal() {
2304         synchronized (this) {
2305             return mTempWhitelistAppIdArray;
2306         }
2307     }
2308 
addPowerSaveTempWhitelistAppChecked(String packageName, long duration, int userId, String reason)2309     void addPowerSaveTempWhitelistAppChecked(String packageName, long duration,
2310             int userId, String reason) throws RemoteException {
2311         getContext().enforceCallingPermission(
2312                 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
2313                 "No permission to change device idle whitelist");
2314         final int callingUid = Binder.getCallingUid();
2315         userId = ActivityManager.getService().handleIncomingUser(
2316                 Binder.getCallingPid(),
2317                 callingUid,
2318                 userId,
2319                 /*allowAll=*/ false,
2320                 /*requireFull=*/ false,
2321                 "addPowerSaveTempWhitelistApp", null);
2322         final long token = Binder.clearCallingIdentity();
2323         try {
2324             addPowerSaveTempWhitelistAppInternal(callingUid,
2325                     packageName, duration, userId, true, reason);
2326         } finally {
2327             Binder.restoreCallingIdentity(token);
2328         }
2329     }
2330 
removePowerSaveTempWhitelistAppChecked(String packageName, int userId)2331     void removePowerSaveTempWhitelistAppChecked(String packageName, int userId)
2332             throws RemoteException {
2333         getContext().enforceCallingPermission(
2334                 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
2335                 "No permission to change device idle whitelist");
2336         final int callingUid = Binder.getCallingUid();
2337         userId = ActivityManager.getService().handleIncomingUser(
2338                 Binder.getCallingPid(),
2339                 callingUid,
2340                 userId,
2341                 /*allowAll=*/ false,
2342                 /*requireFull=*/ false,
2343                 "removePowerSaveTempWhitelistApp", null);
2344         final long token = Binder.clearCallingIdentity();
2345         try {
2346             removePowerSaveTempWhitelistAppInternal(packageName, userId);
2347         } finally {
2348             Binder.restoreCallingIdentity(token);
2349         }
2350     }
2351 
2352     /**
2353      * Adds an app to the temporary whitelist and resets the endTime for granting the
2354      * app an exemption to access network and acquire wakelocks.
2355      */
addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName, long duration, int userId, boolean sync, String reason)2356     void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
2357             long duration, int userId, boolean sync, String reason) {
2358         try {
2359             int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId);
2360             addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, duration, sync, reason);
2361         } catch (NameNotFoundException e) {
2362         }
2363     }
2364 
2365     /**
2366      * Adds an app to the temporary whitelist and resets the endTime for granting the
2367      * app an exemption to access network and acquire wakelocks.
2368      */
addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int uid, long duration, boolean sync, String reason)2369     void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int uid,
2370             long duration, boolean sync, String reason) {
2371         final long timeNow = SystemClock.elapsedRealtime();
2372         boolean informWhitelistChanged = false;
2373         int appId = UserHandle.getAppId(uid);
2374         synchronized (this) {
2375             int callingAppId = UserHandle.getAppId(callingUid);
2376             if (callingAppId >= Process.FIRST_APPLICATION_UID) {
2377                 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
2378                     throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
2379                             + " is not on whitelist");
2380                 }
2381             }
2382             duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
2383             Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
2384             final boolean newEntry = entry == null;
2385             // Set the new end time
2386             if (newEntry) {
2387                 entry = new Pair<>(new MutableLong(0), reason);
2388                 mTempWhitelistAppIdEndTimes.put(appId, entry);
2389             }
2390             entry.first.value = timeNow + duration;
2391             if (DEBUG) {
2392                 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist. New entry: " + newEntry);
2393             }
2394             if (newEntry) {
2395                 // No pending timeout for the app id, post a delayed message
2396                 try {
2397                     mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
2398                             reason, uid);
2399                 } catch (RemoteException e) {
2400                 }
2401                 postTempActiveTimeoutMessage(appId, duration);
2402                 updateTempWhitelistAppIdsLocked(appId, true);
2403                 if (sync) {
2404                     informWhitelistChanged = true;
2405                 } else {
2406                     mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED, appId, 1)
2407                             .sendToTarget();
2408                 }
2409                 reportTempWhitelistChangedLocked();
2410             }
2411         }
2412         if (informWhitelistChanged) {
2413             mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, true);
2414         }
2415     }
2416 
2417     /**
2418      * Removes an app from the temporary whitelist and notifies the observers.
2419      */
removePowerSaveTempWhitelistAppInternal(String packageName, int userId)2420     private void removePowerSaveTempWhitelistAppInternal(String packageName, int userId) {
2421         try {
2422             final int uid = getContext().getPackageManager().getPackageUidAsUser(
2423                     packageName, userId);
2424             final int appId = UserHandle.getAppId(uid);
2425             removePowerSaveTempWhitelistAppDirectInternal(appId);
2426         } catch (NameNotFoundException e) {
2427         }
2428     }
2429 
removePowerSaveTempWhitelistAppDirectInternal(int appId)2430     private void removePowerSaveTempWhitelistAppDirectInternal(int appId) {
2431         synchronized (this) {
2432             final int idx = mTempWhitelistAppIdEndTimes.indexOfKey(appId);
2433             if (idx < 0) {
2434                 // Nothing else to do
2435                 return;
2436             }
2437             final String reason = mTempWhitelistAppIdEndTimes.valueAt(idx).second;
2438             mTempWhitelistAppIdEndTimes.removeAt(idx);
2439             onAppRemovedFromTempWhitelistLocked(appId, reason);
2440         }
2441     }
2442 
postTempActiveTimeoutMessage(int appId, long delay)2443     private void postTempActiveTimeoutMessage(int appId, long delay) {
2444         if (DEBUG) {
2445             Slog.d(TAG, "postTempActiveTimeoutMessage: appId=" + appId + ", delay=" + delay);
2446         }
2447         mHandler.sendMessageDelayed(
2448                 mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, appId, 0), delay);
2449     }
2450 
checkTempAppWhitelistTimeout(int appId)2451     void checkTempAppWhitelistTimeout(int appId) {
2452         final long timeNow = SystemClock.elapsedRealtime();
2453         if (DEBUG) {
2454             Slog.d(TAG, "checkTempAppWhitelistTimeout: appId=" + appId + ", timeNow=" + timeNow);
2455         }
2456         synchronized (this) {
2457             Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
2458             if (entry == null) {
2459                 // Nothing to do
2460                 return;
2461             }
2462             if (timeNow >= entry.first.value) {
2463                 mTempWhitelistAppIdEndTimes.delete(appId);
2464                 onAppRemovedFromTempWhitelistLocked(appId, entry.second);
2465             } else {
2466                 // Need more time
2467                 if (DEBUG) {
2468                     Slog.d(TAG, "Time to remove AppId " + appId + ": " + entry.first.value);
2469                 }
2470                 postTempActiveTimeoutMessage(appId, entry.first.value - timeNow);
2471             }
2472         }
2473     }
2474 
2475     @GuardedBy("this")
onAppRemovedFromTempWhitelistLocked(int appId, String reason)2476     private void onAppRemovedFromTempWhitelistLocked(int appId, String reason) {
2477         if (DEBUG) {
2478             Slog.d(TAG, "Removing appId " + appId + " from temp whitelist");
2479         }
2480         updateTempWhitelistAppIdsLocked(appId, false);
2481         mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED, appId, 0)
2482                 .sendToTarget();
2483         reportTempWhitelistChangedLocked();
2484         try {
2485             mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
2486                     reason, appId);
2487         } catch (RemoteException e) {
2488         }
2489     }
2490 
exitIdleInternal(String reason)2491     public void exitIdleInternal(String reason) {
2492         synchronized (this) {
2493             mActiveReason = ACTIVE_REASON_FROM_BINDER_CALL;
2494             becomeActiveLocked(reason, Binder.getCallingUid());
2495         }
2496     }
2497 
2498     @VisibleForTesting
isNetworkConnected()2499     boolean isNetworkConnected() {
2500         synchronized (this) {
2501             return mNetworkConnected;
2502         }
2503     }
2504 
updateConnectivityState(Intent connIntent)2505     void updateConnectivityState(Intent connIntent) {
2506         ConnectivityService cm;
2507         synchronized (this) {
2508             cm = mInjector.getConnectivityService();
2509         }
2510         if (cm == null) {
2511             return;
2512         }
2513         // Note: can't call out to ConnectivityService with our lock held.
2514         NetworkInfo ni = cm.getActiveNetworkInfo();
2515         synchronized (this) {
2516             boolean conn;
2517             if (ni == null) {
2518                 conn = false;
2519             } else {
2520                 if (connIntent == null) {
2521                     conn = ni.isConnected();
2522                 } else {
2523                     final int networkType =
2524                             connIntent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
2525                                     ConnectivityManager.TYPE_NONE);
2526                     if (ni.getType() != networkType) {
2527                         return;
2528                     }
2529                     conn = !connIntent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
2530                             false);
2531                 }
2532             }
2533             if (conn != mNetworkConnected) {
2534                 mNetworkConnected = conn;
2535                 if (conn && mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
2536                     stepLightIdleStateLocked("network");
2537                 }
2538             }
2539         }
2540     }
2541 
2542     @VisibleForTesting
isScreenOn()2543     boolean isScreenOn() {
2544         synchronized (this) {
2545             return mScreenOn;
2546         }
2547     }
2548 
updateInteractivityLocked()2549     void updateInteractivityLocked() {
2550         // The interactivity state from the power manager tells us whether the display is
2551         // in a state that we need to keep things running so they will update at a normal
2552         // frequency.
2553         boolean screenOn = mPowerManager.isInteractive();
2554         if (DEBUG) Slog.d(TAG, "updateInteractivityLocked: screenOn=" + screenOn);
2555         if (!screenOn && mScreenOn) {
2556             mScreenOn = false;
2557             if (!mForceIdle) {
2558                 becomeInactiveIfAppropriateLocked();
2559             }
2560         } else if (screenOn) {
2561             mScreenOn = true;
2562             if (!mForceIdle && (!mScreenLocked || !mConstants.WAIT_FOR_UNLOCK)) {
2563                 mActiveReason = ACTIVE_REASON_SCREEN;
2564                 becomeActiveLocked("screen", Process.myUid());
2565             }
2566         }
2567     }
2568 
2569     @VisibleForTesting
isCharging()2570     boolean isCharging() {
2571         synchronized (this) {
2572             return mCharging;
2573         }
2574     }
2575 
updateChargingLocked(boolean charging)2576     void updateChargingLocked(boolean charging) {
2577         if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
2578         if (!charging && mCharging) {
2579             mCharging = false;
2580             if (!mForceIdle) {
2581                 becomeInactiveIfAppropriateLocked();
2582             }
2583         } else if (charging) {
2584             mCharging = charging;
2585             if (!mForceIdle) {
2586                 mActiveReason = ACTIVE_REASON_CHARGING;
2587                 becomeActiveLocked("charging", Process.myUid());
2588             }
2589         }
2590     }
2591 
2592     @VisibleForTesting
isQuickDozeEnabled()2593     boolean isQuickDozeEnabled() {
2594         synchronized (this) {
2595             return mQuickDozeActivated;
2596         }
2597     }
2598 
2599     /** Updates the quick doze flag and enters deep doze if appropriate. */
2600     @VisibleForTesting
updateQuickDozeFlagLocked(boolean enabled)2601     void updateQuickDozeFlagLocked(boolean enabled) {
2602         if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
2603         mQuickDozeActivated = enabled;
2604         if (enabled) {
2605             // If Quick Doze is enabled, see if we should go straight into it.
2606             becomeInactiveIfAppropriateLocked();
2607         }
2608         // Going from Deep Doze to Light Idle (if quick doze becomes disabled) is tricky and
2609         // probably not worth the overhead, so leave in deep doze if that's the case until the
2610         // next natural time to come out of it.
2611     }
2612 
2613 
2614     /** Returns true if the screen is locked. */
2615     @VisibleForTesting
isKeyguardShowing()2616     boolean isKeyguardShowing() {
2617         synchronized (this) {
2618             return mScreenLocked;
2619         }
2620     }
2621 
2622     @VisibleForTesting
keyguardShowingLocked(boolean showing)2623     void keyguardShowingLocked(boolean showing) {
2624         if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing);
2625         if (mScreenLocked != showing) {
2626             mScreenLocked = showing;
2627             if (mScreenOn && !mForceIdle && !mScreenLocked) {
2628                 mActiveReason = ACTIVE_REASON_UNLOCKED;
2629                 becomeActiveLocked("unlocked", Process.myUid());
2630             }
2631         }
2632     }
2633 
2634     @VisibleForTesting
scheduleReportActiveLocked(String activeReason, int activeUid)2635     void scheduleReportActiveLocked(String activeReason, int activeUid) {
2636         Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
2637         mHandler.sendMessage(msg);
2638     }
2639 
becomeActiveLocked(String activeReason, int activeUid)2640     void becomeActiveLocked(String activeReason, int activeUid) {
2641         becomeActiveLocked(activeReason, activeUid, mConstants.INACTIVE_TIMEOUT, true);
2642     }
2643 
becomeActiveLocked(String activeReason, int activeUid, long newInactiveTimeout, boolean changeLightIdle)2644     private void becomeActiveLocked(String activeReason, int activeUid,
2645             long newInactiveTimeout, boolean changeLightIdle) {
2646         if (DEBUG) {
2647             Slog.i(TAG, "becomeActiveLocked, reason=" + activeReason
2648                     + ", changeLightIdle=" + changeLightIdle);
2649         }
2650         if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
2651             EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
2652             mState = STATE_ACTIVE;
2653             mInactiveTimeout = newInactiveTimeout;
2654             mCurIdleBudget = 0;
2655             mMaintenanceStartTime = 0;
2656             resetIdleManagementLocked();
2657 
2658             if (changeLightIdle) {
2659                 EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
2660                 mLightState = LIGHT_STATE_ACTIVE;
2661                 resetLightIdleManagementLocked();
2662                 // Only report active if light is also ACTIVE.
2663                 scheduleReportActiveLocked(activeReason, activeUid);
2664                 addEvent(EVENT_NORMAL, activeReason);
2665             }
2666         }
2667     }
2668 
2669     /** Must only be used in tests. */
2670     @VisibleForTesting
setDeepEnabledForTest(boolean enabled)2671     void setDeepEnabledForTest(boolean enabled) {
2672         synchronized (this) {
2673             mDeepEnabled = enabled;
2674         }
2675     }
2676 
2677     /** Must only be used in tests. */
2678     @VisibleForTesting
setLightEnabledForTest(boolean enabled)2679     void setLightEnabledForTest(boolean enabled) {
2680         synchronized (this) {
2681             mLightEnabled = enabled;
2682         }
2683     }
2684 
2685     /** Sanity check to make sure DeviceIdleController and AlarmManager are on the same page. */
verifyAlarmStateLocked()2686     private void verifyAlarmStateLocked() {
2687         if (mState == STATE_ACTIVE && mNextAlarmTime != 0) {
2688             Slog.wtf(TAG, "mState=ACTIVE but mNextAlarmTime=" + mNextAlarmTime);
2689         }
2690         if (mState != STATE_IDLE && mLocalAlarmManager.isIdling()) {
2691             Slog.wtf(TAG, "mState=" + stateToString(mState) + " but AlarmManager is idling");
2692         }
2693         if (mState == STATE_IDLE && !mLocalAlarmManager.isIdling()) {
2694             Slog.wtf(TAG, "mState=IDLE but AlarmManager is not idling");
2695         }
2696         if (mLightState == LIGHT_STATE_ACTIVE && mNextLightAlarmTime != 0) {
2697             Slog.wtf(TAG, "mLightState=ACTIVE but mNextLightAlarmTime is "
2698                     + TimeUtils.formatDuration(mNextLightAlarmTime - SystemClock.elapsedRealtime())
2699                     + " from now");
2700         }
2701     }
2702 
becomeInactiveIfAppropriateLocked()2703     void becomeInactiveIfAppropriateLocked() {
2704         verifyAlarmStateLocked();
2705 
2706         final boolean isScreenBlockingInactive =
2707                 mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked);
2708         if (DEBUG) {
2709             Slog.d(TAG, "becomeInactiveIfAppropriateLocked():"
2710                     + " isScreenBlockingInactive=" + isScreenBlockingInactive
2711                     + " (mScreenOn=" + mScreenOn
2712                     + ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK
2713                     + ", mScreenLocked=" + mScreenLocked + ")"
2714                     + " mCharging=" + mCharging
2715                     + " mForceIdle=" + mForceIdle
2716             );
2717         }
2718         if (!mForceIdle && (mCharging || isScreenBlockingInactive)) {
2719             return;
2720         }
2721         // Become inactive and determine if we will ultimately go idle.
2722         if (mDeepEnabled) {
2723             if (mQuickDozeActivated) {
2724                 if (mState == STATE_QUICK_DOZE_DELAY || mState == STATE_IDLE
2725                         || mState == STATE_IDLE_MAINTENANCE) {
2726                     // Already "idling". Don't want to restart the process.
2727                     // mLightState can't be LIGHT_STATE_ACTIVE if mState is any of these 3
2728                     // values, so returning here is safe.
2729                     return;
2730                 }
2731                 if (DEBUG) {
2732                     Slog.d(TAG, "Moved from "
2733                             + stateToString(mState) + " to STATE_QUICK_DOZE_DELAY");
2734                 }
2735                 mState = STATE_QUICK_DOZE_DELAY;
2736                 // Make sure any motion sensing or locating is stopped.
2737                 resetIdleManagementLocked();
2738                 // Wait a small amount of time in case something (eg: background service from
2739                 // recently closed app) needs to finish running.
2740                 scheduleAlarmLocked(mConstants.QUICK_DOZE_DELAY_TIMEOUT, false);
2741                 EventLogTags.writeDeviceIdle(mState, "no activity");
2742             } else if (mState == STATE_ACTIVE) {
2743                 mState = STATE_INACTIVE;
2744                 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
2745                 resetIdleManagementLocked();
2746                 long delay = mInactiveTimeout;
2747                 if (shouldUseIdleTimeoutFactorLocked()) {
2748                     delay = (long) (mPreIdleFactor * delay);
2749                 }
2750                 scheduleAlarmLocked(delay, false);
2751                 EventLogTags.writeDeviceIdle(mState, "no activity");
2752             }
2753         }
2754         if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
2755             mLightState = LIGHT_STATE_INACTIVE;
2756             if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
2757             resetLightIdleManagementLocked();
2758             scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
2759             EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
2760         }
2761     }
2762 
resetIdleManagementLocked()2763     private void resetIdleManagementLocked() {
2764         mNextIdlePendingDelay = 0;
2765         mNextIdleDelay = 0;
2766         mNextLightIdleDelay = 0;
2767         mIdleStartTime = 0;
2768         cancelAlarmLocked();
2769         cancelSensingTimeoutAlarmLocked();
2770         cancelLocatingLocked();
2771         stopMonitoringMotionLocked();
2772         mAnyMotionDetector.stop();
2773         updateActiveConstraintsLocked();
2774     }
2775 
resetLightIdleManagementLocked()2776     private void resetLightIdleManagementLocked() {
2777         cancelLightAlarmLocked();
2778     }
2779 
exitForceIdleLocked()2780     void exitForceIdleLocked() {
2781         if (mForceIdle) {
2782             mForceIdle = false;
2783             if (mScreenOn || mCharging) {
2784                 mActiveReason = ACTIVE_REASON_FORCED;
2785                 becomeActiveLocked("exit-force", Process.myUid());
2786             }
2787         }
2788     }
2789 
2790     /**
2791      * Must only be used in tests.
2792      *
2793      * This sets the state value directly and thus doesn't trigger any behavioral changes.
2794      */
2795     @VisibleForTesting
setLightStateForTest(int lightState)2796     void setLightStateForTest(int lightState) {
2797         synchronized (this) {
2798             mLightState = lightState;
2799         }
2800     }
2801 
2802     @VisibleForTesting
getLightState()2803     int getLightState() {
2804         return mLightState;
2805     }
2806 
stepLightIdleStateLocked(String reason)2807     void stepLightIdleStateLocked(String reason) {
2808         if (mLightState == LIGHT_STATE_OVERRIDE) {
2809             // If we are already in deep device idle mode, then
2810             // there is nothing left to do for light mode.
2811             return;
2812         }
2813 
2814         if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState);
2815         EventLogTags.writeDeviceIdleLightStep();
2816 
2817         switch (mLightState) {
2818             case LIGHT_STATE_INACTIVE:
2819                 mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
2820                 // Reset the upcoming idle delays.
2821                 mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
2822                 mMaintenanceStartTime = 0;
2823                 if (!isOpsInactiveLocked()) {
2824                     // We have some active ops going on...  give them a chance to finish
2825                     // before going in to our first idle.
2826                     mLightState = LIGHT_STATE_PRE_IDLE;
2827                     EventLogTags.writeDeviceIdleLight(mLightState, reason);
2828                     scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT);
2829                     break;
2830                 }
2831                 // Nothing active, fall through to immediately idle.
2832             case LIGHT_STATE_PRE_IDLE:
2833             case LIGHT_STATE_IDLE_MAINTENANCE:
2834                 if (mMaintenanceStartTime != 0) {
2835                     long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime;
2836                     if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
2837                         // We didn't use up all of our minimum budget; add this to the reserve.
2838                         mCurIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET-duration);
2839                     } else {
2840                         // We used more than our minimum budget; this comes out of the reserve.
2841                         mCurIdleBudget -= (duration-mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);
2842                     }
2843                 }
2844                 mMaintenanceStartTime = 0;
2845                 scheduleLightAlarmLocked(mNextLightIdleDelay);
2846                 mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
2847                         (long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
2848                 if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {
2849                     mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
2850                 }
2851                 if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
2852                 mLightState = LIGHT_STATE_IDLE;
2853                 EventLogTags.writeDeviceIdleLight(mLightState, reason);
2854                 addEvent(EVENT_LIGHT_IDLE, null);
2855                 mGoingIdleWakeLock.acquire();
2856                 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
2857                 break;
2858             case LIGHT_STATE_IDLE:
2859             case LIGHT_STATE_WAITING_FOR_NETWORK:
2860                 if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
2861                     // We have been idling long enough, now it is time to do some work.
2862                     mActiveIdleOpCount = 1;
2863                     mActiveIdleWakeLock.acquire();
2864                     mMaintenanceStartTime = SystemClock.elapsedRealtime();
2865                     if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
2866                         mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
2867                     } else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
2868                         mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
2869                     }
2870                     scheduleLightAlarmLocked(mCurIdleBudget);
2871                     if (DEBUG) Slog.d(TAG,
2872                             "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
2873                     mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
2874                     EventLogTags.writeDeviceIdleLight(mLightState, reason);
2875                     addEvent(EVENT_LIGHT_MAINTENANCE, null);
2876                     mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
2877                 } else {
2878                     // We'd like to do maintenance, but currently don't have network
2879                     // connectivity...  let's try to wait until the network comes back.
2880                     // We'll only wait for another full idle period, however, and then give up.
2881                     scheduleLightAlarmLocked(mNextLightIdleDelay);
2882                     if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK.");
2883                     mLightState = LIGHT_STATE_WAITING_FOR_NETWORK;
2884                     EventLogTags.writeDeviceIdleLight(mLightState, reason);
2885                 }
2886                 break;
2887         }
2888     }
2889 
2890     @VisibleForTesting
getState()2891     int getState() {
2892         return mState;
2893     }
2894 
2895     @VisibleForTesting
stepIdleStateLocked(String reason)2896     void stepIdleStateLocked(String reason) {
2897         if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
2898         EventLogTags.writeDeviceIdleStep();
2899 
2900         final long now = SystemClock.elapsedRealtime();
2901         if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
2902             // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
2903             if (mState != STATE_ACTIVE) {
2904                 mActiveReason = ACTIVE_REASON_ALARM;
2905                 becomeActiveLocked("alarm", Process.myUid());
2906                 becomeInactiveIfAppropriateLocked();
2907             }
2908             return;
2909         }
2910 
2911         if (mNumBlockingConstraints != 0 && !mForceIdle) {
2912             // We have some constraints from other parts of the system server preventing
2913             // us from moving to the next state.
2914             if (DEBUG) {
2915                 Slog.i(TAG, "Cannot step idle state. Blocked by: " + mConstraints.values().stream()
2916                         .filter(x -> x.active)
2917                         .map(x -> x.name)
2918                         .collect(Collectors.joining(",")));
2919             }
2920             return;
2921         }
2922 
2923         switch (mState) {
2924             case STATE_INACTIVE:
2925                 // We have now been inactive long enough, it is time to start looking
2926                 // for motion and sleep some more while doing so.
2927                 startMonitoringMotionLocked();
2928                 long delay = mConstants.IDLE_AFTER_INACTIVE_TIMEOUT;
2929                 if (shouldUseIdleTimeoutFactorLocked()) {
2930                     delay = (long) (mPreIdleFactor * delay);
2931                 }
2932                 scheduleAlarmLocked(delay, false);
2933                 moveToStateLocked(STATE_IDLE_PENDING, reason);
2934                 break;
2935             case STATE_IDLE_PENDING:
2936                 moveToStateLocked(STATE_SENSING, reason);
2937                 cancelLocatingLocked();
2938                 mLocated = false;
2939                 mLastGenericLocation = null;
2940                 mLastGpsLocation = null;
2941                 updateActiveConstraintsLocked();
2942 
2943                 // Wait for open constraints and an accelerometer reading before moving on.
2944                 if (mUseMotionSensor && mAnyMotionDetector.hasSensor()) {
2945                     scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
2946                     mNotMoving = false;
2947                     mAnyMotionDetector.checkForAnyMotion();
2948                     break;
2949                 } else if (mNumBlockingConstraints != 0) {
2950                     cancelAlarmLocked();
2951                     break;
2952                 }
2953 
2954                 mNotMoving = true;
2955                 // Otherwise, fall through and check this off the list of requirements.
2956             case STATE_SENSING:
2957                 cancelSensingTimeoutAlarmLocked();
2958                 moveToStateLocked(STATE_LOCATING, reason);
2959                 scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
2960                 LocationManager locationManager = mInjector.getLocationManager();
2961                 if (locationManager != null
2962                         && locationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
2963                     locationManager.requestLocationUpdates(mLocationRequest,
2964                             mGenericLocationListener, mHandler.getLooper());
2965                     mLocating = true;
2966                 } else {
2967                     mHasNetworkLocation = false;
2968                 }
2969                 if (locationManager != null
2970                         && locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
2971                     mHasGps = true;
2972                     locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
2973                             mGpsLocationListener, mHandler.getLooper());
2974                     mLocating = true;
2975                 } else {
2976                     mHasGps = false;
2977                 }
2978                 // If we have a location provider, we're all set, the listeners will move state
2979                 // forward.
2980                 if (mLocating) {
2981                     break;
2982                 }
2983 
2984                 // Otherwise, we have to move from locating into idle maintenance.
2985             case STATE_LOCATING:
2986                 cancelAlarmLocked();
2987                 cancelLocatingLocked();
2988                 mAnyMotionDetector.stop();
2989 
2990                 // Intentional fallthrough -- time to go into IDLE state.
2991             case STATE_QUICK_DOZE_DELAY:
2992                 // Reset the upcoming idle delays.
2993                 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
2994                 mNextIdleDelay = mConstants.IDLE_TIMEOUT;
2995 
2996                 // Everything is in place to go into IDLE state.
2997             case STATE_IDLE_MAINTENANCE:
2998                 scheduleAlarmLocked(mNextIdleDelay, true);
2999                 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
3000                         " ms.");
3001                 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
3002                 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
3003                 mIdleStartTime = SystemClock.elapsedRealtime();
3004                 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
3005                 if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
3006                     mNextIdleDelay = mConstants.IDLE_TIMEOUT;
3007                 }
3008                 moveToStateLocked(STATE_IDLE, reason);
3009                 if (mLightState != LIGHT_STATE_OVERRIDE) {
3010                     mLightState = LIGHT_STATE_OVERRIDE;
3011                     cancelLightAlarmLocked();
3012                 }
3013                 addEvent(EVENT_DEEP_IDLE, null);
3014                 mGoingIdleWakeLock.acquire();
3015                 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
3016                 break;
3017             case STATE_IDLE:
3018                 // We have been idling long enough, now it is time to do some work.
3019                 mActiveIdleOpCount = 1;
3020                 mActiveIdleWakeLock.acquire();
3021                 scheduleAlarmLocked(mNextIdlePendingDelay, false);
3022                 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
3023                         "Next alarm in " + mNextIdlePendingDelay + " ms.");
3024                 mMaintenanceStartTime = SystemClock.elapsedRealtime();
3025                 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
3026                         (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
3027                 if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
3028                     mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
3029                 }
3030                 moveToStateLocked(STATE_IDLE_MAINTENANCE, reason);
3031                 addEvent(EVENT_DEEP_MAINTENANCE, null);
3032                 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
3033                 break;
3034         }
3035     }
3036 
moveToStateLocked(int state, String reason)3037     private void moveToStateLocked(int state, String reason) {
3038         final int oldState = mState;
3039         mState = state;
3040         if (DEBUG) {
3041             Slog.d(TAG, String.format("Moved from STATE_%s to STATE_%s.",
3042                     stateToString(oldState), stateToString(mState)));
3043         }
3044         EventLogTags.writeDeviceIdle(mState, reason);
3045         updateActiveConstraintsLocked();
3046     }
3047 
incActiveIdleOps()3048     void incActiveIdleOps() {
3049         synchronized (this) {
3050             mActiveIdleOpCount++;
3051         }
3052     }
3053 
decActiveIdleOps()3054     void decActiveIdleOps() {
3055         synchronized (this) {
3056             mActiveIdleOpCount--;
3057             if (mActiveIdleOpCount <= 0) {
3058                 exitMaintenanceEarlyIfNeededLocked();
3059                 mActiveIdleWakeLock.release();
3060             }
3061         }
3062     }
3063 
3064     /** Must only be used in tests. */
3065     @VisibleForTesting
setActiveIdleOpsForTest(int count)3066     void setActiveIdleOpsForTest(int count) {
3067         synchronized (this) {
3068             mActiveIdleOpCount = count;
3069         }
3070     }
3071 
setJobsActive(boolean active)3072     void setJobsActive(boolean active) {
3073         synchronized (this) {
3074             mJobsActive = active;
3075             reportMaintenanceActivityIfNeededLocked();
3076             if (!active) {
3077                 exitMaintenanceEarlyIfNeededLocked();
3078             }
3079         }
3080     }
3081 
setAlarmsActive(boolean active)3082     void setAlarmsActive(boolean active) {
3083         synchronized (this) {
3084             mAlarmsActive = active;
3085             if (!active) {
3086                 exitMaintenanceEarlyIfNeededLocked();
3087             }
3088         }
3089     }
3090 
registerMaintenanceActivityListener(IMaintenanceActivityListener listener)3091     boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener) {
3092         synchronized (this) {
3093             mMaintenanceActivityListeners.register(listener);
3094             return mReportedMaintenanceActivity;
3095         }
3096     }
3097 
unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener)3098     void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener) {
3099         synchronized (this) {
3100             mMaintenanceActivityListeners.unregister(listener);
3101         }
3102     }
3103 
3104     @VisibleForTesting
setPreIdleTimeoutMode(int mode)3105     int setPreIdleTimeoutMode(int mode) {
3106         return setPreIdleTimeoutFactor(getPreIdleTimeoutByMode(mode));
3107     }
3108 
3109     @VisibleForTesting
getPreIdleTimeoutByMode(int mode)3110     float getPreIdleTimeoutByMode(int mode) {
3111         switch (mode) {
3112             case PowerManager.PRE_IDLE_TIMEOUT_MODE_LONG: {
3113                 return mConstants.PRE_IDLE_FACTOR_LONG;
3114             }
3115             case PowerManager.PRE_IDLE_TIMEOUT_MODE_SHORT: {
3116                 return mConstants.PRE_IDLE_FACTOR_SHORT;
3117             }
3118             case PowerManager.PRE_IDLE_TIMEOUT_MODE_NORMAL: {
3119                 return 1.0f;
3120             }
3121             default: {
3122                 Slog.w(TAG, "Invalid time out factor mode: " + mode);
3123                 return 1.0f;
3124             }
3125         }
3126     }
3127 
3128     @VisibleForTesting
getPreIdleTimeoutFactor()3129     float getPreIdleTimeoutFactor() {
3130         return mPreIdleFactor;
3131     }
3132 
3133     @VisibleForTesting
setPreIdleTimeoutFactor(float ratio)3134     int setPreIdleTimeoutFactor(float ratio) {
3135         if (!mDeepEnabled) {
3136             if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Deep Idle disable");
3137             return SET_IDLE_FACTOR_RESULT_NOT_SUPPORT;
3138         } else if (ratio <= MIN_PRE_IDLE_FACTOR_CHANGE) {
3139             if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Invalid input");
3140             return SET_IDLE_FACTOR_RESULT_INVALID;
3141         } else if (Math.abs(ratio - mPreIdleFactor) < MIN_PRE_IDLE_FACTOR_CHANGE) {
3142             if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: New factor same as previous factor");
3143             return SET_IDLE_FACTOR_RESULT_IGNORED;
3144         }
3145         synchronized (this) {
3146             mLastPreIdleFactor = mPreIdleFactor;
3147             mPreIdleFactor = ratio;
3148         }
3149         if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: " + ratio);
3150         postUpdatePreIdleFactor();
3151         return SET_IDLE_FACTOR_RESULT_OK;
3152     }
3153 
3154     @VisibleForTesting
resetPreIdleTimeoutMode()3155     void resetPreIdleTimeoutMode() {
3156         synchronized (this) {
3157             mLastPreIdleFactor = mPreIdleFactor;
3158             mPreIdleFactor = 1.0f;
3159         }
3160         if (DEBUG) Slog.d(TAG, "resetPreIdleTimeoutMode to 1.0");
3161         postResetPreIdleTimeoutFactor();
3162     }
3163 
postUpdatePreIdleFactor()3164     private void postUpdatePreIdleFactor() {
3165         mHandler.sendEmptyMessage(MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR);
3166     }
3167 
postResetPreIdleTimeoutFactor()3168     private void postResetPreIdleTimeoutFactor() {
3169         mHandler.sendEmptyMessage(MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR);
3170     }
3171 
3172     @VisibleForTesting
updatePreIdleFactor()3173     void updatePreIdleFactor() {
3174         synchronized (this) {
3175             if (!shouldUseIdleTimeoutFactorLocked()) {
3176                 return;
3177             }
3178             if (mState == STATE_INACTIVE || mState == STATE_IDLE_PENDING) {
3179                 if (mNextAlarmTime == 0) {
3180                     return;
3181                 }
3182                 long delay = mNextAlarmTime - SystemClock.elapsedRealtime();
3183                 if (delay < MIN_STATE_STEP_ALARM_CHANGE) {
3184                     return;
3185                 }
3186                 long newDelay = (long) (delay / mLastPreIdleFactor * mPreIdleFactor);
3187                 if (Math.abs(delay - newDelay) < MIN_STATE_STEP_ALARM_CHANGE) {
3188                     return;
3189                 }
3190                 scheduleAlarmLocked(newDelay, false);
3191             }
3192         }
3193     }
3194 
3195     @VisibleForTesting
maybeDoImmediateMaintenance()3196     void maybeDoImmediateMaintenance() {
3197         synchronized (this) {
3198             if (mState == STATE_IDLE) {
3199                 long duration = SystemClock.elapsedRealtime() - mIdleStartTime;
3200                 /* Let's trgger a immediate maintenance,
3201                  * if it has been idle for a long time */
3202                 if (duration > mConstants.IDLE_TIMEOUT) {
3203                     scheduleAlarmLocked(0, false);
3204                 }
3205             }
3206         }
3207     }
3208 
shouldUseIdleTimeoutFactorLocked()3209     private boolean shouldUseIdleTimeoutFactorLocked() {
3210         // exclude ACTIVE_REASON_MOTION, for exclude device in pocket case
3211         if (mActiveReason == ACTIVE_REASON_MOTION) {
3212             return false;
3213         }
3214         return true;
3215     }
3216 
3217     /** Must only be used in tests. */
3218     @VisibleForTesting
setIdleStartTimeForTest(long idleStartTime)3219     void setIdleStartTimeForTest(long idleStartTime) {
3220         synchronized (this) {
3221             mIdleStartTime = idleStartTime;
3222         }
3223     }
3224 
reportMaintenanceActivityIfNeededLocked()3225     void reportMaintenanceActivityIfNeededLocked() {
3226         boolean active = mJobsActive;
3227         if (active == mReportedMaintenanceActivity) {
3228             return;
3229         }
3230         mReportedMaintenanceActivity = active;
3231         Message msg = mHandler.obtainMessage(MSG_REPORT_MAINTENANCE_ACTIVITY,
3232                 mReportedMaintenanceActivity ? 1 : 0, 0);
3233         mHandler.sendMessage(msg);
3234     }
3235 
3236     @VisibleForTesting
getNextAlarmTime()3237     long getNextAlarmTime() {
3238         return mNextAlarmTime;
3239     }
3240 
isOpsInactiveLocked()3241     boolean isOpsInactiveLocked() {
3242         return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
3243     }
3244 
exitMaintenanceEarlyIfNeededLocked()3245     void exitMaintenanceEarlyIfNeededLocked() {
3246         if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE
3247                 || mLightState == LIGHT_STATE_PRE_IDLE) {
3248             if (isOpsInactiveLocked()) {
3249                 final long now = SystemClock.elapsedRealtime();
3250                 if (DEBUG) {
3251                     StringBuilder sb = new StringBuilder();
3252                     sb.append("Exit: start=");
3253                     TimeUtils.formatDuration(mMaintenanceStartTime, sb);
3254                     sb.append(" now=");
3255                     TimeUtils.formatDuration(now, sb);
3256                     Slog.d(TAG, sb.toString());
3257                 }
3258                 if (mState == STATE_IDLE_MAINTENANCE) {
3259                     stepIdleStateLocked("s:early");
3260                 } else if (mLightState == LIGHT_STATE_PRE_IDLE) {
3261                     stepLightIdleStateLocked("s:predone");
3262                 } else {
3263                     stepLightIdleStateLocked("s:early");
3264                 }
3265             }
3266         }
3267     }
3268 
motionLocked()3269     void motionLocked() {
3270         if (DEBUG) Slog.d(TAG, "motionLocked()");
3271         // The motion sensor will have been disabled at this point
3272         handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
3273     }
3274 
handleMotionDetectedLocked(long timeout, String type)3275     void handleMotionDetectedLocked(long timeout, String type) {
3276         // The device is not yet active, so we want to go back to the pending idle
3277         // state to wait again for no motion.  Note that we only monitor for motion
3278         // after moving out of the inactive state, so no need to worry about that.
3279         final boolean becomeInactive = mState != STATE_ACTIVE
3280                 || mLightState == LIGHT_STATE_OVERRIDE;
3281         // We only want to change the IDLE state if it's OVERRIDE.
3282         becomeActiveLocked(type, Process.myUid(), timeout, mLightState == LIGHT_STATE_OVERRIDE);
3283         if (becomeInactive) {
3284             becomeInactiveIfAppropriateLocked();
3285         }
3286     }
3287 
receivedGenericLocationLocked(Location location)3288     void receivedGenericLocationLocked(Location location) {
3289         if (mState != STATE_LOCATING) {
3290             cancelLocatingLocked();
3291             return;
3292         }
3293         if (DEBUG) Slog.d(TAG, "Generic location: " + location);
3294         mLastGenericLocation = new Location(location);
3295         if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
3296             return;
3297         }
3298         mLocated = true;
3299         if (mNotMoving) {
3300             stepIdleStateLocked("s:location");
3301         }
3302     }
3303 
receivedGpsLocationLocked(Location location)3304     void receivedGpsLocationLocked(Location location) {
3305         if (mState != STATE_LOCATING) {
3306             cancelLocatingLocked();
3307             return;
3308         }
3309         if (DEBUG) Slog.d(TAG, "GPS location: " + location);
3310         mLastGpsLocation = new Location(location);
3311         if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
3312             return;
3313         }
3314         mLocated = true;
3315         if (mNotMoving) {
3316             stepIdleStateLocked("s:gps");
3317         }
3318     }
3319 
startMonitoringMotionLocked()3320     void startMonitoringMotionLocked() {
3321         if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()");
3322         if (mMotionSensor != null && !mMotionListener.active) {
3323             mMotionListener.registerLocked();
3324         }
3325     }
3326 
stopMonitoringMotionLocked()3327     void stopMonitoringMotionLocked() {
3328         if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()");
3329         if (mMotionSensor != null && mMotionListener.active) {
3330             mMotionListener.unregisterLocked();
3331         }
3332     }
3333 
cancelAlarmLocked()3334     void cancelAlarmLocked() {
3335         if (mNextAlarmTime != 0) {
3336             mNextAlarmTime = 0;
3337             mAlarmManager.cancel(mDeepAlarmListener);
3338         }
3339     }
3340 
cancelLightAlarmLocked()3341     void cancelLightAlarmLocked() {
3342         if (mNextLightAlarmTime != 0) {
3343             mNextLightAlarmTime = 0;
3344             mAlarmManager.cancel(mLightAlarmListener);
3345         }
3346     }
3347 
cancelLocatingLocked()3348     void cancelLocatingLocked() {
3349         if (mLocating) {
3350             LocationManager locationManager = mInjector.getLocationManager();
3351             locationManager.removeUpdates(mGenericLocationListener);
3352             locationManager.removeUpdates(mGpsLocationListener);
3353             mLocating = false;
3354         }
3355     }
3356 
cancelSensingTimeoutAlarmLocked()3357     void cancelSensingTimeoutAlarmLocked() {
3358         if (mNextSensingTimeoutAlarmTime != 0) {
3359             mNextSensingTimeoutAlarmTime = 0;
3360             mAlarmManager.cancel(mSensingTimeoutAlarmListener);
3361         }
3362     }
3363 
scheduleAlarmLocked(long delay, boolean idleUntil)3364     void scheduleAlarmLocked(long delay, boolean idleUntil) {
3365         if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
3366 
3367         if (mUseMotionSensor && mMotionSensor == null
3368                 && mState != STATE_QUICK_DOZE_DELAY
3369                 && mState != STATE_IDLE
3370                 && mState != STATE_IDLE_MAINTENANCE) {
3371             // If there is no motion sensor on this device, but we need one, then we won't schedule
3372             // alarms, because we can't determine if the device is not moving.  This effectively
3373             // turns off normal execution of device idling, although it is still possible to
3374             // manually poke it by pretending like the alarm is going off.
3375             // STATE_QUICK_DOZE_DELAY skips the motion sensing so if the state is past the motion
3376             // sensing stage (ie, is QUICK_DOZE_DELAY, IDLE, or IDLE_MAINTENANCE), then idling
3377             // can continue until the user interacts with the device.
3378             return;
3379         }
3380         mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
3381         if (idleUntil) {
3382             mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
3383                     mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
3384         } else {
3385             mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
3386                     mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
3387         }
3388     }
3389 
scheduleLightAlarmLocked(long delay)3390     void scheduleLightAlarmLocked(long delay) {
3391         if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
3392         mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
3393         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
3394                 mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
3395     }
3396 
scheduleSensingTimeoutAlarmLocked(long delay)3397     void scheduleSensingTimeoutAlarmLocked(long delay) {
3398         if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
3399         mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
3400         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
3401             "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
3402     }
3403 
buildAppIdArray(ArrayMap<String, Integer> systemApps, ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds)3404     private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
3405             ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
3406         outAppIds.clear();
3407         if (systemApps != null) {
3408             for (int i = 0; i < systemApps.size(); i++) {
3409                 outAppIds.put(systemApps.valueAt(i), true);
3410             }
3411         }
3412         if (userApps != null) {
3413             for (int i = 0; i < userApps.size(); i++) {
3414                 outAppIds.put(userApps.valueAt(i), true);
3415             }
3416         }
3417         int size = outAppIds.size();
3418         int[] appids = new int[size];
3419         for (int i = 0; i < size; i++) {
3420             appids[i] = outAppIds.keyAt(i);
3421         }
3422         return appids;
3423     }
3424 
updateWhitelistAppIdsLocked()3425     private void updateWhitelistAppIdsLocked() {
3426         mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
3427                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
3428         mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
3429                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
3430         mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
3431                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
3432         if (mLocalActivityManager != null) {
3433             mLocalActivityManager.setDeviceIdleWhitelist(
3434                     mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
3435         }
3436         if (mLocalPowerManager != null) {
3437             if (DEBUG) {
3438                 Slog.d(TAG, "Setting wakelock whitelist to "
3439                         + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
3440             }
3441             mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
3442         }
3443         passWhiteListsToForceAppStandbyTrackerLocked();
3444     }
3445 
updateTempWhitelistAppIdsLocked(int appId, boolean adding)3446     private void updateTempWhitelistAppIdsLocked(int appId, boolean adding) {
3447         final int size = mTempWhitelistAppIdEndTimes.size();
3448         if (mTempWhitelistAppIdArray.length != size) {
3449             mTempWhitelistAppIdArray = new int[size];
3450         }
3451         for (int i = 0; i < size; i++) {
3452             mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
3453         }
3454         if (mLocalActivityManager != null) {
3455             if (DEBUG) {
3456                 Slog.d(TAG, "Setting activity manager temp whitelist to "
3457                         + Arrays.toString(mTempWhitelistAppIdArray));
3458             }
3459             mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, appId,
3460                     adding);
3461         }
3462         if (mLocalPowerManager != null) {
3463             if (DEBUG) {
3464                 Slog.d(TAG, "Setting wakelock temp whitelist to "
3465                         + Arrays.toString(mTempWhitelistAppIdArray));
3466             }
3467             mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
3468         }
3469         passWhiteListsToForceAppStandbyTrackerLocked();
3470     }
3471 
reportPowerSaveWhitelistChangedLocked()3472     private void reportPowerSaveWhitelistChangedLocked() {
3473         Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
3474         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3475         getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
3476     }
3477 
reportTempWhitelistChangedLocked()3478     private void reportTempWhitelistChangedLocked() {
3479         Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
3480         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3481         getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
3482     }
3483 
passWhiteListsToForceAppStandbyTrackerLocked()3484     private void passWhiteListsToForceAppStandbyTrackerLocked() {
3485         mAppStateTracker.setPowerSaveWhitelistAppIds(
3486                 mPowerSaveWhitelistExceptIdleAppIdArray,
3487                 mPowerSaveWhitelistUserAppIdArray,
3488                 mTempWhitelistAppIdArray);
3489     }
3490 
readConfigFileLocked()3491     void readConfigFileLocked() {
3492         if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
3493         mPowerSaveWhitelistUserApps.clear();
3494         FileInputStream stream;
3495         try {
3496             stream = mConfigFile.openRead();
3497         } catch (FileNotFoundException e) {
3498             return;
3499         }
3500         try {
3501             XmlPullParser parser = Xml.newPullParser();
3502             parser.setInput(stream, StandardCharsets.UTF_8.name());
3503             readConfigFileLocked(parser);
3504         } catch (XmlPullParserException e) {
3505         } finally {
3506             try {
3507                 stream.close();
3508             } catch (IOException e) {
3509             }
3510         }
3511     }
3512 
readConfigFileLocked(XmlPullParser parser)3513     private void readConfigFileLocked(XmlPullParser parser) {
3514         final PackageManager pm = getContext().getPackageManager();
3515 
3516         try {
3517             int type;
3518             while ((type = parser.next()) != XmlPullParser.START_TAG
3519                     && type != XmlPullParser.END_DOCUMENT) {
3520                 ;
3521             }
3522 
3523             if (type != XmlPullParser.START_TAG) {
3524                 throw new IllegalStateException("no start tag found");
3525             }
3526 
3527             int outerDepth = parser.getDepth();
3528             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3529                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3530                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3531                     continue;
3532                 }
3533 
3534                 String tagName = parser.getName();
3535                 switch (tagName) {
3536                     case "wl":
3537                         String name = parser.getAttributeValue(null, "n");
3538                         if (name != null) {
3539                             try {
3540                                 ApplicationInfo ai = pm.getApplicationInfo(name,
3541                                         PackageManager.MATCH_ANY_USER);
3542                                 mPowerSaveWhitelistUserApps.put(ai.packageName,
3543                                         UserHandle.getAppId(ai.uid));
3544                             } catch (PackageManager.NameNotFoundException e) {
3545                             }
3546                         }
3547                         break;
3548                     case "un-wl":
3549                         final String packageName = parser.getAttributeValue(null, "n");
3550                         if (mPowerSaveWhitelistApps.containsKey(packageName)) {
3551                             mRemovedFromSystemWhitelistApps.put(packageName,
3552                                     mPowerSaveWhitelistApps.remove(packageName));
3553                         }
3554                         break;
3555                     default:
3556                         Slog.w(TAG, "Unknown element under <config>: "
3557                                 + parser.getName());
3558                         XmlUtils.skipCurrentTag(parser);
3559                         break;
3560                 }
3561             }
3562 
3563         } catch (IllegalStateException e) {
3564             Slog.w(TAG, "Failed parsing config " + e);
3565         } catch (NullPointerException e) {
3566             Slog.w(TAG, "Failed parsing config " + e);
3567         } catch (NumberFormatException e) {
3568             Slog.w(TAG, "Failed parsing config " + e);
3569         } catch (XmlPullParserException e) {
3570             Slog.w(TAG, "Failed parsing config " + e);
3571         } catch (IOException e) {
3572             Slog.w(TAG, "Failed parsing config " + e);
3573         } catch (IndexOutOfBoundsException e) {
3574             Slog.w(TAG, "Failed parsing config " + e);
3575         }
3576     }
3577 
writeConfigFileLocked()3578     void writeConfigFileLocked() {
3579         mHandler.removeMessages(MSG_WRITE_CONFIG);
3580         mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
3581     }
3582 
handleWriteConfigFile()3583     void handleWriteConfigFile() {
3584         final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
3585 
3586         try {
3587             synchronized (this) {
3588                 XmlSerializer out = new FastXmlSerializer();
3589                 out.setOutput(memStream, StandardCharsets.UTF_8.name());
3590                 writeConfigFileLocked(out);
3591             }
3592         } catch (IOException e) {
3593         }
3594 
3595         synchronized (mConfigFile) {
3596             FileOutputStream stream = null;
3597             try {
3598                 stream = mConfigFile.startWrite();
3599                 memStream.writeTo(stream);
3600                 stream.flush();
3601                 FileUtils.sync(stream);
3602                 stream.close();
3603                 mConfigFile.finishWrite(stream);
3604             } catch (IOException e) {
3605                 Slog.w(TAG, "Error writing config file", e);
3606                 mConfigFile.failWrite(stream);
3607             }
3608         }
3609     }
3610 
writeConfigFileLocked(XmlSerializer out)3611     void writeConfigFileLocked(XmlSerializer out) throws IOException {
3612         out.startDocument(null, true);
3613         out.startTag(null, "config");
3614         for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
3615             String name = mPowerSaveWhitelistUserApps.keyAt(i);
3616             out.startTag(null, "wl");
3617             out.attribute(null, "n", name);
3618             out.endTag(null, "wl");
3619         }
3620         for (int i = 0; i < mRemovedFromSystemWhitelistApps.size(); i++) {
3621             out.startTag(null, "un-wl");
3622             out.attribute(null, "n", mRemovedFromSystemWhitelistApps.keyAt(i));
3623             out.endTag(null, "un-wl");
3624         }
3625         out.endTag(null, "config");
3626         out.endDocument();
3627     }
3628 
dumpHelp(PrintWriter pw)3629     static void dumpHelp(PrintWriter pw) {
3630         pw.println("Device idle controller (deviceidle) commands:");
3631         pw.println("  help");
3632         pw.println("    Print this help text.");
3633         pw.println("  step [light|deep]");
3634         pw.println("    Immediately step to next state, without waiting for alarm.");
3635         pw.println("  force-idle [light|deep]");
3636         pw.println("    Force directly into idle mode, regardless of other device state.");
3637         pw.println("  force-inactive");
3638         pw.println("    Force to be inactive, ready to freely step idle states.");
3639         pw.println("  unforce");
3640         pw.println("    Resume normal functioning after force-idle or force-inactive.");
3641         pw.println("  get [light|deep|force|screen|charging|network]");
3642         pw.println("    Retrieve the current given state.");
3643         pw.println("  disable [light|deep|all]");
3644         pw.println("    Completely disable device idle mode.");
3645         pw.println("  enable [light|deep|all]");
3646         pw.println("    Re-enable device idle mode after it had previously been disabled.");
3647         pw.println("  enabled [light|deep|all]");
3648         pw.println("    Print 1 if device idle mode is currently enabled, else 0.");
3649         pw.println("  whitelist");
3650         pw.println("    Print currently whitelisted apps.");
3651         pw.println("  whitelist [package ...]");
3652         pw.println("    Add (prefix with +) or remove (prefix with -) packages.");
3653         pw.println("  sys-whitelist [package ...|reset]");
3654         pw.println("    Prefix the package with '-' to remove it from the system whitelist or '+'"
3655                 + " to put it back in the system whitelist.");
3656         pw.println("    Note that only packages that were"
3657                 + " earlier removed from the system whitelist can be added back.");
3658         pw.println("    reset will reset the whitelist to the original state");
3659         pw.println("    Prints the system whitelist if no arguments are specified");
3660         pw.println("  except-idle-whitelist [package ...|reset]");
3661         pw.println("    Prefix the package with '+' to add it to whitelist or "
3662                 + "'=' to check if it is already whitelisted");
3663         pw.println("    [reset] will reset the whitelist to it's original state");
3664         pw.println("    Note that unlike <whitelist> cmd, "
3665                 + "changes made using this won't be persisted across boots");
3666         pw.println("  tempwhitelist");
3667         pw.println("    Print packages that are temporarily whitelisted.");
3668         pw.println("  tempwhitelist [-u USER] [-d DURATION] [-r] [package]");
3669         pw.println("    Temporarily place package in whitelist for DURATION milliseconds.");
3670         pw.println("    If no DURATION is specified, 10 seconds is used");
3671         pw.println("    If [-r] option is used, then the package is removed from temp whitelist "
3672                 + "and any [-d] is ignored");
3673         pw.println("  motion");
3674         pw.println("    Simulate a motion event to bring the device out of deep doze");
3675         pw.println("  pre-idle-factor [0|1|2]");
3676         pw.println("    Set a new factor to idle time before step to idle"
3677                 + "(inactive_to and idle_after_inactive_to)");
3678         pw.println("  reset-pre-idle-factor");
3679         pw.println("    Reset factor to idle time to default");
3680     }
3681 
3682     class Shell extends ShellCommand {
3683         int userId = UserHandle.USER_SYSTEM;
3684 
3685         @Override
onCommand(String cmd)3686         public int onCommand(String cmd) {
3687             return onShellCommand(this, cmd);
3688         }
3689 
3690         @Override
onHelp()3691         public void onHelp() {
3692             PrintWriter pw = getOutPrintWriter();
3693             dumpHelp(pw);
3694         }
3695     }
3696 
onShellCommand(Shell shell, String cmd)3697     int onShellCommand(Shell shell, String cmd) {
3698         PrintWriter pw = shell.getOutPrintWriter();
3699         if ("step".equals(cmd)) {
3700             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3701                     null);
3702             synchronized (this) {
3703                 long token = Binder.clearCallingIdentity();
3704                 String arg = shell.getNextArg();
3705                 try {
3706                     if (arg == null || "deep".equals(arg)) {
3707                         stepIdleStateLocked("s:shell");
3708                         pw.print("Stepped to deep: ");
3709                         pw.println(stateToString(mState));
3710                     } else if ("light".equals(arg)) {
3711                         stepLightIdleStateLocked("s:shell");
3712                         pw.print("Stepped to light: "); pw.println(lightStateToString(mLightState));
3713                     } else {
3714                         pw.println("Unknown idle mode: " + arg);
3715                     }
3716                 } finally {
3717                     Binder.restoreCallingIdentity(token);
3718                 }
3719             }
3720         } else if ("force-idle".equals(cmd)) {
3721             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3722                     null);
3723             synchronized (this) {
3724                 long token = Binder.clearCallingIdentity();
3725                 String arg = shell.getNextArg();
3726                 try {
3727                     if (arg == null || "deep".equals(arg)) {
3728                         if (!mDeepEnabled) {
3729                             pw.println("Unable to go deep idle; not enabled");
3730                             return -1;
3731                         }
3732                         mForceIdle = true;
3733                         becomeInactiveIfAppropriateLocked();
3734                         int curState = mState;
3735                         while (curState != STATE_IDLE) {
3736                             stepIdleStateLocked("s:shell");
3737                             if (curState == mState) {
3738                                 pw.print("Unable to go deep idle; stopped at ");
3739                                 pw.println(stateToString(mState));
3740                                 exitForceIdleLocked();
3741                                 return -1;
3742                             }
3743                             curState = mState;
3744                         }
3745                         pw.println("Now forced in to deep idle mode");
3746                     } else if ("light".equals(arg)) {
3747                         mForceIdle = true;
3748                         becomeInactiveIfAppropriateLocked();
3749                         int curLightState = mLightState;
3750                         while (curLightState != LIGHT_STATE_IDLE) {
3751                             stepLightIdleStateLocked("s:shell");
3752                             if (curLightState == mLightState) {
3753                                 pw.print("Unable to go light idle; stopped at ");
3754                                 pw.println(lightStateToString(mLightState));
3755                                 exitForceIdleLocked();
3756                                 return -1;
3757                             }
3758                             curLightState = mLightState;
3759                         }
3760                         pw.println("Now forced in to light idle mode");
3761                     } else {
3762                         pw.println("Unknown idle mode: " + arg);
3763                     }
3764                 } finally {
3765                     Binder.restoreCallingIdentity(token);
3766                 }
3767             }
3768         } else if ("force-inactive".equals(cmd)) {
3769             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3770                     null);
3771             synchronized (this) {
3772                 long token = Binder.clearCallingIdentity();
3773                 try {
3774                     mForceIdle = true;
3775                     becomeInactiveIfAppropriateLocked();
3776                     pw.print("Light state: ");
3777                     pw.print(lightStateToString(mLightState));
3778                     pw.print(", deep state: ");
3779                     pw.println(stateToString(mState));
3780                 } finally {
3781                     Binder.restoreCallingIdentity(token);
3782                 }
3783             }
3784         } else if ("unforce".equals(cmd)) {
3785             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3786                     null);
3787             synchronized (this) {
3788                 long token = Binder.clearCallingIdentity();
3789                 try {
3790                     exitForceIdleLocked();
3791                     pw.print("Light state: ");
3792                     pw.print(lightStateToString(mLightState));
3793                     pw.print(", deep state: ");
3794                     pw.println(stateToString(mState));
3795                 } finally {
3796                     Binder.restoreCallingIdentity(token);
3797                 }
3798             }
3799         } else if ("get".equals(cmd)) {
3800             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3801                     null);
3802             synchronized (this) {
3803                 String arg = shell.getNextArg();
3804                 if (arg != null) {
3805                     long token = Binder.clearCallingIdentity();
3806                     try {
3807                         switch (arg) {
3808                             case "light": pw.println(lightStateToString(mLightState)); break;
3809                             case "deep": pw.println(stateToString(mState)); break;
3810                             case "force": pw.println(mForceIdle); break;
3811                             case "quick": pw.println(mQuickDozeActivated); break;
3812                             case "screen": pw.println(mScreenOn); break;
3813                             case "charging": pw.println(mCharging); break;
3814                             case "network": pw.println(mNetworkConnected); break;
3815                             default: pw.println("Unknown get option: " + arg); break;
3816                         }
3817                     } finally {
3818                         Binder.restoreCallingIdentity(token);
3819                     }
3820                 } else {
3821                     pw.println("Argument required");
3822                 }
3823             }
3824         } else if ("disable".equals(cmd)) {
3825             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3826                     null);
3827             synchronized (this) {
3828                 long token = Binder.clearCallingIdentity();
3829                 String arg = shell.getNextArg();
3830                 try {
3831                     boolean becomeActive = false;
3832                     boolean valid = false;
3833                     if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
3834                         valid = true;
3835                         if (mDeepEnabled) {
3836                             mDeepEnabled = false;
3837                             becomeActive = true;
3838                             pw.println("Deep idle mode disabled");
3839                         }
3840                     }
3841                     if (arg == null || "light".equals(arg) || "all".equals(arg)) {
3842                         valid = true;
3843                         if (mLightEnabled) {
3844                             mLightEnabled = false;
3845                             becomeActive = true;
3846                             pw.println("Light idle mode disabled");
3847                         }
3848                     }
3849                     if (becomeActive) {
3850                         mActiveReason = ACTIVE_REASON_FORCED;
3851                         becomeActiveLocked((arg == null ? "all" : arg) + "-disabled",
3852                                 Process.myUid());
3853                     }
3854                     if (!valid) {
3855                         pw.println("Unknown idle mode: " + arg);
3856                     }
3857                 } finally {
3858                     Binder.restoreCallingIdentity(token);
3859                 }
3860             }
3861         } else if ("enable".equals(cmd)) {
3862             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
3863                     null);
3864             synchronized (this) {
3865                 long token = Binder.clearCallingIdentity();
3866                 String arg = shell.getNextArg();
3867                 try {
3868                     boolean becomeInactive = false;
3869                     boolean valid = false;
3870                     if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
3871                         valid = true;
3872                         if (!mDeepEnabled) {
3873                             mDeepEnabled = true;
3874                             becomeInactive = true;
3875                             pw.println("Deep idle mode enabled");
3876                         }
3877                     }
3878                     if (arg == null || "light".equals(arg) || "all".equals(arg)) {
3879                         valid = true;
3880                         if (!mLightEnabled) {
3881                             mLightEnabled = true;
3882                             becomeInactive = true;
3883                             pw.println("Light idle mode enable");
3884                         }
3885                     }
3886                     if (becomeInactive) {
3887                         becomeInactiveIfAppropriateLocked();
3888                     }
3889                     if (!valid) {
3890                         pw.println("Unknown idle mode: " + arg);
3891                     }
3892                 } finally {
3893                     Binder.restoreCallingIdentity(token);
3894                 }
3895             }
3896         } else if ("enabled".equals(cmd)) {
3897             synchronized (this) {
3898                 String arg = shell.getNextArg();
3899                 if (arg == null || "all".equals(arg)) {
3900                     pw.println(mDeepEnabled && mLightEnabled ? "1" : 0);
3901                 } else if ("deep".equals(arg)) {
3902                     pw.println(mDeepEnabled ? "1" : 0);
3903                 } else if ("light".equals(arg)) {
3904                     pw.println(mLightEnabled ? "1" : 0);
3905                 } else {
3906                     pw.println("Unknown idle mode: " + arg);
3907                 }
3908             }
3909         } else if ("whitelist".equals(cmd)) {
3910             String arg = shell.getNextArg();
3911             if (arg != null) {
3912                 getContext().enforceCallingOrSelfPermission(
3913                         android.Manifest.permission.DEVICE_POWER, null);
3914                 long token = Binder.clearCallingIdentity();
3915                 try {
3916                     do {
3917                         if (arg.length() < 1 || (arg.charAt(0) != '-'
3918                                 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
3919                             pw.println("Package must be prefixed with +, -, or =: " + arg);
3920                             return -1;
3921                         }
3922                         char op = arg.charAt(0);
3923                         String pkg = arg.substring(1);
3924                         if (op == '+') {
3925                             if (addPowerSaveWhitelistAppInternal(pkg)) {
3926                                 pw.println("Added: " + pkg);
3927                             } else {
3928                                 pw.println("Unknown package: " + pkg);
3929                             }
3930                         } else if (op == '-') {
3931                             if (removePowerSaveWhitelistAppInternal(pkg)) {
3932                                 pw.println("Removed: " + pkg);
3933                             }
3934                         } else {
3935                             pw.println(getPowerSaveWhitelistAppInternal(pkg));
3936                         }
3937                     } while ((arg=shell.getNextArg()) != null);
3938                 } finally {
3939                     Binder.restoreCallingIdentity(token);
3940                 }
3941             } else {
3942                 synchronized (this) {
3943                     for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
3944                         pw.print("system-excidle,");
3945                         pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
3946                         pw.print(",");
3947                         pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
3948                     }
3949                     for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
3950                         pw.print("system,");
3951                         pw.print(mPowerSaveWhitelistApps.keyAt(j));
3952                         pw.print(",");
3953                         pw.println(mPowerSaveWhitelistApps.valueAt(j));
3954                     }
3955                     for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
3956                         pw.print("user,");
3957                         pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
3958                         pw.print(",");
3959                         pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
3960                     }
3961                 }
3962             }
3963         } else if ("tempwhitelist".equals(cmd)) {
3964             long duration = 10000;
3965             boolean removePkg = false;
3966             String opt;
3967             while ((opt=shell.getNextOption()) != null) {
3968                 if ("-u".equals(opt)) {
3969                     opt = shell.getNextArg();
3970                     if (opt == null) {
3971                         pw.println("-u requires a user number");
3972                         return -1;
3973                     }
3974                     shell.userId = Integer.parseInt(opt);
3975                 } else if ("-d".equals(opt)) {
3976                     opt = shell.getNextArg();
3977                     if (opt == null) {
3978                         pw.println("-d requires a duration");
3979                         return -1;
3980                     }
3981                     duration = Long.parseLong(opt);
3982                 } else if ("-r".equals(opt)) {
3983                     removePkg = true;
3984                 }
3985             }
3986             String arg = shell.getNextArg();
3987             if (arg != null) {
3988                 try {
3989                     if (removePkg) {
3990                         removePowerSaveTempWhitelistAppChecked(arg, shell.userId);
3991                     } else {
3992                         addPowerSaveTempWhitelistAppChecked(arg, duration, shell.userId, "shell");
3993                     }
3994                 } catch (Exception e) {
3995                     pw.println("Failed: " + e);
3996                     return -1;
3997                 }
3998             } else if (removePkg) {
3999                 pw.println("[-r] requires a package name");
4000                 return -1;
4001             } else {
4002                 dumpTempWhitelistSchedule(pw, false);
4003             }
4004         } else if ("except-idle-whitelist".equals(cmd)) {
4005             getContext().enforceCallingOrSelfPermission(
4006                     android.Manifest.permission.DEVICE_POWER, null);
4007             final long token = Binder.clearCallingIdentity();
4008             try {
4009                 String arg = shell.getNextArg();
4010                 if (arg == null) {
4011                     pw.println("No arguments given");
4012                     return -1;
4013                 } else if ("reset".equals(arg)) {
4014                     resetPowerSaveWhitelistExceptIdleInternal();
4015                 } else {
4016                     do {
4017                         if (arg.length() < 1 || (arg.charAt(0) != '-'
4018                                 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
4019                             pw.println("Package must be prefixed with +, -, or =: " + arg);
4020                             return -1;
4021                         }
4022                         char op = arg.charAt(0);
4023                         String pkg = arg.substring(1);
4024                         if (op == '+') {
4025                             if (addPowerSaveWhitelistExceptIdleInternal(pkg)) {
4026                                 pw.println("Added: " + pkg);
4027                             } else {
4028                                 pw.println("Unknown package: " + pkg);
4029                             }
4030                         } else if (op == '=') {
4031                             pw.println(getPowerSaveWhitelistExceptIdleInternal(pkg));
4032                         } else {
4033                             pw.println("Unknown argument: " + arg);
4034                             return -1;
4035                         }
4036                     } while ((arg = shell.getNextArg()) != null);
4037                 }
4038             } finally {
4039                 Binder.restoreCallingIdentity(token);
4040             }
4041         } else if ("sys-whitelist".equals(cmd)) {
4042             String arg = shell.getNextArg();
4043             if (arg != null) {
4044                 getContext().enforceCallingOrSelfPermission(
4045                         android.Manifest.permission.DEVICE_POWER, null);
4046                 final long token = Binder.clearCallingIdentity();
4047                 try {
4048                     if ("reset".equals(arg)) {
4049                         resetSystemPowerWhitelistInternal();
4050                     } else {
4051                         do {
4052                             if (arg.length() < 1
4053                                     || (arg.charAt(0) != '-' && arg.charAt(0) != '+')) {
4054                                 pw.println("Package must be prefixed with + or - " + arg);
4055                                 return -1;
4056                             }
4057                             final char op = arg.charAt(0);
4058                             final String pkg = arg.substring(1);
4059                             switch (op) {
4060                                 case '+':
4061                                     if (restoreSystemPowerWhitelistAppInternal(pkg)) {
4062                                         pw.println("Restored " + pkg);
4063                                     }
4064                                     break;
4065                                 case '-':
4066                                     if (removeSystemPowerWhitelistAppInternal(pkg)) {
4067                                         pw.println("Removed " + pkg);
4068                                     }
4069                                     break;
4070                             }
4071                         } while ((arg = shell.getNextArg()) != null);
4072                     }
4073                 } finally {
4074                     Binder.restoreCallingIdentity(token);
4075                 }
4076             } else {
4077                 synchronized (this) {
4078                     for (int j = 0; j < mPowerSaveWhitelistApps.size(); j++) {
4079                         pw.print(mPowerSaveWhitelistApps.keyAt(j));
4080                         pw.print(",");
4081                         pw.println(mPowerSaveWhitelistApps.valueAt(j));
4082                     }
4083                 }
4084             }
4085         } else if ("motion".equals(cmd)) {
4086             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4087                     null);
4088             synchronized (this) {
4089                 long token = Binder.clearCallingIdentity();
4090                 try {
4091                     motionLocked();
4092                     pw.print("Light state: ");
4093                     pw.print(lightStateToString(mLightState));
4094                     pw.print(", deep state: ");
4095                     pw.println(stateToString(mState));
4096                 } finally {
4097                     Binder.restoreCallingIdentity(token);
4098                 }
4099             }
4100         } else if ("pre-idle-factor".equals(cmd)) {
4101             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4102                     null);
4103             synchronized (this) {
4104                 long token = Binder.clearCallingIdentity();
4105                 int ret  = SET_IDLE_FACTOR_RESULT_UNINIT;
4106                 try {
4107                     String arg = shell.getNextArg();
4108                     boolean valid = false;
4109                     int mode = 0;
4110                     if (arg != null) {
4111                         mode = Integer.parseInt(arg);
4112                         ret = setPreIdleTimeoutMode(mode);
4113                         if (ret == SET_IDLE_FACTOR_RESULT_OK) {
4114                             pw.println("pre-idle-factor: " + mode);
4115                             valid = true;
4116                         } else if (ret == SET_IDLE_FACTOR_RESULT_NOT_SUPPORT) {
4117                             valid = true;
4118                             pw.println("Deep idle not supported");
4119                         } else if (ret == SET_IDLE_FACTOR_RESULT_IGNORED) {
4120                             valid = true;
4121                             pw.println("Idle timeout factor not changed");
4122                         }
4123                     }
4124                     if (!valid) {
4125                         pw.println("Unknown idle timeout factor: " + arg
4126                                 + ",(error code: " + ret + ")");
4127                     }
4128                 } catch (NumberFormatException e) {
4129                     pw.println("Unknown idle timeout factor"
4130                             + ",(error code: " + ret + ")");
4131                 } finally {
4132                     Binder.restoreCallingIdentity(token);
4133                 }
4134             }
4135         } else if ("reset-pre-idle-factor".equals(cmd)) {
4136             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
4137                     null);
4138             synchronized (this) {
4139                 long token = Binder.clearCallingIdentity();
4140                 try {
4141                     resetPreIdleTimeoutMode();
4142                 } finally {
4143                     Binder.restoreCallingIdentity(token);
4144                 }
4145             }
4146         } else {
4147             return shell.handleDefaultCommands(cmd);
4148         }
4149         return 0;
4150     }
4151 
dump(FileDescriptor fd, PrintWriter pw, String[] args)4152     void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4153         if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
4154 
4155         if (args != null) {
4156             int userId = UserHandle.USER_SYSTEM;
4157             for (int i=0; i<args.length; i++) {
4158                 String arg = args[i];
4159                 if ("-h".equals(arg)) {
4160                     dumpHelp(pw);
4161                     return;
4162                 } else if ("-u".equals(arg)) {
4163                     i++;
4164                     if (i < args.length) {
4165                         arg = args[i];
4166                         userId = Integer.parseInt(arg);
4167                     }
4168                 } else if ("-a".equals(arg)) {
4169                     // Ignore, we always dump all.
4170                 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
4171                     pw.println("Unknown option: " + arg);
4172                     return;
4173                 } else {
4174                     Shell shell = new Shell();
4175                     shell.userId = userId;
4176                     String[] newArgs = new String[args.length-i];
4177                     System.arraycopy(args, i, newArgs, 0, args.length-i);
4178                     shell.exec(mBinderService, null, fd, null, newArgs, null,
4179                             new ResultReceiver(null));
4180                     return;
4181                 }
4182             }
4183         }
4184 
4185         synchronized (this) {
4186             mConstants.dump(pw);
4187 
4188             if (mEventCmds[0] != EVENT_NULL) {
4189                 pw.println("  Idling history:");
4190                 long now = SystemClock.elapsedRealtime();
4191                 for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) {
4192                     int cmd = mEventCmds[i];
4193                     if (cmd == EVENT_NULL) {
4194                         continue;
4195                     }
4196                     String label;
4197                     switch (mEventCmds[i]) {
4198                         case EVENT_NORMAL:              label = "     normal"; break;
4199                         case EVENT_LIGHT_IDLE:          label = " light-idle"; break;
4200                         case EVENT_LIGHT_MAINTENANCE:   label = "light-maint"; break;
4201                         case EVENT_DEEP_IDLE:           label = "  deep-idle"; break;
4202                         case EVENT_DEEP_MAINTENANCE:    label = " deep-maint"; break;
4203                         default:                        label = "         ??"; break;
4204                     }
4205                     pw.print("    ");
4206                     pw.print(label);
4207                     pw.print(": ");
4208                     TimeUtils.formatDuration(mEventTimes[i], now, pw);
4209                     if (mEventReasons[i] != null) {
4210                         pw.print(" (");
4211                         pw.print(mEventReasons[i]);
4212                         pw.print(")");
4213                     }
4214                     pw.println();
4215 
4216                 }
4217             }
4218 
4219             int size = mPowerSaveWhitelistAppsExceptIdle.size();
4220             if (size > 0) {
4221                 pw.println("  Whitelist (except idle) system apps:");
4222                 for (int i = 0; i < size; i++) {
4223                     pw.print("    ");
4224                     pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
4225                 }
4226             }
4227             size = mPowerSaveWhitelistApps.size();
4228             if (size > 0) {
4229                 pw.println("  Whitelist system apps:");
4230                 for (int i = 0; i < size; i++) {
4231                     pw.print("    ");
4232                     pw.println(mPowerSaveWhitelistApps.keyAt(i));
4233                 }
4234             }
4235             size = mRemovedFromSystemWhitelistApps.size();
4236             if (size > 0) {
4237                 pw.println("  Removed from whitelist system apps:");
4238                 for (int i = 0; i < size; i++) {
4239                     pw.print("    ");
4240                     pw.println(mRemovedFromSystemWhitelistApps.keyAt(i));
4241                 }
4242             }
4243             size = mPowerSaveWhitelistUserApps.size();
4244             if (size > 0) {
4245                 pw.println("  Whitelist user apps:");
4246                 for (int i = 0; i < size; i++) {
4247                     pw.print("    ");
4248                     pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
4249                 }
4250             }
4251             size = mPowerSaveWhitelistExceptIdleAppIds.size();
4252             if (size > 0) {
4253                 pw.println("  Whitelist (except idle) all app ids:");
4254                 for (int i = 0; i < size; i++) {
4255                     pw.print("    ");
4256                     pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
4257                     pw.println();
4258                 }
4259             }
4260             size = mPowerSaveWhitelistUserAppIds.size();
4261             if (size > 0) {
4262                 pw.println("  Whitelist user app ids:");
4263                 for (int i = 0; i < size; i++) {
4264                     pw.print("    ");
4265                     pw.print(mPowerSaveWhitelistUserAppIds.keyAt(i));
4266                     pw.println();
4267                 }
4268             }
4269             size = mPowerSaveWhitelistAllAppIds.size();
4270             if (size > 0) {
4271                 pw.println("  Whitelist all app ids:");
4272                 for (int i = 0; i < size; i++) {
4273                     pw.print("    ");
4274                     pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
4275                     pw.println();
4276                 }
4277             }
4278             dumpTempWhitelistSchedule(pw, true);
4279 
4280             size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
4281             if (size > 0) {
4282                 pw.println("  Temp whitelist app ids:");
4283                 for (int i = 0; i < size; i++) {
4284                     pw.print("    ");
4285                     pw.print(mTempWhitelistAppIdArray[i]);
4286                     pw.println();
4287                 }
4288             }
4289 
4290             pw.print("  mLightEnabled="); pw.print(mLightEnabled);
4291             pw.print("  mDeepEnabled="); pw.println(mDeepEnabled);
4292             pw.print("  mForceIdle="); pw.println(mForceIdle);
4293             pw.print("  mUseMotionSensor="); pw.print(mUseMotionSensor);
4294             if (mUseMotionSensor) {
4295                 pw.print(" mMotionSensor="); pw.println(mMotionSensor);
4296             } else {
4297                 pw.println();
4298             }
4299             pw.print("  mScreenOn="); pw.println(mScreenOn);
4300             pw.print("  mScreenLocked="); pw.println(mScreenLocked);
4301             pw.print("  mNetworkConnected="); pw.println(mNetworkConnected);
4302             pw.print("  mCharging="); pw.println(mCharging);
4303             if (mConstraints.size() != 0) {
4304                 pw.println("  mConstraints={");
4305                 for (int i = 0; i < mConstraints.size(); i++) {
4306                     final DeviceIdleConstraintTracker tracker = mConstraints.valueAt(i);
4307                     pw.print("    \""); pw.print(tracker.name); pw.print("\"=");
4308                     if (tracker.minState == mState) {
4309                         pw.println(tracker.active);
4310                     } else {
4311                         pw.print("ignored <mMinState="); pw.print(stateToString(tracker.minState));
4312                         pw.println(">");
4313                     }
4314                 }
4315                 pw.println("  }");
4316             }
4317             if (mUseMotionSensor) {
4318                 pw.print("  mMotionActive="); pw.println(mMotionListener.active);
4319                 pw.print("  mNotMoving="); pw.println(mNotMoving);
4320             }
4321             pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
4322                     pw.print(mHasGps); pw.print(" mHasNetwork=");
4323                     pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
4324             if (mLastGenericLocation != null) {
4325                 pw.print("  mLastGenericLocation="); pw.println(mLastGenericLocation);
4326             }
4327             if (mLastGpsLocation != null) {
4328                 pw.print("  mLastGpsLocation="); pw.println(mLastGpsLocation);
4329             }
4330             pw.print("  mState="); pw.print(stateToString(mState));
4331             pw.print(" mLightState=");
4332             pw.println(lightStateToString(mLightState));
4333             pw.print("  mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
4334             pw.println();
4335             if (mActiveIdleOpCount != 0) {
4336                 pw.print("  mActiveIdleOpCount="); pw.println(mActiveIdleOpCount);
4337             }
4338             if (mNextAlarmTime != 0) {
4339                 pw.print("  mNextAlarmTime=");
4340                 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
4341                 pw.println();
4342             }
4343             if (mNextIdlePendingDelay != 0) {
4344                 pw.print("  mNextIdlePendingDelay=");
4345                 TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
4346                 pw.println();
4347             }
4348             if (mNextIdleDelay != 0) {
4349                 pw.print("  mNextIdleDelay=");
4350                 TimeUtils.formatDuration(mNextIdleDelay, pw);
4351                 pw.println();
4352             }
4353             if (mNextLightIdleDelay != 0) {
4354                 pw.print("  mNextIdleDelay=");
4355                 TimeUtils.formatDuration(mNextLightIdleDelay, pw);
4356                 pw.println();
4357             }
4358             if (mNextLightAlarmTime != 0) {
4359                 pw.print("  mNextLightAlarmTime=");
4360                 TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
4361                 pw.println();
4362             }
4363             if (mCurIdleBudget != 0) {
4364                 pw.print("  mCurIdleBudget=");
4365                 TimeUtils.formatDuration(mCurIdleBudget, pw);
4366                 pw.println();
4367             }
4368             if (mMaintenanceStartTime != 0) {
4369                 pw.print("  mMaintenanceStartTime=");
4370                 TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw);
4371                 pw.println();
4372             }
4373             if (mJobsActive) {
4374                 pw.print("  mJobsActive="); pw.println(mJobsActive);
4375             }
4376             if (mAlarmsActive) {
4377                 pw.print("  mAlarmsActive="); pw.println(mAlarmsActive);
4378             }
4379             if (Math.abs(mPreIdleFactor - 1.0f) > MIN_PRE_IDLE_FACTOR_CHANGE) {
4380                 pw.print("  mPreIdleFactor="); pw.println(mPreIdleFactor);
4381             }
4382         }
4383     }
4384 
dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle)4385     void dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle) {
4386         final int size = mTempWhitelistAppIdEndTimes.size();
4387         if (size > 0) {
4388             String prefix = "";
4389             if (printTitle) {
4390                 pw.println("  Temp whitelist schedule:");
4391                 prefix = "    ";
4392             }
4393             final long timeNow = SystemClock.elapsedRealtime();
4394             for (int i = 0; i < size; i++) {
4395                 pw.print(prefix);
4396                 pw.print("UID=");
4397                 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
4398                 pw.print(": ");
4399                 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
4400                 TimeUtils.formatDuration(entry.first.value, timeNow, pw);
4401                 pw.print(" - ");
4402                 pw.println(entry.second);
4403             }
4404         }
4405     }
4406  }
4407