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