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