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