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