blob: 8316a2625ccd53df2dcdebdff0686f5ae2b0dcb6 [file] [log] [blame]
Aurimas Liutikas88c7ff12023-08-10 12:42:26 -07001/*
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
17package com.android.server;
18
19import static android.os.PowerExemptionManager.REASON_SHELL;
20import static android.os.PowerExemptionManager.REASON_UNKNOWN;
21import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
22import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
23import static android.os.Process.INVALID_UID;
24
25import android.Manifest;
26import android.annotation.NonNull;
27import android.annotation.Nullable;
28import android.annotation.SuppressLint;
29import android.app.ActivityManager;
30import android.app.ActivityManagerInternal;
31import android.app.AlarmManager;
32import android.app.BroadcastOptions;
33import android.content.BroadcastReceiver;
34import android.content.Context;
35import android.content.IIntentReceiver;
36import android.content.Intent;
37import android.content.IntentFilter;
38import android.content.pm.ApplicationInfo;
39import android.content.pm.PackageManager;
40import android.content.pm.PackageManager.NameNotFoundException;
41import android.content.pm.PackageManagerInternal;
42import android.content.res.Resources;
43import android.hardware.Sensor;
44import android.hardware.SensorEvent;
45import android.hardware.SensorEventListener;
46import android.hardware.SensorManager;
47import android.hardware.TriggerEvent;
48import android.hardware.TriggerEventListener;
49import android.location.Location;
50import android.location.LocationListener;
51import android.location.LocationManager;
52import android.location.LocationRequest;
53import android.net.ConnectivityManager;
54import android.net.INetworkPolicyManager;
55import android.net.NetworkInfo;
56import android.net.Uri;
57import android.os.BatteryManager;
58import android.os.BatteryStats;
59import android.os.Binder;
60import android.os.Bundle;
61import android.os.Environment;
62import android.os.Handler;
63import android.os.IDeviceIdleController;
64import android.os.Looper;
65import android.os.Message;
66import android.os.PowerExemptionManager;
67import android.os.PowerExemptionManager.ReasonCode;
68import android.os.PowerExemptionManager.TempAllowListType;
69import android.os.PowerManager;
70import android.os.PowerManager.ServiceType;
71import android.os.PowerManagerInternal;
72import android.os.Process;
73import android.os.RemoteException;
74import android.os.ResultReceiver;
75import android.os.ServiceManager;
76import android.os.ShellCallback;
77import android.os.ShellCommand;
78import android.os.SystemClock;
79import android.os.Trace;
80import android.os.UserHandle;
81import android.provider.DeviceConfig;
82import android.telephony.TelephonyCallback;
83import android.telephony.TelephonyManager;
84import android.telephony.emergency.EmergencyNumber;
85import android.util.ArrayMap;
86import android.util.ArraySet;
87import android.util.AtomicFile;
88import android.util.MutableLong;
89import android.util.Pair;
90import android.util.Slog;
91import android.util.SparseArray;
92import android.util.SparseBooleanArray;
93import android.util.TimeUtils;
94import android.util.Xml;
95
96import com.android.internal.annotations.GuardedBy;
97import com.android.internal.annotations.VisibleForTesting;
98import com.android.internal.app.IBatteryStats;
99import com.android.internal.util.ArrayUtils;
100import com.android.internal.util.DumpUtils;
101import com.android.internal.util.FastXmlSerializer;
102import com.android.internal.util.XmlUtils;
103import com.android.modules.expresslog.Counter;
104import com.android.server.am.BatteryStatsService;
105import com.android.server.deviceidle.ConstraintController;
106import com.android.server.deviceidle.DeviceIdleConstraintTracker;
107import com.android.server.deviceidle.IDeviceIdleConstraint;
108import com.android.server.deviceidle.TvConstraintController;
109import com.android.server.net.NetworkPolicyManagerInternal;
110import com.android.server.wm.ActivityTaskManagerInternal;
111
112import org.xmlpull.v1.XmlPullParser;
113import org.xmlpull.v1.XmlPullParserException;
114import org.xmlpull.v1.XmlSerializer;
115
116import java.io.ByteArrayOutputStream;
117import java.io.File;
118import java.io.FileDescriptor;
119import java.io.FileInputStream;
120import java.io.FileNotFoundException;
121import java.io.FileOutputStream;
122import java.io.IOException;
123import java.io.PrintWriter;
124import java.nio.charset.StandardCharsets;
125import java.util.Arrays;
126import java.util.Collections;
127import java.util.List;
128import 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 */
300public 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
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
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
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. */
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. */
792 private void postStationaryStatusUpdated() {
793 mHandler.sendEmptyMessage(MSG_REPORT_STATIONARY_STATUS);
794 }
795
796 @GuardedBy("this")
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
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
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
839 private void registerTempAllowlistChangeListener(
840 @NonNull PowerAllowlistInternal.TempAllowlistChangeListener listener) {
841 synchronized (this) {
842 mTempAllowlistChangeListeners.add(listener);
843 }
844 }
845
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
865 public boolean isActive() {
866 return active;
867 }
868
869 @Override
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
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
891 public void onAccuracyChanged(Sensor sensor, int accuracy) {}
892
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
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
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
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
1476 private long getTimeout(long defTimeout, long compTimeout) {
1477 return (!COMPRESS_TIME || defTimeout < compTimeout) ? defTimeout : compTimeout;
1478 }
1479
1480
1481 @Override
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
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
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 {
1836 MyHandler(Looper looper) {
1837 super(looper);
1838 }
1839
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 {
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
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
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
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
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
2087 public String[] getRemovedSystemPowerWhitelistApps() {
2088 return getRemovedSystemPowerWhitelistAppsInternal(
2089 Binder.getCallingUid(), UserHandle.getCallingUserId());
2090 }
2091
2092 @Override public String[] getSystemPowerWhitelistExceptIdle() {
2093 return getSystemPowerWhitelistExceptIdleInternal(
2094 Binder.getCallingUid(), UserHandle.getCallingUserId());
2095 }
2096
2097 @Override public String[] getSystemPowerWhitelist() {
2098 return getSystemPowerWhitelistInternal(
2099 Binder.getCallingUid(), UserHandle.getCallingUserId());
2100 }
2101
2102 @Override public String[] getUserPowerWhitelist() {
2103 return getUserPowerWhitelistInternal(
2104 Binder.getCallingUid(), UserHandle.getCallingUserId());
2105 }
2106
2107 @Override public String[] getFullPowerWhitelistExceptIdle() {
2108 return getFullPowerWhitelistExceptIdleInternal(
2109 Binder.getCallingUid(), UserHandle.getCallingUserId());
2110 }
2111
2112 @Override public String[] getFullPowerWhitelist() {
2113 return getFullPowerWhitelistInternal(
2114 Binder.getCallingUid(), UserHandle.getCallingUserId());
2115 }
2116
2117 @Override public int[] getAppIdWhitelistExceptIdle() {
2118 return getAppIdWhitelistExceptIdleInternal();
2119 }
2120
2121 @Override public int[] getAppIdWhitelist() {
2122 return getAppIdWhitelistInternal();
2123 }
2124
2125 @Override public int[] getAppIdUserWhitelist() {
2126 return getAppIdUserWhitelistInternal();
2127 }
2128
2129 @Override public int[] getAppIdTempWhitelist() {
2130 return getAppIdTempWhitelistInternal();
2131 }
2132
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
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
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
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
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
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
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
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
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
2214 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2215 DeviceIdleController.this.dump(fd, pw, args);
2216 }
2217
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
2226 public void onConstraintStateChanged(IDeviceIdleConstraint constraint, boolean active) {
2227 synchronized (DeviceIdleController.this) {
2228 onConstraintStateChangedLocked(constraint, active);
2229 }
2230 }
2231
2232 @Override
2233 public void registerDeviceIdleConstraint(IDeviceIdleConstraint constraint, String name,
2234 @IDeviceIdleConstraint.MinimumState int minState) {
2235 registerDeviceIdleConstraintInternal(constraint, name, minState);
2236 }
2237
2238 @Override
2239 public void unregisterDeviceIdleConstraint(IDeviceIdleConstraint constraint) {
2240 unregisterDeviceIdleConstraintInternal(constraint);
2241 }
2242
2243 @Override
2244 public void exitIdle(String reason) {
2245 exitIdleInternal(reason);
2246 }
2247
2248 @Override
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
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
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
2275 public long getNotificationAllowlistDuration() {
2276 return mConstants.NOTIFICATION_ALLOWLIST_DURATION_MS;
2277 }
2278
2279 @Override
2280 public void setJobsActive(boolean active) {
2281 DeviceIdleController.this.setJobsActive(active);
2282 }
2283
2284 // Up-call from alarm manager.
2285 @Override
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
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
2303 public int[] getPowerSaveWhitelistUserAppIds() {
2304 return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
2305 }
2306
2307 @Override
2308 public int[] getPowerSaveTempWhitelistAppIds() {
2309 return DeviceIdleController.this.getAppIdTempWhitelistInternal();
2310 }
2311
2312 @Override
2313 public void registerStationaryListener(StationaryListener listener) {
2314 DeviceIdleController.this.registerStationaryListener(listener);
2315 }
2316
2317 @Override
2318 public void unregisterStationaryListener(StationaryListener listener) {
2319 DeviceIdleController.this.unregisterStationaryListener(listener);
2320 }
2321
2322 @Override
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
2332 public void registerTempAllowlistChangeListener(
2333 @NonNull TempAllowlistChangeListener listener) {
2334 DeviceIdleController.this.registerTempAllowlistChangeListener(listener);
2335 }
2336
2337 @Override
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
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
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
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
2383 Injector(Context ctx) {
2384 mContext = ctx.createAttributionContext(TAG);
2385 }
2386
2387 AlarmManager getAlarmManager() {
2388 return mContext.getSystemService(AlarmManager.class);
2389 }
2390
2391 AnyMotionDetector getAnyMotionDetector(Handler handler, SensorManager sm,
2392 AnyMotionDetector.DeviceIdleCallback callback, float angleThreshold) {
2393 return new AnyMotionDetector(getPowerManager(), handler, sm, callback, angleThreshold);
2394 }
2395
2396 AppStateTrackerImpl getAppStateTracker(Context ctx, Looper looper) {
2397 return new AppStateTrackerImpl(ctx, looper);
2398 }
2399
2400 ConnectivityManager getConnectivityManager() {
2401 if (mConnectivityManager == null) {
2402 mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
2403 }
2404 return mConnectivityManager;
2405 }
2406
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. */
2415 long getElapsedRealtime() {
2416 return SystemClock.elapsedRealtime();
2417 }
2418
2419 LocationManager getLocationManager() {
2420 if (mLocationManager == null) {
2421 mLocationManager = mContext.getSystemService(LocationManager.class);
2422 }
2423 return mLocationManager;
2424 }
2425
2426 MyHandler getHandler(DeviceIdleController controller) {
2427 return controller.new MyHandler(AppSchedulingModuleThread.getHandler().getLooper());
2428 }
2429
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
2451 PowerManager getPowerManager() {
2452 return mContext.getSystemService(PowerManager.class);
2453 }
2454
2455 SensorManager getSensorManager() {
2456 return mContext.getSystemService(SensorManager.class);
2457 }
2458
2459 TelephonyManager getTelephonyManager() {
2460 return mContext.getSystemService(TelephonyManager.class);
2461 }
2462
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
2472 boolean isLocationPrefetchEnabled() {
2473 return mContext.getResources().getBoolean(
2474 com.android.internal.R.bool.config_autoPowerModePrefetchLocation);
2475 }
2476
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
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
2510 public DeviceIdleController(Context context) {
2511 this(context, new Injector(context));
2512 }
2513
2514 boolean isAppOnWhitelistInternal(int appid) {
2515 synchronized (this) {
2516 return Arrays.binarySearch(mPowerSaveWhitelistAllAppIdArray, appid) >= 0;
2517 }
2518 }
2519
2520 int[] getPowerSaveWhitelistUserAppIds() {
2521 synchronized (this) {
2522 return mPowerSaveWhitelistUserAppIdArray;
2523 }
2524 }
2525
2526 private static File getSystemDir() {
2527 return new File(Environment.getDataDirectory(), "system");
2528 }
2529
2530 @Override
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
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
2707 boolean hasMotionSensor() {
2708 return mUseMotionSensor && mMotionSensor != null;
2709 }
2710
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
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")
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")
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")
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
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
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
2844 public boolean getPowerSaveWhitelistAppInternal(String name) {
2845 synchronized (this) {
2846 return mPowerSaveWhitelistUserApps.containsKey(name);
2847 }
2848 }
2849
2850 void resetSystemPowerWhitelistInternal() {
2851 synchronized (this) {
2852 mPowerSaveWhitelistApps.putAll(mRemovedFromSystemWhitelistApps);
2853 mRemovedFromSystemWhitelistApps.clear();
2854 reportPowerSaveWhitelistChangedLocked();
2855 updateWhitelistAppIdsLocked();
2856 writeConfigFileLocked();
2857 }
2858 }
2859
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
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
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
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
2923 public boolean getPowerSaveWhitelistExceptIdleInternal(String name) {
2924 synchronized (this) {
2925 return mPowerSaveWhitelistAppsExceptIdle.containsKey(name);
2926 }
2927 }
2928
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
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
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
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
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
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
3024 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
3025 synchronized (this) {
3026 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
3027 || mPowerSaveWhitelistUserApps.containsKey(packageName);
3028 }
3029 }
3030
3031 public boolean isPowerSaveWhitelistAppInternal(String packageName) {
3032 synchronized (this) {
3033 return mPowerSaveWhitelistApps.containsKey(packageName)
3034 || mPowerSaveWhitelistUserApps.containsKey(packageName);
3035 }
3036 }
3037
3038 public int[] getAppIdWhitelistExceptIdleInternal() {
3039 synchronized (this) {
3040 return mPowerSaveWhitelistExceptIdleAppIdArray;
3041 }
3042 }
3043
3044 public int[] getAppIdWhitelistInternal() {
3045 synchronized (this) {
3046 return mPowerSaveWhitelistAllAppIdArray;
3047 }
3048 }
3049
3050 public int[] getAppIdUserWhitelistInternal() {
3051 synchronized (this) {
3052 return mPowerSaveWhitelistUserAppIdArray;
3053 }
3054 }
3055
3056 public int[] getAppIdTempWhitelistInternal() {
3057 synchronized (this) {
3058 return mTempWhitelistAppIdArray;
3059 }
3060 }
3061
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
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
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 */
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 */
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 */
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
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
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
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")
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
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
3281 boolean isNetworkConnected() {
3282 synchronized (this) {
3283 return mNetworkConnected;
3284 }
3285 }
3286
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
3325 boolean isScreenOn() {
3326 synchronized (this) {
3327 return mScreenOn;
3328 }
3329 }
3330
3331 @GuardedBy("this")
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
3353 boolean isCharging() {
3354 synchronized (this) {
3355 return mCharging;
3356 }
3357 }
3358
3359 @GuardedBy("this")
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
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")
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
3403 boolean isKeyguardShowing() {
3404 synchronized (this) {
3405 return mScreenLocked;
3406 }
3407 }
3408
3409 @VisibleForTesting
3410 @GuardedBy("this")
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")
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")
3430 void becomeActiveLocked(String activeReason, int activeUid) {
3431 becomeActiveLocked(activeReason, activeUid, mConstants.INACTIVE_TIMEOUT, true);
3432 }
3433
3434 @GuardedBy("this")
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
3463 void setDeepEnabledForTest(boolean enabled) {
3464 synchronized (this) {
3465 mDeepEnabled = enabled;
3466 }
3467 }
3468
3469 /** Must only be used in tests. */
3470 @VisibleForTesting
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")
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")
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")
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")
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")
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
3609 void setLightStateForTest(int lightState) {
3610 synchronized (this) {
3611 mLightState = lightState;
3612 }
3613 }
3614
3615 @VisibleForTesting
3616 int getLightState() {
3617 synchronized (this) {
3618 return mLightState;
3619 }
3620 }
3621
3622 @GuardedBy("this")
3623 @VisibleForTesting
3624 @SuppressLint("WakelockTimeout")
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
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 */
3719 private boolean isUpcomingAlarmClock() {
3720 return mInjector.getElapsedRealtime() + mConstants.MIN_TIME_TO_ALARM
3721 >= mAlarmManager.getNextWakeFromIdleTime();
3722 }
3723
3724 @VisibleForTesting
3725 @GuardedBy("this")
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")
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")
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
3909 void incActiveIdleOps() {
3910 synchronized (this) {
3911 mActiveIdleOpCount++;
3912 }
3913 }
3914
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
3927 void setActiveIdleOpsForTest(int count) {
3928 synchronized (this) {
3929 mActiveIdleOpCount = count;
3930 }
3931 }
3932
3933 void setJobsActive(boolean active) {
3934 synchronized (this) {
3935 mJobsActive = active;
3936 if (!active) {
3937 exitMaintenanceEarlyIfNeededLocked();
3938 }
3939 }
3940 }
3941
3942 void setAlarmsActive(boolean active) {
3943 synchronized (this) {
3944 mAlarmsActive = active;
3945 if (!active) {
3946 exitMaintenanceEarlyIfNeededLocked();
3947 }
3948 }
3949 }
3950
3951 @VisibleForTesting
3952 int setPreIdleTimeoutMode(int mode) {
3953 return setPreIdleTimeoutFactor(getPreIdleTimeoutByMode(mode));
3954 }
3955
3956 @VisibleForTesting
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
3976 float getPreIdleTimeoutFactor() {
3977 synchronized (this) {
3978 return mPreIdleFactor;
3979 }
3980 }
3981
3982 @VisibleForTesting
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
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
4015 private void postUpdatePreIdleFactor() {
4016 mHandler.sendEmptyMessage(MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR);
4017 }
4018
4019 private void postResetPreIdleTimeoutFactor() {
4020 mHandler.sendEmptyMessage(MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR);
4021 }
4022
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
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")
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
4068 void setIdleStartTimeForTest(long idleStartTime) {
4069 synchronized (this) {
4070 mIdleStartTime = idleStartTime;
4071 maybeDoImmediateMaintenance("testing");
4072 }
4073 }
4074
4075 @VisibleForTesting
4076 long getNextAlarmTime() {
4077 synchronized (this) {
4078 return mNextAlarmTime;
4079 }
4080 }
4081
4082 @VisibleForTesting
4083 boolean isEmergencyCallActive() {
4084 return mEmergencyCallListener.isEmergencyCallActive();
4085 }
4086
4087 @GuardedBy("this")
4088 boolean isOpsInactiveLocked() {
4089 return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
4090 }
4091
4092 @GuardedBy("this")
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")
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")
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")
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")
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
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 */
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")
4208 void cancelAlarmLocked() {
4209 if (mNextAlarmTime != 0) {
4210 mNextAlarmTime = 0;
4211 mAlarmManager.cancel(mDeepAlarmListener);
4212 }
4213 }
4214
4215 @GuardedBy("this")
4216 private void cancelLightAlarmLocked() {
4217 if (mNextLightAlarmTime != 0) {
4218 mNextLightAlarmTime = 0;
4219 mAlarmManager.cancel(mLightAlarmListener);
4220 }
4221 }
4222
4223 @GuardedBy("this")
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
4233 private void cancelMotionTimeoutAlarmLocked() {
4234 mAlarmManager.cancel(mMotionTimeoutAlarmListener);
4235 }
4236
4237 private void cancelMotionRegistrationAlarmLocked() {
4238 mAlarmManager.cancel(mMotionRegistrationAlarmListener);
4239 }
4240
4241 @GuardedBy("this")
4242 void cancelSensingTimeoutAlarmLocked() {
4243 if (mNextSensingTimeoutAlarmTime != 0) {
4244 mNextSensingTimeoutAlarmTime = 0;
4245 mAlarmManager.cancel(mSensingTimeoutAlarmListener);
4246 }
4247 }
4248
4249 @GuardedBy("this")
4250 @VisibleForTesting
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")
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
4309 long getNextLightAlarmTimeForTesting() {
4310 synchronized (this) {
4311 return mNextLightAlarmTime;
4312 }
4313 }
4314
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
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")
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
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
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")
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
4444 private void reportPowerSaveWhitelistChangedLocked() {
4445 getContext().sendBroadcastAsUser(mPowerSaveWhitelistChangedIntent, UserHandle.SYSTEM,
4446 null /* receiverPermission */,
4447 mPowerSaveWhitelistChangedOptions);
4448 }
4449
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
4458 private void passWhiteListsToForceAppStandbyTrackerLocked() {
4459 mAppStateTracker.setPowerSaveExemptionListAppIds(
4460 mPowerSaveWhitelistExceptIdleAppIdArray,
4461 mPowerSaveWhitelistUserAppIdArray,
4462 mTempWhitelistAppIdArray);
4463 }
4464
4465 @GuardedBy("this")
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")
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
4554 void writeConfigFileLocked() {
4555 mHandler.removeMessages(MSG_WRITE_CONFIG);
4556 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
4557 }
4558
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
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
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
4659 public int onCommand(String cmd) {
4660 return onShellCommand(this, cmd);
4661 }
4662
4663 @Override
4664 public void onHelp() {
4665 PrintWriter pw = getOutPrintWriter();
4666 dumpHelp(pw);
4667 }
4668 }
4669
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
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
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 }