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