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