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