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