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