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.SensorManager; 34 import android.hardware.SensorEvent; 35 import android.hardware.SensorEventListener; 36 import android.hardware.TriggerEvent; 37 import android.hardware.TriggerEventListener; 38 import android.hardware.display.DisplayManager; 39 import android.location.LocationRequest; 40 import android.location.Location; 41 import android.location.LocationListener; 42 import android.location.LocationManager; 43 import android.net.ConnectivityManager; 44 import android.net.INetworkPolicyManager; 45 import android.net.NetworkInfo; 46 import android.net.Uri; 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.PowerManagerInternal; 59 import android.os.Process; 60 import android.os.RemoteCallbackList; 61 import android.os.RemoteException; 62 import android.os.ResultReceiver; 63 import android.os.ServiceManager; 64 import android.os.ShellCallback; 65 import android.os.ShellCommand; 66 import android.os.SystemClock; 67 import android.os.UserHandle; 68 import android.provider.Settings; 69 import android.util.ArrayMap; 70 import android.util.ArraySet; 71 import android.util.KeyValueListParser; 72 import android.util.MutableLong; 73 import android.util.Pair; 74 import android.util.Slog; 75 import android.util.SparseArray; 76 import android.util.SparseBooleanArray; 77 import android.util.TimeUtils; 78 import android.util.Xml; 79 import android.view.Display; 80 81 import com.android.internal.app.IBatteryStats; 82 import com.android.internal.os.AtomicFile; 83 import com.android.internal.os.BackgroundThread; 84 import com.android.internal.util.DumpUtils; 85 import com.android.internal.util.FastXmlSerializer; 86 import com.android.internal.util.XmlUtils; 87 import com.android.server.am.BatteryStatsService; 88 89 import org.xmlpull.v1.XmlPullParser; 90 import org.xmlpull.v1.XmlPullParserException; 91 import org.xmlpull.v1.XmlSerializer; 92 93 import java.io.ByteArrayOutputStream; 94 import java.io.File; 95 import java.io.FileDescriptor; 96 import java.io.FileInputStream; 97 import java.io.FileNotFoundException; 98 import java.io.FileOutputStream; 99 import java.io.IOException; 100 import java.io.PrintWriter; 101 import java.nio.charset.StandardCharsets; 102 import java.util.Arrays; 103 104 /** 105 * Keeps track of device idleness and drives low power mode based on that. 106 */ 107 public class DeviceIdleController extends SystemService 108 implements AnyMotionDetector.DeviceIdleCallback { 109 private static final String TAG = "DeviceIdleController"; 110 111 private static final boolean DEBUG = false; 112 113 private static final boolean COMPRESS_TIME = false; 114 115 private static final int EVENT_BUFFER_SIZE = 100; 116 117 private AlarmManager mAlarmManager; 118 private IBatteryStats mBatteryStats; 119 private ActivityManagerInternal mLocalActivityManager; 120 private PowerManagerInternal mLocalPowerManager; 121 private PowerManager mPowerManager; 122 private ConnectivityService mConnectivityService; 123 private AlarmManagerService.LocalService mLocalAlarmManager; 124 private INetworkPolicyManager mNetworkPolicyManager; 125 private DisplayManager mDisplayManager; 126 private SensorManager mSensorManager; 127 private Sensor mMotionSensor; 128 private LocationManager mLocationManager; 129 private LocationRequest mLocationRequest; 130 private Intent mIdleIntent; 131 private Intent mLightIdleIntent; 132 private Display mCurDisplay; 133 private AnyMotionDetector mAnyMotionDetector; 134 private boolean mLightEnabled; 135 private boolean mDeepEnabled; 136 private boolean mForceIdle; 137 private boolean mNetworkConnected; 138 private boolean mScreenOn; 139 private boolean mCharging; 140 private boolean mNotMoving; 141 private boolean mLocating; 142 private boolean mLocated; 143 private boolean mHasGps; 144 private boolean mHasNetworkLocation; 145 private Location mLastGenericLocation; 146 private Location mLastGpsLocation; 147 148 /** Device is currently active. */ 149 private static final int STATE_ACTIVE = 0; 150 /** Device is inactive (screen off, no motion) and we are waiting to for idle. */ 151 private static final int STATE_INACTIVE = 1; 152 /** Device is past the initial inactive period, and waiting for the next idle period. */ 153 private static final int STATE_IDLE_PENDING = 2; 154 /** Device is currently sensing motion. */ 155 private static final int STATE_SENSING = 3; 156 /** Device is currently finding location (and may still be sensing). */ 157 private static final int STATE_LOCATING = 4; 158 /** Device is in the idle state, trying to stay asleep as much as possible. */ 159 private static final int STATE_IDLE = 5; 160 /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */ 161 private static final int STATE_IDLE_MAINTENANCE = 6; stateToString(int state)162 private static String stateToString(int state) { 163 switch (state) { 164 case STATE_ACTIVE: return "ACTIVE"; 165 case STATE_INACTIVE: return "INACTIVE"; 166 case STATE_IDLE_PENDING: return "IDLE_PENDING"; 167 case STATE_SENSING: return "SENSING"; 168 case STATE_LOCATING: return "LOCATING"; 169 case STATE_IDLE: return "IDLE"; 170 case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE"; 171 default: return Integer.toString(state); 172 } 173 } 174 175 /** Device is currently active. */ 176 private static final int LIGHT_STATE_ACTIVE = 0; 177 /** Device is inactive (screen off) and we are waiting to for the first light idle. */ 178 private static final int LIGHT_STATE_INACTIVE = 1; 179 /** Device is about to go idle for the first time, wait for current work to complete. */ 180 private static final int LIGHT_STATE_PRE_IDLE = 3; 181 /** Device is in the light idle state, trying to stay asleep as much as possible. */ 182 private static final int LIGHT_STATE_IDLE = 4; 183 /** Device is in the light idle state, we want to go in to idle maintenance but are 184 * waiting for network connectivity before doing so. */ 185 private static final int LIGHT_STATE_WAITING_FOR_NETWORK = 5; 186 /** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */ 187 private static final int LIGHT_STATE_IDLE_MAINTENANCE = 6; 188 /** Device light idle state is overriden, now applying deep doze state. */ 189 private static final int LIGHT_STATE_OVERRIDE = 7; lightStateToString(int state)190 private static String lightStateToString(int state) { 191 switch (state) { 192 case LIGHT_STATE_ACTIVE: return "ACTIVE"; 193 case LIGHT_STATE_INACTIVE: return "INACTIVE"; 194 case LIGHT_STATE_PRE_IDLE: return "PRE_IDLE"; 195 case LIGHT_STATE_IDLE: return "IDLE"; 196 case LIGHT_STATE_WAITING_FOR_NETWORK: return "WAITING_FOR_NETWORK"; 197 case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE"; 198 case LIGHT_STATE_OVERRIDE: return "OVERRIDE"; 199 default: return Integer.toString(state); 200 } 201 } 202 203 private int mState; 204 private int mLightState; 205 206 private long mInactiveTimeout; 207 private long mNextAlarmTime; 208 private long mNextIdlePendingDelay; 209 private long mNextIdleDelay; 210 private long mNextLightIdleDelay; 211 private long mNextLightAlarmTime; 212 private long mNextSensingTimeoutAlarmTime; 213 private long mCurIdleBudget; 214 private long mMaintenanceStartTime; 215 216 private int mActiveIdleOpCount; 217 private PowerManager.WakeLock mActiveIdleWakeLock; // held when there are operations in progress 218 private PowerManager.WakeLock mGoingIdleWakeLock; // held when we are going idle so hardware 219 // (especially NetworkPolicyManager) can shut 220 // down. 221 private boolean mJobsActive; 222 private boolean mAlarmsActive; 223 private boolean mReportedMaintenanceActivity; 224 225 public final AtomicFile mConfigFile; 226 227 private final RemoteCallbackList<IMaintenanceActivityListener> mMaintenanceActivityListeners = 228 new RemoteCallbackList<IMaintenanceActivityListener>(); 229 230 /** 231 * Package names the system has white-listed to opt out of power save restrictions, 232 * except for device idle mode. 233 */ 234 private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>(); 235 236 /** 237 * Package names the user has white-listed using commandline option to opt out of 238 * power save restrictions, except for device idle mode. 239 */ 240 private final ArraySet<String> mPowerSaveWhitelistUserAppsExceptIdle = new ArraySet<>(); 241 242 /** 243 * Package names the system has white-listed to opt out of power save restrictions for 244 * all modes. 245 */ 246 private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>(); 247 248 /** 249 * Package names the user has white-listed to opt out of power save restrictions. 250 */ 251 private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>(); 252 253 /** 254 * App IDs of built-in system apps that have been white-listed except for idle modes. 255 */ 256 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle 257 = new SparseBooleanArray(); 258 259 /** 260 * App IDs of built-in system apps that have been white-listed. 261 */ 262 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray(); 263 264 /** 265 * App IDs that have been white-listed to opt out of power save restrictions, except 266 * for device idle modes. 267 */ 268 private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray(); 269 270 /** 271 * Current app IDs that are in the complete power save white list, but shouldn't be 272 * excluded from idle modes. This array can be shared with others because it will not be 273 * modified once set. 274 */ 275 private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0]; 276 277 /** 278 * App IDs that have been white-listed to opt out of power save restrictions. 279 */ 280 private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray(); 281 282 /** 283 * Current app IDs that are in the complete power save white list. This array can 284 * be shared with others because it will not be modified once set. 285 */ 286 private int[] mPowerSaveWhitelistAllAppIdArray = new int[0]; 287 288 /** 289 * App IDs that have been white-listed by the user to opt out of power save restrictions. 290 */ 291 private final SparseBooleanArray mPowerSaveWhitelistUserAppIds = new SparseBooleanArray(); 292 293 /** 294 * Current app IDs that are in the user power save white list. This array can 295 * be shared with others because it will not be modified once set. 296 */ 297 private int[] mPowerSaveWhitelistUserAppIdArray = new int[0]; 298 299 /** 300 * List of end times for UIDs that are temporarily marked as being allowed to access 301 * the network and acquire wakelocks. Times are in milliseconds. 302 */ 303 private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes 304 = new SparseArray<>(); 305 306 /** 307 * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed. 308 */ 309 Runnable mNetworkPolicyTempWhitelistCallback; 310 311 /** 312 * Current app IDs of temporarily whitelist apps for high-priority messages. 313 */ 314 private int[] mTempWhitelistAppIdArray = new int[0]; 315 316 private static final int EVENT_NULL = 0; 317 private static final int EVENT_NORMAL = 1; 318 private static final int EVENT_LIGHT_IDLE = 2; 319 private static final int EVENT_LIGHT_MAINTENANCE = 3; 320 private static final int EVENT_DEEP_IDLE = 4; 321 private static final int EVENT_DEEP_MAINTENANCE = 5; 322 323 private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE]; 324 private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE]; 325 addEvent(int cmd)326 private void addEvent(int cmd) { 327 if (mEventCmds[0] != cmd) { 328 System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1); 329 System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1); 330 mEventCmds[0] = cmd; 331 mEventTimes[0] = SystemClock.elapsedRealtime(); 332 } 333 } 334 335 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 336 @Override public void onReceive(Context context, Intent intent) { 337 switch (intent.getAction()) { 338 case ConnectivityManager.CONNECTIVITY_ACTION: { 339 updateConnectivityState(intent); 340 } break; 341 case Intent.ACTION_BATTERY_CHANGED: { 342 synchronized (DeviceIdleController.this) { 343 int plugged = intent.getIntExtra("plugged", 0); 344 updateChargingLocked(plugged != 0); 345 } 346 } break; 347 case Intent.ACTION_PACKAGE_REMOVED: { 348 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 349 Uri data = intent.getData(); 350 String ssp; 351 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) { 352 removePowerSaveWhitelistAppInternal(ssp); 353 } 354 } 355 } break; 356 } 357 } 358 }; 359 360 private final AlarmManager.OnAlarmListener mLightAlarmListener 361 = new AlarmManager.OnAlarmListener() { 362 @Override 363 public void onAlarm() { 364 synchronized (DeviceIdleController.this) { 365 stepLightIdleStateLocked("s:alarm"); 366 } 367 } 368 }; 369 370 private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener 371 = new AlarmManager.OnAlarmListener() { 372 @Override 373 public void onAlarm() { 374 if (mState == STATE_SENSING) { 375 synchronized (DeviceIdleController.this) { 376 becomeInactiveIfAppropriateLocked(); 377 } 378 } 379 } 380 }; 381 382 private final AlarmManager.OnAlarmListener mDeepAlarmListener 383 = new AlarmManager.OnAlarmListener() { 384 @Override 385 public void onAlarm() { 386 synchronized (DeviceIdleController.this) { 387 stepIdleStateLocked("s:alarm"); 388 } 389 } 390 }; 391 392 private final BroadcastReceiver mIdleStartedDoneReceiver = new BroadcastReceiver() { 393 @Override public void onReceive(Context context, Intent intent) { 394 // When coming out of a deep idle, we will add in some delay before we allow 395 // the system to settle down and finish the maintenance window. This is 396 // to give a chance for any pending work to be scheduled. 397 if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) { 398 mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP, 399 mConstants.MIN_DEEP_MAINTENANCE_TIME); 400 } else { 401 mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP, 402 mConstants.MIN_LIGHT_MAINTENANCE_TIME); 403 } 404 } 405 }; 406 407 private final DisplayManager.DisplayListener mDisplayListener 408 = new DisplayManager.DisplayListener() { 409 @Override public void onDisplayAdded(int displayId) { 410 } 411 412 @Override public void onDisplayRemoved(int displayId) { 413 } 414 415 @Override public void onDisplayChanged(int displayId) { 416 if (displayId == Display.DEFAULT_DISPLAY) { 417 synchronized (DeviceIdleController.this) { 418 updateDisplayLocked(); 419 } 420 } 421 } 422 }; 423 424 private final class MotionListener extends TriggerEventListener 425 implements SensorEventListener { 426 427 boolean active = false; 428 429 @Override onTrigger(TriggerEvent event)430 public void onTrigger(TriggerEvent event) { 431 synchronized (DeviceIdleController.this) { 432 active = false; 433 motionLocked(); 434 } 435 } 436 437 @Override onSensorChanged(SensorEvent event)438 public void onSensorChanged(SensorEvent event) { 439 synchronized (DeviceIdleController.this) { 440 mSensorManager.unregisterListener(this, mMotionSensor); 441 active = false; 442 motionLocked(); 443 } 444 } 445 446 @Override onAccuracyChanged(Sensor sensor, int accuracy)447 public void onAccuracyChanged(Sensor sensor, int accuracy) {} 448 registerLocked()449 public boolean registerLocked() { 450 boolean success; 451 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { 452 success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor); 453 } else { 454 success = mSensorManager.registerListener( 455 mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL); 456 } 457 if (success) { 458 active = true; 459 } else { 460 Slog.e(TAG, "Unable to register for " + mMotionSensor); 461 } 462 return success; 463 } 464 unregisterLocked()465 public void unregisterLocked() { 466 if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { 467 mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor); 468 } else { 469 mSensorManager.unregisterListener(mMotionListener); 470 } 471 active = false; 472 } 473 } 474 private final MotionListener mMotionListener = new MotionListener(); 475 476 private final LocationListener mGenericLocationListener = new LocationListener() { 477 @Override 478 public void onLocationChanged(Location location) { 479 synchronized (DeviceIdleController.this) { 480 receivedGenericLocationLocked(location); 481 } 482 } 483 484 @Override 485 public void onStatusChanged(String provider, int status, Bundle extras) { 486 } 487 488 @Override 489 public void onProviderEnabled(String provider) { 490 } 491 492 @Override 493 public void onProviderDisabled(String provider) { 494 } 495 }; 496 497 private final LocationListener mGpsLocationListener = new LocationListener() { 498 @Override 499 public void onLocationChanged(Location location) { 500 synchronized (DeviceIdleController.this) { 501 receivedGpsLocationLocked(location); 502 } 503 } 504 505 @Override 506 public void onStatusChanged(String provider, int status, Bundle extras) { 507 } 508 509 @Override 510 public void onProviderEnabled(String provider) { 511 } 512 513 @Override 514 public void onProviderDisabled(String provider) { 515 } 516 }; 517 518 /** 519 * All times are in milliseconds. These constants are kept synchronized with the system 520 * global Settings. Any access to this class or its fields should be done while 521 * holding the DeviceIdleController lock. 522 */ 523 private final class Constants extends ContentObserver { 524 // Key names stored in the settings value. 525 private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT 526 = "light_after_inactive_to"; 527 private static final String KEY_LIGHT_PRE_IDLE_TIMEOUT = "light_pre_idle_to"; 528 private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to"; 529 private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor"; 530 private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to"; 531 private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET 532 = "light_idle_maintenance_min_budget"; 533 private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET 534 = "light_idle_maintenance_max_budget"; 535 private static final String KEY_MIN_LIGHT_MAINTENANCE_TIME = "min_light_maintenance_time"; 536 private static final String KEY_MIN_DEEP_MAINTENANCE_TIME = "min_deep_maintenance_time"; 537 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to"; 538 private static final String KEY_SENSING_TIMEOUT = "sensing_to"; 539 private static final String KEY_LOCATING_TIMEOUT = "locating_to"; 540 private static final String KEY_LOCATION_ACCURACY = "location_accuracy"; 541 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to"; 542 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to"; 543 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to"; 544 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to"; 545 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor"; 546 private static final String KEY_IDLE_TIMEOUT = "idle_to"; 547 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to"; 548 private static final String KEY_IDLE_FACTOR = "idle_factor"; 549 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm"; 550 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION = 551 "max_temp_app_whitelist_duration"; 552 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION = 553 "mms_temp_app_whitelist_duration"; 554 private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION = 555 "sms_temp_app_whitelist_duration"; 556 private static final String KEY_NOTIFICATION_WHITELIST_DURATION = 557 "notification_whitelist_duration"; 558 559 /** 560 * This is the time, after becoming inactive, that we go in to the first 561 * light-weight idle mode. 562 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 563 * @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT 564 */ 565 public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT; 566 567 /** 568 * This is amount of time we will wait from the point where we decide we would 569 * like to go idle until we actually do, while waiting for jobs and other current 570 * activity to finish. 571 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 572 * @see #KEY_LIGHT_PRE_IDLE_TIMEOUT 573 */ 574 public long LIGHT_PRE_IDLE_TIMEOUT; 575 576 /** 577 * This is the initial time that we will run in idle maintenance mode. 578 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 579 * @see #KEY_LIGHT_IDLE_TIMEOUT 580 */ 581 public long LIGHT_IDLE_TIMEOUT; 582 583 /** 584 * Scaling factor to apply to the light idle mode time each time we complete a cycle. 585 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 586 * @see #KEY_LIGHT_IDLE_FACTOR 587 */ 588 public float LIGHT_IDLE_FACTOR; 589 590 /** 591 * This is the maximum time we will run in idle maintenence mode. 592 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 593 * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT 594 */ 595 public long LIGHT_MAX_IDLE_TIMEOUT; 596 597 /** 598 * This is the minimum amount of time we want to make available for maintenance mode 599 * when lightly idling. That is, we will always have at least this amount of time 600 * available maintenance before timing out and cutting off maintenance mode. 601 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 602 * @see #KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET 603 */ 604 public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; 605 606 /** 607 * This is the maximum amount of time we want to make available for maintenance mode 608 * when lightly idling. That is, if the system isn't using up its minimum maintenance 609 * budget and this time is being added to the budget reserve, this is the maximum 610 * reserve size we will allow to grow and thus the maximum amount of time we will 611 * allow for the maintenance window. 612 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 613 * @see #KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET 614 */ 615 public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET; 616 617 /** 618 * This is the minimum amount of time that we will stay in maintenance mode after 619 * a light doze. We have this minimum to allow various things to respond to switching 620 * in to maintenance mode and scheduling their work -- otherwise we may 621 * see there is nothing to do (no jobs pending) and go out of maintenance 622 * mode immediately. 623 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 624 * @see #KEY_MIN_LIGHT_MAINTENANCE_TIME 625 */ 626 public long MIN_LIGHT_MAINTENANCE_TIME; 627 628 /** 629 * This is the minimum amount of time that we will stay in maintenance mode after 630 * a full doze. We have this minimum to allow various things to respond to switching 631 * in to maintenance mode and scheduling their work -- otherwise we may 632 * see there is nothing to do (no jobs pending) and go out of maintenance 633 * mode immediately. 634 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 635 * @see #KEY_MIN_DEEP_MAINTENANCE_TIME 636 */ 637 public long MIN_DEEP_MAINTENANCE_TIME; 638 639 /** 640 * This is the time, after becoming inactive, at which we start looking at the 641 * motion sensor to determine if the device is being left alone. We don't do this 642 * immediately after going inactive just because we don't want to be continually running 643 * the motion sensor whenever the screen is off. 644 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 645 * @see #KEY_INACTIVE_TIMEOUT 646 */ 647 public long INACTIVE_TIMEOUT; 648 649 /** 650 * If we don't receive a callback from AnyMotion in this amount of time + 651 * {@link #LOCATING_TIMEOUT}, we will change from 652 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING 653 * will be ignored. 654 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 655 * @see #KEY_SENSING_TIMEOUT 656 */ 657 public long SENSING_TIMEOUT; 658 659 /** 660 * This is how long we will wait to try to get a good location fix before going in to 661 * idle mode. 662 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 663 * @see #KEY_LOCATING_TIMEOUT 664 */ 665 public long LOCATING_TIMEOUT; 666 667 /** 668 * The desired maximum accuracy (in meters) we consider the location to be good enough to go 669 * on to idle. We will be trying to get an accuracy fix at least this good or until 670 * {@link #LOCATING_TIMEOUT} expires. 671 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 672 * @see #KEY_LOCATION_ACCURACY 673 */ 674 public float LOCATION_ACCURACY; 675 676 /** 677 * This is the time, after seeing motion, that we wait after becoming inactive from 678 * that until we start looking for motion again. 679 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 680 * @see #KEY_MOTION_INACTIVE_TIMEOUT 681 */ 682 public long MOTION_INACTIVE_TIMEOUT; 683 684 /** 685 * This is the time, after the inactive timeout elapses, that we will wait looking 686 * for motion until we truly consider the device to be idle. 687 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 688 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT 689 */ 690 public long IDLE_AFTER_INACTIVE_TIMEOUT; 691 692 /** 693 * This is the initial time, after being idle, that we will allow ourself to be back 694 * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to 695 * idle. 696 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 697 * @see #KEY_IDLE_PENDING_TIMEOUT 698 */ 699 public long IDLE_PENDING_TIMEOUT; 700 701 /** 702 * Maximum pending idle timeout (time spent running) we will be allowed to use. 703 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 704 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT 705 */ 706 public long MAX_IDLE_PENDING_TIMEOUT; 707 708 /** 709 * Scaling factor to apply to current pending idle timeout each time we cycle through 710 * that state. 711 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 712 * @see #KEY_IDLE_PENDING_FACTOR 713 */ 714 public float IDLE_PENDING_FACTOR; 715 716 /** 717 * This is the initial time that we want to sit in the idle state before waking up 718 * again to return to pending idle and allowing normal work to run. 719 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 720 * @see #KEY_IDLE_TIMEOUT 721 */ 722 public long IDLE_TIMEOUT; 723 724 /** 725 * Maximum idle duration we will be allowed to use. 726 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 727 * @see #KEY_MAX_IDLE_TIMEOUT 728 */ 729 public long MAX_IDLE_TIMEOUT; 730 731 /** 732 * Scaling factor to apply to current idle timeout each time we cycle through that state. 733 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 734 * @see #KEY_IDLE_FACTOR 735 */ 736 public float IDLE_FACTOR; 737 738 /** 739 * This is the minimum time we will allow until the next upcoming alarm for us to 740 * actually go in to idle mode. 741 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 742 * @see #KEY_MIN_TIME_TO_ALARM 743 */ 744 public long MIN_TIME_TO_ALARM; 745 746 /** 747 * Max amount of time to temporarily whitelist an app when it receives a high priority 748 * tickle. 749 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 750 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION 751 */ 752 public long MAX_TEMP_APP_WHITELIST_DURATION; 753 754 /** 755 * Amount of time we would like to whitelist an app that is receiving an MMS. 756 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 757 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION 758 */ 759 public long MMS_TEMP_APP_WHITELIST_DURATION; 760 761 /** 762 * Amount of time we would like to whitelist an app that is receiving an SMS. 763 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 764 * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION 765 */ 766 public long SMS_TEMP_APP_WHITELIST_DURATION; 767 768 /** 769 * Amount of time we would like to whitelist an app that is handling a 770 * {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}. 771 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 772 * @see #KEY_NOTIFICATION_WHITELIST_DURATION 773 */ 774 public long NOTIFICATION_WHITELIST_DURATION; 775 776 private final ContentResolver mResolver; 777 private final boolean mHasWatch; 778 private final KeyValueListParser mParser = new KeyValueListParser(','); 779 Constants(Handler handler, ContentResolver resolver)780 public Constants(Handler handler, ContentResolver resolver) { 781 super(handler); 782 mResolver = resolver; 783 mHasWatch = getContext().getPackageManager().hasSystemFeature( 784 PackageManager.FEATURE_WATCH); 785 mResolver.registerContentObserver(Settings.Global.getUriFor( 786 mHasWatch ? Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH 787 : Settings.Global.DEVICE_IDLE_CONSTANTS), 788 false, this); 789 updateConstants(); 790 } 791 792 @Override onChange(boolean selfChange, Uri uri)793 public void onChange(boolean selfChange, Uri uri) { 794 updateConstants(); 795 } 796 updateConstants()797 private void updateConstants() { 798 synchronized (DeviceIdleController.this) { 799 try { 800 mParser.setString(Settings.Global.getString(mResolver, 801 mHasWatch ? Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH 802 : Settings.Global.DEVICE_IDLE_CONSTANTS)); 803 } catch (IllegalArgumentException e) { 804 // Failed to parse the settings string, log this and move on 805 // with defaults. 806 Slog.e(TAG, "Bad device idle settings", e); 807 } 808 809 LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong( 810 KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, 811 !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L); 812 LIGHT_PRE_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_PRE_IDLE_TIMEOUT, 813 !COMPRESS_TIME ? 10 * 60 * 1000L : 30 * 1000L); 814 LIGHT_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_TIMEOUT, 815 !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L); 816 LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR, 817 2f); 818 LIGHT_MAX_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_MAX_IDLE_TIMEOUT, 819 !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L); 820 LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getLong( 821 KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, 822 !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L); 823 LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getLong( 824 KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, 825 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L); 826 MIN_LIGHT_MAINTENANCE_TIME = mParser.getLong( 827 KEY_MIN_LIGHT_MAINTENANCE_TIME, 828 !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L); 829 MIN_DEEP_MAINTENANCE_TIME = mParser.getLong( 830 KEY_MIN_DEEP_MAINTENANCE_TIME, 831 !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L); 832 long inactiveTimeoutDefault = (mHasWatch ? 15 : 30) * 60 * 1000L; 833 INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT, 834 !COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10)); 835 SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT, 836 !DEBUG ? 4 * 60 * 1000L : 60 * 1000L); 837 LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT, 838 !DEBUG ? 30 * 1000L : 15 * 1000L); 839 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20); 840 MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT, 841 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L); 842 long idleAfterInactiveTimeout = (mHasWatch ? 15 : 30) * 60 * 1000L; 843 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT, 844 !COMPRESS_TIME ? idleAfterInactiveTimeout 845 : (idleAfterInactiveTimeout / 10)); 846 IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT, 847 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L); 848 MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT, 849 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L); 850 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR, 851 2f); 852 IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT, 853 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L); 854 MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT, 855 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L); 856 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR, 857 2f); 858 MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM, 859 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L); 860 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong( 861 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L); 862 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong( 863 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L); 864 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong( 865 KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L); 866 NOTIFICATION_WHITELIST_DURATION = mParser.getLong( 867 KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L); 868 } 869 } 870 dump(PrintWriter pw)871 void dump(PrintWriter pw) { 872 pw.println(" Settings:"); 873 874 pw.print(" "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("="); 875 TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw); 876 pw.println(); 877 878 pw.print(" "); pw.print(KEY_LIGHT_PRE_IDLE_TIMEOUT); pw.print("="); 879 TimeUtils.formatDuration(LIGHT_PRE_IDLE_TIMEOUT, pw); 880 pw.println(); 881 882 pw.print(" "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("="); 883 TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw); 884 pw.println(); 885 886 pw.print(" "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("="); 887 pw.print(LIGHT_IDLE_FACTOR); 888 pw.println(); 889 890 pw.print(" "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT); pw.print("="); 891 TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT, pw); 892 pw.println(); 893 894 pw.print(" "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); pw.print("="); 895 TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, pw); 896 pw.println(); 897 898 pw.print(" "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET); pw.print("="); 899 TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, pw); 900 pw.println(); 901 902 pw.print(" "); pw.print(KEY_MIN_LIGHT_MAINTENANCE_TIME); pw.print("="); 903 TimeUtils.formatDuration(MIN_LIGHT_MAINTENANCE_TIME, pw); 904 pw.println(); 905 906 pw.print(" "); pw.print(KEY_MIN_DEEP_MAINTENANCE_TIME); pw.print("="); 907 TimeUtils.formatDuration(MIN_DEEP_MAINTENANCE_TIME, pw); 908 pw.println(); 909 910 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("="); 911 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw); 912 pw.println(); 913 914 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("="); 915 TimeUtils.formatDuration(SENSING_TIMEOUT, pw); 916 pw.println(); 917 918 pw.print(" "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("="); 919 TimeUtils.formatDuration(LOCATING_TIMEOUT, pw); 920 pw.println(); 921 922 pw.print(" "); pw.print(KEY_LOCATION_ACCURACY); pw.print("="); 923 pw.print(LOCATION_ACCURACY); pw.print("m"); 924 pw.println(); 925 926 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("="); 927 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw); 928 pw.println(); 929 930 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("="); 931 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw); 932 pw.println(); 933 934 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("="); 935 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw); 936 pw.println(); 937 938 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("="); 939 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw); 940 pw.println(); 941 942 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("="); 943 pw.println(IDLE_PENDING_FACTOR); 944 945 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("="); 946 TimeUtils.formatDuration(IDLE_TIMEOUT, pw); 947 pw.println(); 948 949 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("="); 950 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw); 951 pw.println(); 952 953 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("="); 954 pw.println(IDLE_FACTOR); 955 956 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("="); 957 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw); 958 pw.println(); 959 960 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("="); 961 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw); 962 pw.println(); 963 964 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("="); 965 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw); 966 pw.println(); 967 968 pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("="); 969 TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw); 970 pw.println(); 971 972 pw.print(" "); pw.print(KEY_NOTIFICATION_WHITELIST_DURATION); pw.print("="); 973 TimeUtils.formatDuration(NOTIFICATION_WHITELIST_DURATION, pw); 974 pw.println(); 975 } 976 } 977 978 private Constants mConstants; 979 980 @Override onAnyMotionResult(int result)981 public void onAnyMotionResult(int result) { 982 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")"); 983 if (result != AnyMotionDetector.RESULT_UNKNOWN) { 984 synchronized (this) { 985 cancelSensingTimeoutAlarmLocked(); 986 } 987 } 988 if ((result == AnyMotionDetector.RESULT_MOVED) || 989 (result == AnyMotionDetector.RESULT_UNKNOWN)) { 990 synchronized (this) { 991 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary"); 992 } 993 } else if (result == AnyMotionDetector.RESULT_STATIONARY) { 994 if (mState == STATE_SENSING) { 995 // If we are currently sensing, it is time to move to locating. 996 synchronized (this) { 997 mNotMoving = true; 998 stepIdleStateLocked("s:stationary"); 999 } 1000 } else if (mState == STATE_LOCATING) { 1001 // If we are currently locating, note that we are not moving and step 1002 // if we have located the position. 1003 synchronized (this) { 1004 mNotMoving = true; 1005 if (mLocated) { 1006 stepIdleStateLocked("s:stationary"); 1007 } 1008 } 1009 } 1010 } 1011 } 1012 1013 private static final int MSG_WRITE_CONFIG = 1; 1014 private static final int MSG_REPORT_IDLE_ON = 2; 1015 private static final int MSG_REPORT_IDLE_ON_LIGHT = 3; 1016 private static final int MSG_REPORT_IDLE_OFF = 4; 1017 private static final int MSG_REPORT_ACTIVE = 5; 1018 private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6; 1019 private static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7; 1020 private static final int MSG_FINISH_IDLE_OP = 8; 1021 1022 final class MyHandler extends Handler { MyHandler(Looper looper)1023 MyHandler(Looper looper) { 1024 super(looper); 1025 } 1026 handleMessage(Message msg)1027 @Override public void handleMessage(Message msg) { 1028 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")"); 1029 switch (msg.what) { 1030 case MSG_WRITE_CONFIG: { 1031 // Does not hold a wakelock. Just let this happen whenever. 1032 handleWriteConfigFile(); 1033 } break; 1034 case MSG_REPORT_IDLE_ON: 1035 case MSG_REPORT_IDLE_ON_LIGHT: { 1036 // mGoingIdleWakeLock is held at this point 1037 EventLogTags.writeDeviceIdleOnStart(); 1038 final boolean deepChanged; 1039 final boolean lightChanged; 1040 if (msg.what == MSG_REPORT_IDLE_ON) { 1041 deepChanged = mLocalPowerManager.setDeviceIdleMode(true); 1042 lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false); 1043 } else { 1044 deepChanged = mLocalPowerManager.setDeviceIdleMode(false); 1045 lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true); 1046 } 1047 try { 1048 mNetworkPolicyManager.setDeviceIdleMode(true); 1049 mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON 1050 ? BatteryStats.DEVICE_IDLE_MODE_DEEP 1051 : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid()); 1052 } catch (RemoteException e) { 1053 } 1054 if (deepChanged) { 1055 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); 1056 } 1057 if (lightChanged) { 1058 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL); 1059 } 1060 EventLogTags.writeDeviceIdleOnComplete(); 1061 mGoingIdleWakeLock.release(); 1062 } break; 1063 case MSG_REPORT_IDLE_OFF: { 1064 // mActiveIdleWakeLock is held at this point 1065 EventLogTags.writeDeviceIdleOffStart("unknown"); 1066 final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false); 1067 final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false); 1068 try { 1069 mNetworkPolicyManager.setDeviceIdleMode(false); 1070 mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF, 1071 null, Process.myUid()); 1072 } catch (RemoteException e) { 1073 } 1074 if (deepChanged) { 1075 incActiveIdleOps(); 1076 getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL, 1077 null, mIdleStartedDoneReceiver, null, 0, null, null); 1078 } 1079 if (lightChanged) { 1080 incActiveIdleOps(); 1081 getContext().sendOrderedBroadcastAsUser(mLightIdleIntent, UserHandle.ALL, 1082 null, mIdleStartedDoneReceiver, null, 0, null, null); 1083 } 1084 // Always start with one active op for the message being sent here. 1085 // Now we are done! 1086 decActiveIdleOps(); 1087 EventLogTags.writeDeviceIdleOffComplete(); 1088 } break; 1089 case MSG_REPORT_ACTIVE: { 1090 // The device is awake at this point, so no wakelock necessary. 1091 String activeReason = (String)msg.obj; 1092 int activeUid = msg.arg1; 1093 EventLogTags.writeDeviceIdleOffStart( 1094 activeReason != null ? activeReason : "unknown"); 1095 final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false); 1096 final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false); 1097 try { 1098 mNetworkPolicyManager.setDeviceIdleMode(false); 1099 mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF, 1100 activeReason, activeUid); 1101 } catch (RemoteException e) { 1102 } 1103 if (deepChanged) { 1104 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); 1105 } 1106 if (lightChanged) { 1107 getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL); 1108 } 1109 EventLogTags.writeDeviceIdleOffComplete(); 1110 } break; 1111 case MSG_TEMP_APP_WHITELIST_TIMEOUT: { 1112 // TODO: What is keeping the device awake at this point? Does it need to be? 1113 int uid = msg.arg1; 1114 checkTempAppWhitelistTimeout(uid); 1115 } break; 1116 case MSG_REPORT_MAINTENANCE_ACTIVITY: { 1117 // TODO: What is keeping the device awake at this point? Does it need to be? 1118 boolean active = (msg.arg1 == 1); 1119 final int size = mMaintenanceActivityListeners.beginBroadcast(); 1120 try { 1121 for (int i = 0; i < size; i++) { 1122 try { 1123 mMaintenanceActivityListeners.getBroadcastItem(i) 1124 .onMaintenanceActivityChanged(active); 1125 } catch (RemoteException ignored) { 1126 } 1127 } 1128 } finally { 1129 mMaintenanceActivityListeners.finishBroadcast(); 1130 } 1131 } break; 1132 case MSG_FINISH_IDLE_OP: { 1133 // mActiveIdleWakeLock is held at this point 1134 decActiveIdleOps(); 1135 } break; 1136 } 1137 } 1138 } 1139 1140 final MyHandler mHandler; 1141 1142 BinderService mBinderService; 1143 1144 private final class BinderService extends IDeviceIdleController.Stub { addPowerSaveWhitelistApp(String name)1145 @Override public void addPowerSaveWhitelistApp(String name) { 1146 if (DEBUG) { 1147 Slog.i(TAG, "addPowerSaveWhitelistApp(name = " + name + ")"); 1148 } 1149 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 1150 null); 1151 long ident = Binder.clearCallingIdentity(); 1152 try { 1153 addPowerSaveWhitelistAppInternal(name); 1154 } finally { 1155 Binder.restoreCallingIdentity(ident); 1156 } 1157 } 1158 removePowerSaveWhitelistApp(String name)1159 @Override public void removePowerSaveWhitelistApp(String name) { 1160 if (DEBUG) { 1161 Slog.i(TAG, "removePowerSaveWhitelistApp(name = " + name + ")"); 1162 } 1163 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 1164 null); 1165 long ident = Binder.clearCallingIdentity(); 1166 try { 1167 removePowerSaveWhitelistAppInternal(name); 1168 } finally { 1169 Binder.restoreCallingIdentity(ident); 1170 } 1171 } 1172 getSystemPowerWhitelistExceptIdle()1173 @Override public String[] getSystemPowerWhitelistExceptIdle() { 1174 return getSystemPowerWhitelistExceptIdleInternal(); 1175 } 1176 getSystemPowerWhitelist()1177 @Override public String[] getSystemPowerWhitelist() { 1178 return getSystemPowerWhitelistInternal(); 1179 } 1180 getUserPowerWhitelist()1181 @Override public String[] getUserPowerWhitelist() { 1182 return getUserPowerWhitelistInternal(); 1183 } 1184 getFullPowerWhitelistExceptIdle()1185 @Override public String[] getFullPowerWhitelistExceptIdle() { 1186 return getFullPowerWhitelistExceptIdleInternal(); 1187 } 1188 getFullPowerWhitelist()1189 @Override public String[] getFullPowerWhitelist() { 1190 return getFullPowerWhitelistInternal(); 1191 } 1192 getAppIdWhitelistExceptIdle()1193 @Override public int[] getAppIdWhitelistExceptIdle() { 1194 return getAppIdWhitelistExceptIdleInternal(); 1195 } 1196 getAppIdWhitelist()1197 @Override public int[] getAppIdWhitelist() { 1198 return getAppIdWhitelistInternal(); 1199 } 1200 getAppIdUserWhitelist()1201 @Override public int[] getAppIdUserWhitelist() { 1202 return getAppIdUserWhitelistInternal(); 1203 } 1204 getAppIdTempWhitelist()1205 @Override public int[] getAppIdTempWhitelist() { 1206 return getAppIdTempWhitelistInternal(); 1207 } 1208 isPowerSaveWhitelistExceptIdleApp(String name)1209 @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) { 1210 return isPowerSaveWhitelistExceptIdleAppInternal(name); 1211 } 1212 isPowerSaveWhitelistApp(String name)1213 @Override public boolean isPowerSaveWhitelistApp(String name) { 1214 return isPowerSaveWhitelistAppInternal(name); 1215 } 1216 addPowerSaveTempWhitelistApp(String packageName, long duration, int userId, String reason)1217 @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration, 1218 int userId, String reason) throws RemoteException { 1219 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason); 1220 } 1221 addPowerSaveTempWhitelistAppForMms(String packageName, int userId, String reason)1222 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName, 1223 int userId, String reason) throws RemoteException { 1224 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION; 1225 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason); 1226 return duration; 1227 } 1228 addPowerSaveTempWhitelistAppForSms(String packageName, int userId, String reason)1229 @Override public long addPowerSaveTempWhitelistAppForSms(String packageName, 1230 int userId, String reason) throws RemoteException { 1231 long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION; 1232 addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason); 1233 return duration; 1234 } 1235 exitIdle(String reason)1236 @Override public void exitIdle(String reason) { 1237 getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER, 1238 null); 1239 long ident = Binder.clearCallingIdentity(); 1240 try { 1241 exitIdleInternal(reason); 1242 } finally { 1243 Binder.restoreCallingIdentity(ident); 1244 } 1245 } 1246 registerMaintenanceActivityListener( IMaintenanceActivityListener listener)1247 @Override public boolean registerMaintenanceActivityListener( 1248 IMaintenanceActivityListener listener) { 1249 return DeviceIdleController.this.registerMaintenanceActivityListener(listener); 1250 } 1251 unregisterMaintenanceActivityListener( IMaintenanceActivityListener listener)1252 @Override public void unregisterMaintenanceActivityListener( 1253 IMaintenanceActivityListener listener) { 1254 DeviceIdleController.this.unregisterMaintenanceActivityListener(listener); 1255 } 1256 dump(FileDescriptor fd, PrintWriter pw, String[] args)1257 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1258 DeviceIdleController.this.dump(fd, pw, args); 1259 } 1260 onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)1261 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, 1262 FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 1263 (new Shell()).exec(this, in, out, err, args, callback, resultReceiver); 1264 } 1265 } 1266 1267 public class LocalService { 1268 // duration in milliseconds addPowerSaveTempWhitelistApp(int callingUid, String packageName, long duration, int userId, boolean sync, String reason)1269 public void addPowerSaveTempWhitelistApp(int callingUid, String packageName, 1270 long duration, int userId, boolean sync, String reason) { 1271 addPowerSaveTempWhitelistAppInternal(callingUid, packageName, duration, 1272 userId, sync, reason); 1273 } 1274 1275 // duration in milliseconds addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync, String reason)1276 public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync, 1277 String reason) { 1278 addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason); 1279 } 1280 1281 // duration in milliseconds getNotificationWhitelistDuration()1282 public long getNotificationWhitelistDuration() { 1283 return mConstants.NOTIFICATION_WHITELIST_DURATION; 1284 } 1285 setNetworkPolicyTempWhitelistCallback(Runnable callback)1286 public void setNetworkPolicyTempWhitelistCallback(Runnable callback) { 1287 setNetworkPolicyTempWhitelistCallbackInternal(callback); 1288 } 1289 setJobsActive(boolean active)1290 public void setJobsActive(boolean active) { 1291 DeviceIdleController.this.setJobsActive(active); 1292 } 1293 1294 // Up-call from alarm manager. setAlarmsActive(boolean active)1295 public void setAlarmsActive(boolean active) { 1296 DeviceIdleController.this.setAlarmsActive(active); 1297 } 1298 1299 /** Is the app on any of the power save whitelists, whether system or user? */ isAppOnWhitelist(int appid)1300 public boolean isAppOnWhitelist(int appid) { 1301 return DeviceIdleController.this.isAppOnWhitelistInternal(appid); 1302 } 1303 1304 /** 1305 * Returns the array of app ids whitelisted by user. Take care not to 1306 * modify this, as it is a reference to the original copy. But the reference 1307 * can change when the list changes, so it needs to be re-acquired when 1308 * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent. 1309 */ getPowerSaveWhitelistUserAppIds()1310 public int[] getPowerSaveWhitelistUserAppIds() { 1311 return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds(); 1312 } 1313 } 1314 DeviceIdleController(Context context)1315 public DeviceIdleController(Context context) { 1316 super(context); 1317 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml")); 1318 mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); 1319 } 1320 isAppOnWhitelistInternal(int appid)1321 boolean isAppOnWhitelistInternal(int appid) { 1322 synchronized (this) { 1323 return Arrays.binarySearch(mPowerSaveWhitelistAllAppIdArray, appid) >= 0; 1324 } 1325 } 1326 getPowerSaveWhitelistUserAppIds()1327 int[] getPowerSaveWhitelistUserAppIds() { 1328 synchronized (this) { 1329 return mPowerSaveWhitelistUserAppIdArray; 1330 } 1331 } 1332 getSystemDir()1333 private static File getSystemDir() { 1334 return new File(Environment.getDataDirectory(), "system"); 1335 } 1336 1337 @Override onStart()1338 public void onStart() { 1339 final PackageManager pm = getContext().getPackageManager(); 1340 1341 synchronized (this) { 1342 mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean( 1343 com.android.internal.R.bool.config_enableAutoPowerModes); 1344 SystemConfig sysConfig = SystemConfig.getInstance(); 1345 ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle(); 1346 for (int i=0; i<allowPowerExceptIdle.size(); i++) { 1347 String pkg = allowPowerExceptIdle.valueAt(i); 1348 try { 1349 ApplicationInfo ai = pm.getApplicationInfo(pkg, 1350 PackageManager.MATCH_SYSTEM_ONLY); 1351 int appid = UserHandle.getAppId(ai.uid); 1352 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid); 1353 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true); 1354 } catch (PackageManager.NameNotFoundException e) { 1355 } 1356 } 1357 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); 1358 for (int i=0; i<allowPower.size(); i++) { 1359 String pkg = allowPower.valueAt(i); 1360 try { 1361 ApplicationInfo ai = pm.getApplicationInfo(pkg, 1362 PackageManager.MATCH_SYSTEM_ONLY); 1363 int appid = UserHandle.getAppId(ai.uid); 1364 // These apps are on both the whitelist-except-idle as well 1365 // as the full whitelist, so they apply in all cases. 1366 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid); 1367 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true); 1368 mPowerSaveWhitelistApps.put(ai.packageName, appid); 1369 mPowerSaveWhitelistSystemAppIds.put(appid, true); 1370 } catch (PackageManager.NameNotFoundException e) { 1371 } 1372 } 1373 1374 mConstants = new Constants(mHandler, getContext().getContentResolver()); 1375 1376 readConfigFileLocked(); 1377 updateWhitelistAppIdsLocked(); 1378 1379 mNetworkConnected = true; 1380 mScreenOn = true; 1381 // Start out assuming we are charging. If we aren't, we will at least get 1382 // a battery update the next time the level drops. 1383 mCharging = true; 1384 mState = STATE_ACTIVE; 1385 mLightState = LIGHT_STATE_ACTIVE; 1386 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT; 1387 } 1388 1389 mBinderService = new BinderService(); 1390 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService); 1391 publishLocalService(LocalService.class, new LocalService()); 1392 } 1393 1394 @Override onBootPhase(int phase)1395 public void onBootPhase(int phase) { 1396 if (phase == PHASE_SYSTEM_SERVICES_READY) { 1397 synchronized (this) { 1398 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); 1399 mBatteryStats = BatteryStatsService.getService(); 1400 mLocalActivityManager = getLocalService(ActivityManagerInternal.class); 1401 mLocalPowerManager = getLocalService(PowerManagerInternal.class); 1402 mPowerManager = getContext().getSystemService(PowerManager.class); 1403 mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1404 "deviceidle_maint"); 1405 mActiveIdleWakeLock.setReferenceCounted(false); 1406 mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1407 "deviceidle_going_idle"); 1408 mGoingIdleWakeLock.setReferenceCounted(true); 1409 mConnectivityService = (ConnectivityService)ServiceManager.getService( 1410 Context.CONNECTIVITY_SERVICE); 1411 mLocalAlarmManager = getLocalService(AlarmManagerService.LocalService.class); 1412 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( 1413 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); 1414 mDisplayManager = (DisplayManager) getContext().getSystemService( 1415 Context.DISPLAY_SERVICE); 1416 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); 1417 int sigMotionSensorId = getContext().getResources().getInteger( 1418 com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor); 1419 if (sigMotionSensorId > 0) { 1420 mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true); 1421 } 1422 if (mMotionSensor == null && getContext().getResources().getBoolean( 1423 com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) { 1424 mMotionSensor = mSensorManager.getDefaultSensor( 1425 Sensor.TYPE_WRIST_TILT_GESTURE, true); 1426 } 1427 if (mMotionSensor == null) { 1428 // As a last ditch, fall back to SMD. 1429 mMotionSensor = mSensorManager.getDefaultSensor( 1430 Sensor.TYPE_SIGNIFICANT_MOTION, true); 1431 } 1432 1433 if (getContext().getResources().getBoolean( 1434 com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) { 1435 mLocationManager = (LocationManager) getContext().getSystemService( 1436 Context.LOCATION_SERVICE); 1437 mLocationRequest = new LocationRequest() 1438 .setQuality(LocationRequest.ACCURACY_FINE) 1439 .setInterval(0) 1440 .setFastestInterval(0) 1441 .setNumUpdates(1); 1442 } 1443 1444 float angleThreshold = getContext().getResources().getInteger( 1445 com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f; 1446 mAnyMotionDetector = new AnyMotionDetector( 1447 (PowerManager) getContext().getSystemService(Context.POWER_SERVICE), 1448 mHandler, mSensorManager, this, angleThreshold); 1449 1450 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 1451 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY 1452 | Intent.FLAG_RECEIVER_FOREGROUND); 1453 mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED); 1454 mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY 1455 | Intent.FLAG_RECEIVER_FOREGROUND); 1456 1457 IntentFilter filter = new IntentFilter(); 1458 filter.addAction(Intent.ACTION_BATTERY_CHANGED); 1459 getContext().registerReceiver(mReceiver, filter); 1460 1461 filter = new IntentFilter(); 1462 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 1463 filter.addDataScheme("package"); 1464 getContext().registerReceiver(mReceiver, filter); 1465 1466 filter = new IntentFilter(); 1467 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 1468 getContext().registerReceiver(mReceiver, filter); 1469 1470 mLocalActivityManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); 1471 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); 1472 mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray); 1473 mDisplayManager.registerDisplayListener(mDisplayListener, null); 1474 updateDisplayLocked(); 1475 } 1476 updateConnectivityState(null); 1477 } 1478 } 1479 addPowerSaveWhitelistAppInternal(String name)1480 public boolean addPowerSaveWhitelistAppInternal(String name) { 1481 synchronized (this) { 1482 try { 1483 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 1484 PackageManager.MATCH_ANY_USER); 1485 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) { 1486 reportPowerSaveWhitelistChangedLocked(); 1487 updateWhitelistAppIdsLocked(); 1488 writeConfigFileLocked(); 1489 } 1490 return true; 1491 } catch (PackageManager.NameNotFoundException e) { 1492 return false; 1493 } 1494 } 1495 } 1496 removePowerSaveWhitelistAppInternal(String name)1497 public boolean removePowerSaveWhitelistAppInternal(String name) { 1498 synchronized (this) { 1499 if (mPowerSaveWhitelistUserApps.remove(name) != null) { 1500 reportPowerSaveWhitelistChangedLocked(); 1501 updateWhitelistAppIdsLocked(); 1502 writeConfigFileLocked(); 1503 return true; 1504 } 1505 } 1506 return false; 1507 } 1508 getPowerSaveWhitelistAppInternal(String name)1509 public boolean getPowerSaveWhitelistAppInternal(String name) { 1510 synchronized (this) { 1511 return mPowerSaveWhitelistUserApps.containsKey(name); 1512 } 1513 } 1514 addPowerSaveWhitelistExceptIdleInternal(String name)1515 public boolean addPowerSaveWhitelistExceptIdleInternal(String name) { 1516 synchronized (this) { 1517 try { 1518 final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 1519 PackageManager.MATCH_ANY_USER); 1520 if (mPowerSaveWhitelistAppsExceptIdle.put(name, UserHandle.getAppId(ai.uid)) 1521 == null) { 1522 mPowerSaveWhitelistUserAppsExceptIdle.add(name); 1523 reportPowerSaveWhitelistChangedLocked(); 1524 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray( 1525 mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps, 1526 mPowerSaveWhitelistExceptIdleAppIds); 1527 } 1528 return true; 1529 } catch (PackageManager.NameNotFoundException e) { 1530 return false; 1531 } 1532 } 1533 } 1534 resetPowerSaveWhitelistExceptIdleInternal()1535 public void resetPowerSaveWhitelistExceptIdleInternal() { 1536 synchronized (this) { 1537 if (mPowerSaveWhitelistAppsExceptIdle.removeAll( 1538 mPowerSaveWhitelistUserAppsExceptIdle)) { 1539 reportPowerSaveWhitelistChangedLocked(); 1540 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray( 1541 mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps, 1542 mPowerSaveWhitelistExceptIdleAppIds); 1543 mPowerSaveWhitelistUserAppsExceptIdle.clear(); 1544 } 1545 } 1546 } 1547 getPowerSaveWhitelistExceptIdleInternal(String name)1548 public boolean getPowerSaveWhitelistExceptIdleInternal(String name) { 1549 synchronized (this) { 1550 return mPowerSaveWhitelistAppsExceptIdle.containsKey(name); 1551 } 1552 } 1553 getSystemPowerWhitelistExceptIdleInternal()1554 public String[] getSystemPowerWhitelistExceptIdleInternal() { 1555 synchronized (this) { 1556 int size = mPowerSaveWhitelistAppsExceptIdle.size(); 1557 String[] apps = new String[size]; 1558 for (int i = 0; i < size; i++) { 1559 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i); 1560 } 1561 return apps; 1562 } 1563 } 1564 getSystemPowerWhitelistInternal()1565 public String[] getSystemPowerWhitelistInternal() { 1566 synchronized (this) { 1567 int size = mPowerSaveWhitelistApps.size(); 1568 String[] apps = new String[size]; 1569 for (int i = 0; i < size; i++) { 1570 apps[i] = mPowerSaveWhitelistApps.keyAt(i); 1571 } 1572 return apps; 1573 } 1574 } 1575 getUserPowerWhitelistInternal()1576 public String[] getUserPowerWhitelistInternal() { 1577 synchronized (this) { 1578 int size = mPowerSaveWhitelistUserApps.size(); 1579 String[] apps = new String[size]; 1580 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) { 1581 apps[i] = mPowerSaveWhitelistUserApps.keyAt(i); 1582 } 1583 return apps; 1584 } 1585 } 1586 getFullPowerWhitelistExceptIdleInternal()1587 public String[] getFullPowerWhitelistExceptIdleInternal() { 1588 synchronized (this) { 1589 int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size(); 1590 String[] apps = new String[size]; 1591 int cur = 0; 1592 for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) { 1593 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i); 1594 cur++; 1595 } 1596 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) { 1597 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i); 1598 cur++; 1599 } 1600 return apps; 1601 } 1602 } 1603 getFullPowerWhitelistInternal()1604 public String[] getFullPowerWhitelistInternal() { 1605 synchronized (this) { 1606 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size(); 1607 String[] apps = new String[size]; 1608 int cur = 0; 1609 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) { 1610 apps[cur] = mPowerSaveWhitelistApps.keyAt(i); 1611 cur++; 1612 } 1613 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) { 1614 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i); 1615 cur++; 1616 } 1617 return apps; 1618 } 1619 } 1620 isPowerSaveWhitelistExceptIdleAppInternal(String packageName)1621 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) { 1622 synchronized (this) { 1623 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName) 1624 || mPowerSaveWhitelistUserApps.containsKey(packageName); 1625 } 1626 } 1627 isPowerSaveWhitelistAppInternal(String packageName)1628 public boolean isPowerSaveWhitelistAppInternal(String packageName) { 1629 synchronized (this) { 1630 return mPowerSaveWhitelistApps.containsKey(packageName) 1631 || mPowerSaveWhitelistUserApps.containsKey(packageName); 1632 } 1633 } 1634 getAppIdWhitelistExceptIdleInternal()1635 public int[] getAppIdWhitelistExceptIdleInternal() { 1636 synchronized (this) { 1637 return mPowerSaveWhitelistExceptIdleAppIdArray; 1638 } 1639 } 1640 getAppIdWhitelistInternal()1641 public int[] getAppIdWhitelistInternal() { 1642 synchronized (this) { 1643 return mPowerSaveWhitelistAllAppIdArray; 1644 } 1645 } 1646 getAppIdUserWhitelistInternal()1647 public int[] getAppIdUserWhitelistInternal() { 1648 synchronized (this) { 1649 return mPowerSaveWhitelistUserAppIdArray; 1650 } 1651 } 1652 getAppIdTempWhitelistInternal()1653 public int[] getAppIdTempWhitelistInternal() { 1654 synchronized (this) { 1655 return mTempWhitelistAppIdArray; 1656 } 1657 } 1658 addPowerSaveTempWhitelistAppChecked(String packageName, long duration, int userId, String reason)1659 void addPowerSaveTempWhitelistAppChecked(String packageName, long duration, 1660 int userId, String reason) throws RemoteException { 1661 getContext().enforceCallingPermission( 1662 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, 1663 "No permission to change device idle whitelist"); 1664 final int callingUid = Binder.getCallingUid(); 1665 userId = ActivityManager.getService().handleIncomingUser( 1666 Binder.getCallingPid(), 1667 callingUid, 1668 userId, 1669 /*allowAll=*/ false, 1670 /*requireFull=*/ false, 1671 "addPowerSaveTempWhitelistApp", null); 1672 final long token = Binder.clearCallingIdentity(); 1673 try { 1674 addPowerSaveTempWhitelistAppInternal(callingUid, 1675 packageName, duration, userId, true, reason); 1676 } finally { 1677 Binder.restoreCallingIdentity(token); 1678 } 1679 } 1680 1681 /** 1682 * Adds an app to the temporary whitelist and resets the endTime for granting the 1683 * app an exemption to access network and acquire wakelocks. 1684 */ addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName, long duration, int userId, boolean sync, String reason)1685 void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName, 1686 long duration, int userId, boolean sync, String reason) { 1687 try { 1688 int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId); 1689 int appId = UserHandle.getAppId(uid); 1690 addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason); 1691 } catch (NameNotFoundException e) { 1692 } 1693 } 1694 1695 /** 1696 * Adds an app to the temporary whitelist and resets the endTime for granting the 1697 * app an exemption to access network and acquire wakelocks. 1698 */ addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId, long duration, boolean sync, String reason)1699 void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId, 1700 long duration, boolean sync, String reason) { 1701 final long timeNow = SystemClock.elapsedRealtime(); 1702 Runnable networkPolicyTempWhitelistCallback = null; 1703 synchronized (this) { 1704 int callingAppId = UserHandle.getAppId(callingUid); 1705 if (callingAppId >= Process.FIRST_APPLICATION_UID) { 1706 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) { 1707 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid) 1708 + " is not on whitelist"); 1709 } 1710 } 1711 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION); 1712 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId); 1713 final boolean newEntry = entry == null; 1714 // Set the new end time 1715 if (newEntry) { 1716 entry = new Pair<>(new MutableLong(0), reason); 1717 mTempWhitelistAppIdEndTimes.put(appId, entry); 1718 } 1719 entry.first.value = timeNow + duration; 1720 if (DEBUG) { 1721 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist. New entry: " + newEntry); 1722 } 1723 if (newEntry) { 1724 // No pending timeout for the app id, post a delayed message 1725 try { 1726 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START, 1727 reason, appId); 1728 } catch (RemoteException e) { 1729 } 1730 postTempActiveTimeoutMessage(appId, duration); 1731 updateTempWhitelistAppIdsLocked(appId, true); 1732 if (mNetworkPolicyTempWhitelistCallback != null) { 1733 if (!sync) { 1734 mHandler.post(mNetworkPolicyTempWhitelistCallback); 1735 } else { 1736 networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback; 1737 } 1738 } 1739 reportTempWhitelistChangedLocked(); 1740 } 1741 } 1742 if (networkPolicyTempWhitelistCallback != null) { 1743 networkPolicyTempWhitelistCallback.run(); 1744 } 1745 } 1746 setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback)1747 public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) { 1748 synchronized (this) { 1749 mNetworkPolicyTempWhitelistCallback = callback; 1750 } 1751 } 1752 postTempActiveTimeoutMessage(int uid, long delay)1753 private void postTempActiveTimeoutMessage(int uid, long delay) { 1754 if (DEBUG) { 1755 Slog.d(TAG, "postTempActiveTimeoutMessage: uid=" + uid + ", delay=" + delay); 1756 } 1757 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0), 1758 delay); 1759 } 1760 checkTempAppWhitelistTimeout(int uid)1761 void checkTempAppWhitelistTimeout(int uid) { 1762 final long timeNow = SystemClock.elapsedRealtime(); 1763 if (DEBUG) { 1764 Slog.d(TAG, "checkTempAppWhitelistTimeout: uid=" + uid + ", timeNow=" + timeNow); 1765 } 1766 synchronized (this) { 1767 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid); 1768 if (entry == null) { 1769 // Nothing to do 1770 return; 1771 } 1772 if (timeNow >= entry.first.value) { 1773 mTempWhitelistAppIdEndTimes.delete(uid); 1774 if (DEBUG) { 1775 Slog.d(TAG, "Removing UID " + uid + " from temp whitelist"); 1776 } 1777 updateTempWhitelistAppIdsLocked(uid, false); 1778 if (mNetworkPolicyTempWhitelistCallback != null) { 1779 mHandler.post(mNetworkPolicyTempWhitelistCallback); 1780 } 1781 reportTempWhitelistChangedLocked(); 1782 try { 1783 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH, 1784 entry.second, uid); 1785 } catch (RemoteException e) { 1786 } 1787 } else { 1788 // Need more time 1789 if (DEBUG) { 1790 Slog.d(TAG, "Time to remove UID " + uid + ": " + entry.first.value); 1791 } 1792 postTempActiveTimeoutMessage(uid, entry.first.value - timeNow); 1793 } 1794 } 1795 } 1796 exitIdleInternal(String reason)1797 public void exitIdleInternal(String reason) { 1798 synchronized (this) { 1799 becomeActiveLocked(reason, Binder.getCallingUid()); 1800 } 1801 } 1802 updateConnectivityState(Intent connIntent)1803 void updateConnectivityState(Intent connIntent) { 1804 ConnectivityService cm; 1805 synchronized (this) { 1806 cm = mConnectivityService; 1807 } 1808 if (cm == null) { 1809 return; 1810 } 1811 // Note: can't call out to ConnectivityService with our lock held. 1812 NetworkInfo ni = cm.getActiveNetworkInfo(); 1813 synchronized (this) { 1814 boolean conn; 1815 if (ni == null) { 1816 conn = false; 1817 } else { 1818 if (connIntent == null) { 1819 conn = ni.isConnected(); 1820 } else { 1821 final int networkType = 1822 connIntent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1823 ConnectivityManager.TYPE_NONE); 1824 if (ni.getType() != networkType) { 1825 return; 1826 } 1827 conn = !connIntent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, 1828 false); 1829 } 1830 } 1831 if (conn != mNetworkConnected) { 1832 mNetworkConnected = conn; 1833 if (conn && mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) { 1834 stepLightIdleStateLocked("network"); 1835 } 1836 } 1837 } 1838 } 1839 updateDisplayLocked()1840 void updateDisplayLocked() { 1841 mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); 1842 // We consider any situation where the display is showing something to be it on, 1843 // because if there is anything shown we are going to be updating it at some 1844 // frequency so can't be allowed to go into deep sleeps. 1845 boolean screenOn = mCurDisplay.getState() == Display.STATE_ON; 1846 if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn); 1847 if (!screenOn && mScreenOn) { 1848 mScreenOn = false; 1849 if (!mForceIdle) { 1850 becomeInactiveIfAppropriateLocked(); 1851 } 1852 } else if (screenOn) { 1853 mScreenOn = true; 1854 if (!mForceIdle) { 1855 becomeActiveLocked("screen", Process.myUid()); 1856 } 1857 } 1858 } 1859 updateChargingLocked(boolean charging)1860 void updateChargingLocked(boolean charging) { 1861 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging); 1862 if (!charging && mCharging) { 1863 mCharging = false; 1864 if (!mForceIdle) { 1865 becomeInactiveIfAppropriateLocked(); 1866 } 1867 } else if (charging) { 1868 mCharging = charging; 1869 if (!mForceIdle) { 1870 becomeActiveLocked("charging", Process.myUid()); 1871 } 1872 } 1873 } 1874 scheduleReportActiveLocked(String activeReason, int activeUid)1875 void scheduleReportActiveLocked(String activeReason, int activeUid) { 1876 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason); 1877 mHandler.sendMessage(msg); 1878 } 1879 becomeActiveLocked(String activeReason, int activeUid)1880 void becomeActiveLocked(String activeReason, int activeUid) { 1881 if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason); 1882 if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) { 1883 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason); 1884 EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason); 1885 scheduleReportActiveLocked(activeReason, activeUid); 1886 mState = STATE_ACTIVE; 1887 mLightState = LIGHT_STATE_ACTIVE; 1888 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT; 1889 mCurIdleBudget = 0; 1890 mMaintenanceStartTime = 0; 1891 resetIdleManagementLocked(); 1892 resetLightIdleManagementLocked(); 1893 addEvent(EVENT_NORMAL); 1894 } 1895 } 1896 becomeInactiveIfAppropriateLocked()1897 void becomeInactiveIfAppropriateLocked() { 1898 if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()"); 1899 if ((!mScreenOn && !mCharging) || mForceIdle) { 1900 // Screen has turned off; we are now going to become inactive and start 1901 // waiting to see if we will ultimately go idle. 1902 if (mState == STATE_ACTIVE && mDeepEnabled) { 1903 mState = STATE_INACTIVE; 1904 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE"); 1905 resetIdleManagementLocked(); 1906 scheduleAlarmLocked(mInactiveTimeout, false); 1907 EventLogTags.writeDeviceIdle(mState, "no activity"); 1908 } 1909 if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) { 1910 mLightState = LIGHT_STATE_INACTIVE; 1911 if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE"); 1912 resetLightIdleManagementLocked(); 1913 scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); 1914 EventLogTags.writeDeviceIdleLight(mLightState, "no activity"); 1915 } 1916 } 1917 } 1918 resetIdleManagementLocked()1919 void resetIdleManagementLocked() { 1920 mNextIdlePendingDelay = 0; 1921 mNextIdleDelay = 0; 1922 mNextLightIdleDelay = 0; 1923 cancelAlarmLocked(); 1924 cancelSensingTimeoutAlarmLocked(); 1925 cancelLocatingLocked(); 1926 stopMonitoringMotionLocked(); 1927 mAnyMotionDetector.stop(); 1928 } 1929 resetLightIdleManagementLocked()1930 void resetLightIdleManagementLocked() { 1931 cancelLightAlarmLocked(); 1932 } 1933 exitForceIdleLocked()1934 void exitForceIdleLocked() { 1935 if (mForceIdle) { 1936 mForceIdle = false; 1937 if (mScreenOn || mCharging) { 1938 becomeActiveLocked("exit-force", Process.myUid()); 1939 } 1940 } 1941 } 1942 stepLightIdleStateLocked(String reason)1943 void stepLightIdleStateLocked(String reason) { 1944 if (mLightState == LIGHT_STATE_OVERRIDE) { 1945 // If we are already in deep device idle mode, then 1946 // there is nothing left to do for light mode. 1947 return; 1948 } 1949 1950 if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState); 1951 EventLogTags.writeDeviceIdleLightStep(); 1952 1953 switch (mLightState) { 1954 case LIGHT_STATE_INACTIVE: 1955 mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; 1956 // Reset the upcoming idle delays. 1957 mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT; 1958 mMaintenanceStartTime = 0; 1959 if (!isOpsInactiveLocked()) { 1960 // We have some active ops going on... give them a chance to finish 1961 // before going in to our first idle. 1962 mLightState = LIGHT_STATE_PRE_IDLE; 1963 EventLogTags.writeDeviceIdleLight(mLightState, reason); 1964 scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT); 1965 break; 1966 } 1967 // Nothing active, fall through to immediately idle. 1968 case LIGHT_STATE_PRE_IDLE: 1969 case LIGHT_STATE_IDLE_MAINTENANCE: 1970 if (mMaintenanceStartTime != 0) { 1971 long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime; 1972 if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) { 1973 // We didn't use up all of our minimum budget; add this to the reserve. 1974 mCurIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET-duration); 1975 } else { 1976 // We used more than our minimum budget; this comes out of the reserve. 1977 mCurIdleBudget -= (duration-mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); 1978 } 1979 } 1980 mMaintenanceStartTime = 0; 1981 scheduleLightAlarmLocked(mNextLightIdleDelay); 1982 mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT, 1983 (long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR)); 1984 if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) { 1985 mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT; 1986 } 1987 if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE."); 1988 mLightState = LIGHT_STATE_IDLE; 1989 EventLogTags.writeDeviceIdleLight(mLightState, reason); 1990 addEvent(EVENT_LIGHT_IDLE); 1991 mGoingIdleWakeLock.acquire(); 1992 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT); 1993 break; 1994 case LIGHT_STATE_IDLE: 1995 case LIGHT_STATE_WAITING_FOR_NETWORK: 1996 if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) { 1997 // We have been idling long enough, now it is time to do some work. 1998 mActiveIdleOpCount = 1; 1999 mActiveIdleWakeLock.acquire(); 2000 mMaintenanceStartTime = SystemClock.elapsedRealtime(); 2001 if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) { 2002 mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; 2003 } else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) { 2004 mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET; 2005 } 2006 scheduleLightAlarmLocked(mCurIdleBudget); 2007 if (DEBUG) Slog.d(TAG, 2008 "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE."); 2009 mLightState = LIGHT_STATE_IDLE_MAINTENANCE; 2010 EventLogTags.writeDeviceIdleLight(mLightState, reason); 2011 addEvent(EVENT_LIGHT_MAINTENANCE); 2012 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF); 2013 } else { 2014 // We'd like to do maintenance, but currently don't have network 2015 // connectivity... let's try to wait until the network comes back. 2016 // We'll only wait for another full idle period, however, and then give up. 2017 scheduleLightAlarmLocked(mNextLightIdleDelay); 2018 if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK."); 2019 mLightState = LIGHT_STATE_WAITING_FOR_NETWORK; 2020 EventLogTags.writeDeviceIdleLight(mLightState, reason); 2021 } 2022 break; 2023 } 2024 } 2025 stepIdleStateLocked(String reason)2026 void stepIdleStateLocked(String reason) { 2027 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState); 2028 EventLogTags.writeDeviceIdleStep(); 2029 2030 final long now = SystemClock.elapsedRealtime(); 2031 if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { 2032 // Whoops, there is an upcoming alarm. We don't actually want to go idle. 2033 if (mState != STATE_ACTIVE) { 2034 becomeActiveLocked("alarm", Process.myUid()); 2035 becomeInactiveIfAppropriateLocked(); 2036 } 2037 return; 2038 } 2039 2040 switch (mState) { 2041 case STATE_INACTIVE: 2042 // We have now been inactive long enough, it is time to start looking 2043 // for motion and sleep some more while doing so. 2044 startMonitoringMotionLocked(); 2045 scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false); 2046 // Reset the upcoming idle delays. 2047 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT; 2048 mNextIdleDelay = mConstants.IDLE_TIMEOUT; 2049 mState = STATE_IDLE_PENDING; 2050 if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING."); 2051 EventLogTags.writeDeviceIdle(mState, reason); 2052 break; 2053 case STATE_IDLE_PENDING: 2054 mState = STATE_SENSING; 2055 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING."); 2056 EventLogTags.writeDeviceIdle(mState, reason); 2057 scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT); 2058 cancelLocatingLocked(); 2059 mNotMoving = false; 2060 mLocated = false; 2061 mLastGenericLocation = null; 2062 mLastGpsLocation = null; 2063 mAnyMotionDetector.checkForAnyMotion(); 2064 break; 2065 case STATE_SENSING: 2066 cancelSensingTimeoutAlarmLocked(); 2067 mState = STATE_LOCATING; 2068 if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING."); 2069 EventLogTags.writeDeviceIdle(mState, reason); 2070 scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false); 2071 if (mLocationManager != null 2072 && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) { 2073 mLocationManager.requestLocationUpdates(mLocationRequest, 2074 mGenericLocationListener, mHandler.getLooper()); 2075 mLocating = true; 2076 } else { 2077 mHasNetworkLocation = false; 2078 } 2079 if (mLocationManager != null 2080 && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { 2081 mHasGps = true; 2082 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5, 2083 mGpsLocationListener, mHandler.getLooper()); 2084 mLocating = true; 2085 } else { 2086 mHasGps = false; 2087 } 2088 // If we have a location provider, we're all set, the listeners will move state 2089 // forward. 2090 if (mLocating) { 2091 break; 2092 } 2093 2094 // Otherwise, we have to move from locating into idle maintenance. 2095 case STATE_LOCATING: 2096 cancelAlarmLocked(); 2097 cancelLocatingLocked(); 2098 mAnyMotionDetector.stop(); 2099 2100 case STATE_IDLE_MAINTENANCE: 2101 scheduleAlarmLocked(mNextIdleDelay, true); 2102 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay + 2103 " ms."); 2104 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR); 2105 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay); 2106 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT); 2107 if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) { 2108 mNextIdleDelay = mConstants.IDLE_TIMEOUT; 2109 } 2110 mState = STATE_IDLE; 2111 if (mLightState != LIGHT_STATE_OVERRIDE) { 2112 mLightState = LIGHT_STATE_OVERRIDE; 2113 cancelLightAlarmLocked(); 2114 } 2115 EventLogTags.writeDeviceIdle(mState, reason); 2116 addEvent(EVENT_DEEP_IDLE); 2117 mGoingIdleWakeLock.acquire(); 2118 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON); 2119 break; 2120 case STATE_IDLE: 2121 // We have been idling long enough, now it is time to do some work. 2122 mActiveIdleOpCount = 1; 2123 mActiveIdleWakeLock.acquire(); 2124 scheduleAlarmLocked(mNextIdlePendingDelay, false); 2125 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " + 2126 "Next alarm in " + mNextIdlePendingDelay + " ms."); 2127 mMaintenanceStartTime = SystemClock.elapsedRealtime(); 2128 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT, 2129 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR)); 2130 if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) { 2131 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT; 2132 } 2133 mState = STATE_IDLE_MAINTENANCE; 2134 EventLogTags.writeDeviceIdle(mState, reason); 2135 addEvent(EVENT_DEEP_MAINTENANCE); 2136 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF); 2137 break; 2138 } 2139 } 2140 incActiveIdleOps()2141 void incActiveIdleOps() { 2142 synchronized (this) { 2143 mActiveIdleOpCount++; 2144 } 2145 } 2146 decActiveIdleOps()2147 void decActiveIdleOps() { 2148 synchronized (this) { 2149 mActiveIdleOpCount--; 2150 if (mActiveIdleOpCount <= 0) { 2151 exitMaintenanceEarlyIfNeededLocked(); 2152 mActiveIdleWakeLock.release(); 2153 } 2154 } 2155 } 2156 setJobsActive(boolean active)2157 void setJobsActive(boolean active) { 2158 synchronized (this) { 2159 mJobsActive = active; 2160 reportMaintenanceActivityIfNeededLocked(); 2161 if (!active) { 2162 exitMaintenanceEarlyIfNeededLocked(); 2163 } 2164 } 2165 } 2166 setAlarmsActive(boolean active)2167 void setAlarmsActive(boolean active) { 2168 synchronized (this) { 2169 mAlarmsActive = active; 2170 if (!active) { 2171 exitMaintenanceEarlyIfNeededLocked(); 2172 } 2173 } 2174 } 2175 registerMaintenanceActivityListener(IMaintenanceActivityListener listener)2176 boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener) { 2177 synchronized (this) { 2178 mMaintenanceActivityListeners.register(listener); 2179 return mReportedMaintenanceActivity; 2180 } 2181 } 2182 unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener)2183 void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener) { 2184 synchronized (this) { 2185 mMaintenanceActivityListeners.unregister(listener); 2186 } 2187 } 2188 reportMaintenanceActivityIfNeededLocked()2189 void reportMaintenanceActivityIfNeededLocked() { 2190 boolean active = mJobsActive; 2191 if (active == mReportedMaintenanceActivity) { 2192 return; 2193 } 2194 mReportedMaintenanceActivity = active; 2195 Message msg = mHandler.obtainMessage(MSG_REPORT_MAINTENANCE_ACTIVITY, 2196 mReportedMaintenanceActivity ? 1 : 0, 0); 2197 mHandler.sendMessage(msg); 2198 } 2199 isOpsInactiveLocked()2200 boolean isOpsInactiveLocked() { 2201 return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive; 2202 } 2203 exitMaintenanceEarlyIfNeededLocked()2204 void exitMaintenanceEarlyIfNeededLocked() { 2205 if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE 2206 || mLightState == LIGHT_STATE_PRE_IDLE) { 2207 if (isOpsInactiveLocked()) { 2208 final long now = SystemClock.elapsedRealtime(); 2209 if (DEBUG) { 2210 StringBuilder sb = new StringBuilder(); 2211 sb.append("Exit: start="); 2212 TimeUtils.formatDuration(mMaintenanceStartTime, sb); 2213 sb.append(" now="); 2214 TimeUtils.formatDuration(now, sb); 2215 Slog.d(TAG, sb.toString()); 2216 } 2217 if (mState == STATE_IDLE_MAINTENANCE) { 2218 stepIdleStateLocked("s:early"); 2219 } else if (mLightState == LIGHT_STATE_PRE_IDLE) { 2220 stepLightIdleStateLocked("s:predone"); 2221 } else { 2222 stepLightIdleStateLocked("s:early"); 2223 } 2224 } 2225 } 2226 } 2227 motionLocked()2228 void motionLocked() { 2229 if (DEBUG) Slog.d(TAG, "motionLocked()"); 2230 // The motion sensor will have been disabled at this point 2231 handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion"); 2232 } 2233 handleMotionDetectedLocked(long timeout, String type)2234 void handleMotionDetectedLocked(long timeout, String type) { 2235 // The device is not yet active, so we want to go back to the pending idle 2236 // state to wait again for no motion. Note that we only monitor for motion 2237 // after moving out of the inactive state, so no need to worry about that. 2238 boolean becomeInactive = false; 2239 if (mState != STATE_ACTIVE) { 2240 scheduleReportActiveLocked(type, Process.myUid()); 2241 mState = STATE_ACTIVE; 2242 mInactiveTimeout = timeout; 2243 mCurIdleBudget = 0; 2244 mMaintenanceStartTime = 0; 2245 EventLogTags.writeDeviceIdle(mState, type); 2246 addEvent(EVENT_NORMAL); 2247 becomeInactive = true; 2248 } 2249 if (mLightState == LIGHT_STATE_OVERRIDE) { 2250 // We went out of light idle mode because we had started deep idle mode... let's 2251 // now go back and reset things so we resume light idling if appropriate. 2252 mLightState = STATE_ACTIVE; 2253 EventLogTags.writeDeviceIdleLight(mLightState, type); 2254 becomeInactive = true; 2255 } 2256 if (becomeInactive) { 2257 becomeInactiveIfAppropriateLocked(); 2258 } 2259 } 2260 receivedGenericLocationLocked(Location location)2261 void receivedGenericLocationLocked(Location location) { 2262 if (mState != STATE_LOCATING) { 2263 cancelLocatingLocked(); 2264 return; 2265 } 2266 if (DEBUG) Slog.d(TAG, "Generic location: " + location); 2267 mLastGenericLocation = new Location(location); 2268 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) { 2269 return; 2270 } 2271 mLocated = true; 2272 if (mNotMoving) { 2273 stepIdleStateLocked("s:location"); 2274 } 2275 } 2276 receivedGpsLocationLocked(Location location)2277 void receivedGpsLocationLocked(Location location) { 2278 if (mState != STATE_LOCATING) { 2279 cancelLocatingLocked(); 2280 return; 2281 } 2282 if (DEBUG) Slog.d(TAG, "GPS location: " + location); 2283 mLastGpsLocation = new Location(location); 2284 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) { 2285 return; 2286 } 2287 mLocated = true; 2288 if (mNotMoving) { 2289 stepIdleStateLocked("s:gps"); 2290 } 2291 } 2292 startMonitoringMotionLocked()2293 void startMonitoringMotionLocked() { 2294 if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()"); 2295 if (mMotionSensor != null && !mMotionListener.active) { 2296 mMotionListener.registerLocked(); 2297 } 2298 } 2299 stopMonitoringMotionLocked()2300 void stopMonitoringMotionLocked() { 2301 if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()"); 2302 if (mMotionSensor != null && mMotionListener.active) { 2303 mMotionListener.unregisterLocked(); 2304 } 2305 } 2306 cancelAlarmLocked()2307 void cancelAlarmLocked() { 2308 if (mNextAlarmTime != 0) { 2309 mNextAlarmTime = 0; 2310 mAlarmManager.cancel(mDeepAlarmListener); 2311 } 2312 } 2313 cancelLightAlarmLocked()2314 void cancelLightAlarmLocked() { 2315 if (mNextLightAlarmTime != 0) { 2316 mNextLightAlarmTime = 0; 2317 mAlarmManager.cancel(mLightAlarmListener); 2318 } 2319 } 2320 cancelLocatingLocked()2321 void cancelLocatingLocked() { 2322 if (mLocating) { 2323 mLocationManager.removeUpdates(mGenericLocationListener); 2324 mLocationManager.removeUpdates(mGpsLocationListener); 2325 mLocating = false; 2326 } 2327 } 2328 cancelSensingTimeoutAlarmLocked()2329 void cancelSensingTimeoutAlarmLocked() { 2330 if (mNextSensingTimeoutAlarmTime != 0) { 2331 mNextSensingTimeoutAlarmTime = 0; 2332 mAlarmManager.cancel(mSensingTimeoutAlarmListener); 2333 } 2334 } 2335 scheduleAlarmLocked(long delay, boolean idleUntil)2336 void scheduleAlarmLocked(long delay, boolean idleUntil) { 2337 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")"); 2338 if (mMotionSensor == null) { 2339 // If there is no motion sensor on this device, then we won't schedule 2340 // alarms, because we can't determine if the device is not moving. This effectively 2341 // turns off normal execution of device idling, although it is still possible to 2342 // manually poke it by pretending like the alarm is going off. 2343 return; 2344 } 2345 mNextAlarmTime = SystemClock.elapsedRealtime() + delay; 2346 if (idleUntil) { 2347 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP, 2348 mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler); 2349 } else { 2350 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 2351 mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler); 2352 } 2353 } 2354 scheduleLightAlarmLocked(long delay)2355 void scheduleLightAlarmLocked(long delay) { 2356 if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")"); 2357 mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay; 2358 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 2359 mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler); 2360 } 2361 scheduleSensingTimeoutAlarmLocked(long delay)2362 void scheduleSensingTimeoutAlarmLocked(long delay) { 2363 if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")"); 2364 mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay; 2365 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime, 2366 "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler); 2367 } 2368 buildAppIdArray(ArrayMap<String, Integer> systemApps, ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds)2369 private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps, 2370 ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) { 2371 outAppIds.clear(); 2372 if (systemApps != null) { 2373 for (int i = 0; i < systemApps.size(); i++) { 2374 outAppIds.put(systemApps.valueAt(i), true); 2375 } 2376 } 2377 if (userApps != null) { 2378 for (int i = 0; i < userApps.size(); i++) { 2379 outAppIds.put(userApps.valueAt(i), true); 2380 } 2381 } 2382 int size = outAppIds.size(); 2383 int[] appids = new int[size]; 2384 for (int i = 0; i < size; i++) { 2385 appids[i] = outAppIds.keyAt(i); 2386 } 2387 return appids; 2388 } 2389 updateWhitelistAppIdsLocked()2390 private void updateWhitelistAppIdsLocked() { 2391 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle, 2392 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds); 2393 mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps, 2394 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds); 2395 mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null, 2396 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds); 2397 if (mLocalActivityManager != null) { 2398 if (DEBUG) { 2399 Slog.d(TAG, "Setting activity manager whitelist to " 2400 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray)); 2401 } 2402 mLocalActivityManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); 2403 } 2404 if (mLocalPowerManager != null) { 2405 if (DEBUG) { 2406 Slog.d(TAG, "Setting wakelock whitelist to " 2407 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray)); 2408 } 2409 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); 2410 } 2411 if (mLocalAlarmManager != null) { 2412 if (DEBUG) { 2413 Slog.d(TAG, "Setting alarm whitelist to " 2414 + Arrays.toString(mPowerSaveWhitelistUserAppIdArray)); 2415 } 2416 mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray); 2417 } 2418 } 2419 updateTempWhitelistAppIdsLocked(int appId, boolean adding)2420 private void updateTempWhitelistAppIdsLocked(int appId, boolean adding) { 2421 final int size = mTempWhitelistAppIdEndTimes.size(); 2422 if (mTempWhitelistAppIdArray.length != size) { 2423 mTempWhitelistAppIdArray = new int[size]; 2424 } 2425 for (int i = 0; i < size; i++) { 2426 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i); 2427 } 2428 if (mLocalActivityManager != null) { 2429 if (DEBUG) { 2430 Slog.d(TAG, "Setting activity manager temp whitelist to " 2431 + Arrays.toString(mTempWhitelistAppIdArray)); 2432 } 2433 mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, appId, 2434 adding); 2435 } 2436 if (mLocalPowerManager != null) { 2437 if (DEBUG) { 2438 Slog.d(TAG, "Setting wakelock temp whitelist to " 2439 + Arrays.toString(mTempWhitelistAppIdArray)); 2440 } 2441 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray); 2442 } 2443 } 2444 reportPowerSaveWhitelistChangedLocked()2445 private void reportPowerSaveWhitelistChangedLocked() { 2446 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); 2447 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 2448 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM); 2449 } 2450 reportTempWhitelistChangedLocked()2451 private void reportTempWhitelistChangedLocked() { 2452 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED); 2453 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 2454 getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM); 2455 } 2456 readConfigFileLocked()2457 void readConfigFileLocked() { 2458 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile()); 2459 mPowerSaveWhitelistUserApps.clear(); 2460 FileInputStream stream; 2461 try { 2462 stream = mConfigFile.openRead(); 2463 } catch (FileNotFoundException e) { 2464 return; 2465 } 2466 try { 2467 XmlPullParser parser = Xml.newPullParser(); 2468 parser.setInput(stream, StandardCharsets.UTF_8.name()); 2469 readConfigFileLocked(parser); 2470 } catch (XmlPullParserException e) { 2471 } finally { 2472 try { 2473 stream.close(); 2474 } catch (IOException e) { 2475 } 2476 } 2477 } 2478 readConfigFileLocked(XmlPullParser parser)2479 private void readConfigFileLocked(XmlPullParser parser) { 2480 final PackageManager pm = getContext().getPackageManager(); 2481 2482 try { 2483 int type; 2484 while ((type = parser.next()) != XmlPullParser.START_TAG 2485 && type != XmlPullParser.END_DOCUMENT) { 2486 ; 2487 } 2488 2489 if (type != XmlPullParser.START_TAG) { 2490 throw new IllegalStateException("no start tag found"); 2491 } 2492 2493 int outerDepth = parser.getDepth(); 2494 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2495 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2496 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2497 continue; 2498 } 2499 2500 String tagName = parser.getName(); 2501 if (tagName.equals("wl")) { 2502 String name = parser.getAttributeValue(null, "n"); 2503 if (name != null) { 2504 try { 2505 ApplicationInfo ai = pm.getApplicationInfo(name, 2506 PackageManager.MATCH_ANY_USER); 2507 mPowerSaveWhitelistUserApps.put(ai.packageName, 2508 UserHandle.getAppId(ai.uid)); 2509 } catch (PackageManager.NameNotFoundException e) { 2510 } 2511 } 2512 } else { 2513 Slog.w(TAG, "Unknown element under <config>: " 2514 + parser.getName()); 2515 XmlUtils.skipCurrentTag(parser); 2516 } 2517 } 2518 2519 } catch (IllegalStateException e) { 2520 Slog.w(TAG, "Failed parsing config " + e); 2521 } catch (NullPointerException e) { 2522 Slog.w(TAG, "Failed parsing config " + e); 2523 } catch (NumberFormatException e) { 2524 Slog.w(TAG, "Failed parsing config " + e); 2525 } catch (XmlPullParserException e) { 2526 Slog.w(TAG, "Failed parsing config " + e); 2527 } catch (IOException e) { 2528 Slog.w(TAG, "Failed parsing config " + e); 2529 } catch (IndexOutOfBoundsException e) { 2530 Slog.w(TAG, "Failed parsing config " + e); 2531 } 2532 } 2533 writeConfigFileLocked()2534 void writeConfigFileLocked() { 2535 mHandler.removeMessages(MSG_WRITE_CONFIG); 2536 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000); 2537 } 2538 handleWriteConfigFile()2539 void handleWriteConfigFile() { 2540 final ByteArrayOutputStream memStream = new ByteArrayOutputStream(); 2541 2542 try { 2543 synchronized (this) { 2544 XmlSerializer out = new FastXmlSerializer(); 2545 out.setOutput(memStream, StandardCharsets.UTF_8.name()); 2546 writeConfigFileLocked(out); 2547 } 2548 } catch (IOException e) { 2549 } 2550 2551 synchronized (mConfigFile) { 2552 FileOutputStream stream = null; 2553 try { 2554 stream = mConfigFile.startWrite(); 2555 memStream.writeTo(stream); 2556 stream.flush(); 2557 FileUtils.sync(stream); 2558 stream.close(); 2559 mConfigFile.finishWrite(stream); 2560 } catch (IOException e) { 2561 Slog.w(TAG, "Error writing config file", e); 2562 mConfigFile.failWrite(stream); 2563 } 2564 } 2565 } 2566 writeConfigFileLocked(XmlSerializer out)2567 void writeConfigFileLocked(XmlSerializer out) throws IOException { 2568 out.startDocument(null, true); 2569 out.startTag(null, "config"); 2570 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { 2571 String name = mPowerSaveWhitelistUserApps.keyAt(i); 2572 out.startTag(null, "wl"); 2573 out.attribute(null, "n", name); 2574 out.endTag(null, "wl"); 2575 } 2576 out.endTag(null, "config"); 2577 out.endDocument(); 2578 } 2579 dumpHelp(PrintWriter pw)2580 static void dumpHelp(PrintWriter pw) { 2581 pw.println("Device idle controller (deviceidle) commands:"); 2582 pw.println(" help"); 2583 pw.println(" Print this help text."); 2584 pw.println(" step [light|deep]"); 2585 pw.println(" Immediately step to next state, without waiting for alarm."); 2586 pw.println(" force-idle [light|deep]"); 2587 pw.println(" Force directly into idle mode, regardless of other device state."); 2588 pw.println(" force-inactive"); 2589 pw.println(" Force to be inactive, ready to freely step idle states."); 2590 pw.println(" unforce"); 2591 pw.println(" Resume normal functioning after force-idle or force-inactive."); 2592 pw.println(" get [light|deep|force|screen|charging|network]"); 2593 pw.println(" Retrieve the current given state."); 2594 pw.println(" disable [light|deep|all]"); 2595 pw.println(" Completely disable device idle mode."); 2596 pw.println(" enable [light|deep|all]"); 2597 pw.println(" Re-enable device idle mode after it had previously been disabled."); 2598 pw.println(" enabled [light|deep|all]"); 2599 pw.println(" Print 1 if device idle mode is currently enabled, else 0."); 2600 pw.println(" whitelist"); 2601 pw.println(" Print currently whitelisted apps."); 2602 pw.println(" whitelist [package ...]"); 2603 pw.println(" Add (prefix with +) or remove (prefix with -) packages."); 2604 pw.println(" except-idle-whitelist [package ...|reset]"); 2605 pw.println(" Prefix the package with '+' to add it to whitelist or " 2606 + "'=' to check if it is already whitelisted"); 2607 pw.println(" [reset] will reset the whitelist to it's original state"); 2608 pw.println(" Note that unlike <whitelist> cmd, " 2609 + "changes made using this won't be persisted across boots"); 2610 pw.println(" tempwhitelist"); 2611 pw.println(" Print packages that are temporarily whitelisted."); 2612 pw.println(" tempwhitelist [-u USER] [-d DURATION] [package ..]"); 2613 pw.println(" Temporarily place packages in whitelist for DURATION milliseconds."); 2614 pw.println(" If no DURATION is specified, 10 seconds is used"); 2615 } 2616 2617 class Shell extends ShellCommand { 2618 int userId = UserHandle.USER_SYSTEM; 2619 2620 @Override onCommand(String cmd)2621 public int onCommand(String cmd) { 2622 return onShellCommand(this, cmd); 2623 } 2624 2625 @Override onHelp()2626 public void onHelp() { 2627 PrintWriter pw = getOutPrintWriter(); 2628 dumpHelp(pw); 2629 } 2630 } 2631 onShellCommand(Shell shell, String cmd)2632 int onShellCommand(Shell shell, String cmd) { 2633 PrintWriter pw = shell.getOutPrintWriter(); 2634 if ("step".equals(cmd)) { 2635 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 2636 null); 2637 synchronized (this) { 2638 long token = Binder.clearCallingIdentity(); 2639 String arg = shell.getNextArg(); 2640 try { 2641 if (arg == null || "deep".equals(arg)) { 2642 stepIdleStateLocked("s:shell"); 2643 pw.print("Stepped to deep: "); 2644 pw.println(stateToString(mState)); 2645 } else if ("light".equals(arg)) { 2646 stepLightIdleStateLocked("s:shell"); 2647 pw.print("Stepped to light: "); pw.println(lightStateToString(mLightState)); 2648 } else { 2649 pw.println("Unknown idle mode: " + arg); 2650 } 2651 } finally { 2652 Binder.restoreCallingIdentity(token); 2653 } 2654 } 2655 } else if ("force-idle".equals(cmd)) { 2656 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 2657 null); 2658 synchronized (this) { 2659 long token = Binder.clearCallingIdentity(); 2660 String arg = shell.getNextArg(); 2661 try { 2662 if (arg == null || "deep".equals(arg)) { 2663 if (!mDeepEnabled) { 2664 pw.println("Unable to go deep idle; not enabled"); 2665 return -1; 2666 } 2667 mForceIdle = true; 2668 becomeInactiveIfAppropriateLocked(); 2669 int curState = mState; 2670 while (curState != STATE_IDLE) { 2671 stepIdleStateLocked("s:shell"); 2672 if (curState == mState) { 2673 pw.print("Unable to go deep idle; stopped at "); 2674 pw.println(stateToString(mState)); 2675 exitForceIdleLocked(); 2676 return -1; 2677 } 2678 curState = mState; 2679 } 2680 pw.println("Now forced in to deep idle mode"); 2681 } else if ("light".equals(arg)) { 2682 mForceIdle = true; 2683 becomeInactiveIfAppropriateLocked(); 2684 int curLightState = mLightState; 2685 while (curLightState != LIGHT_STATE_IDLE) { 2686 stepIdleStateLocked("s:shell"); 2687 if (curLightState == mLightState) { 2688 pw.print("Unable to go light idle; stopped at "); 2689 pw.println(lightStateToString(mLightState)); 2690 exitForceIdleLocked(); 2691 return -1; 2692 } 2693 curLightState = mLightState; 2694 } 2695 pw.println("Now forced in to light idle mode"); 2696 } else { 2697 pw.println("Unknown idle mode: " + arg); 2698 } 2699 } finally { 2700 Binder.restoreCallingIdentity(token); 2701 } 2702 } 2703 } else if ("force-inactive".equals(cmd)) { 2704 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 2705 null); 2706 synchronized (this) { 2707 long token = Binder.clearCallingIdentity(); 2708 try { 2709 mForceIdle = true; 2710 becomeInactiveIfAppropriateLocked(); 2711 pw.print("Light state: "); 2712 pw.print(lightStateToString(mLightState)); 2713 pw.print(", deep state: "); 2714 pw.println(stateToString(mState)); 2715 } finally { 2716 Binder.restoreCallingIdentity(token); 2717 } 2718 } 2719 } else if ("unforce".equals(cmd)) { 2720 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 2721 null); 2722 synchronized (this) { 2723 long token = Binder.clearCallingIdentity(); 2724 try { 2725 exitForceIdleLocked(); 2726 pw.print("Light state: "); 2727 pw.print(lightStateToString(mLightState)); 2728 pw.print(", deep state: "); 2729 pw.println(stateToString(mState)); 2730 } finally { 2731 Binder.restoreCallingIdentity(token); 2732 } 2733 } 2734 } else if ("get".equals(cmd)) { 2735 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 2736 null); 2737 synchronized (this) { 2738 String arg = shell.getNextArg(); 2739 if (arg != null) { 2740 long token = Binder.clearCallingIdentity(); 2741 try { 2742 switch (arg) { 2743 case "light": pw.println(lightStateToString(mLightState)); break; 2744 case "deep": pw.println(stateToString(mState)); break; 2745 case "force": pw.println(mForceIdle); break; 2746 case "screen": pw.println(mScreenOn); break; 2747 case "charging": pw.println(mCharging); break; 2748 case "network": pw.println(mNetworkConnected); break; 2749 default: pw.println("Unknown get option: " + arg); break; 2750 } 2751 } finally { 2752 Binder.restoreCallingIdentity(token); 2753 } 2754 } else { 2755 pw.println("Argument required"); 2756 } 2757 } 2758 } else if ("disable".equals(cmd)) { 2759 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 2760 null); 2761 synchronized (this) { 2762 long token = Binder.clearCallingIdentity(); 2763 String arg = shell.getNextArg(); 2764 try { 2765 boolean becomeActive = false; 2766 boolean valid = false; 2767 if (arg == null || "deep".equals(arg) || "all".equals(arg)) { 2768 valid = true; 2769 if (mDeepEnabled) { 2770 mDeepEnabled = false; 2771 becomeActive = true; 2772 pw.println("Deep idle mode disabled"); 2773 } 2774 } 2775 if (arg == null || "light".equals(arg) || "all".equals(arg)) { 2776 valid = true; 2777 if (mLightEnabled) { 2778 mLightEnabled = false; 2779 becomeActive = true; 2780 pw.println("Light idle mode disabled"); 2781 } 2782 } 2783 if (becomeActive) { 2784 becomeActiveLocked((arg == null ? "all" : arg) + "-disabled", 2785 Process.myUid()); 2786 } 2787 if (!valid) { 2788 pw.println("Unknown idle mode: " + arg); 2789 } 2790 } finally { 2791 Binder.restoreCallingIdentity(token); 2792 } 2793 } 2794 } else if ("enable".equals(cmd)) { 2795 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 2796 null); 2797 synchronized (this) { 2798 long token = Binder.clearCallingIdentity(); 2799 String arg = shell.getNextArg(); 2800 try { 2801 boolean becomeInactive = false; 2802 boolean valid = false; 2803 if (arg == null || "deep".equals(arg) || "all".equals(arg)) { 2804 valid = true; 2805 if (!mDeepEnabled) { 2806 mDeepEnabled = true; 2807 becomeInactive = true; 2808 pw.println("Deep idle mode enabled"); 2809 } 2810 } 2811 if (arg == null || "light".equals(arg) || "all".equals(arg)) { 2812 valid = true; 2813 if (!mLightEnabled) { 2814 mLightEnabled = true; 2815 becomeInactive = true; 2816 pw.println("Light idle mode enable"); 2817 } 2818 } 2819 if (becomeInactive) { 2820 becomeInactiveIfAppropriateLocked(); 2821 } 2822 if (!valid) { 2823 pw.println("Unknown idle mode: " + arg); 2824 } 2825 } finally { 2826 Binder.restoreCallingIdentity(token); 2827 } 2828 } 2829 } else if ("enabled".equals(cmd)) { 2830 synchronized (this) { 2831 String arg = shell.getNextArg(); 2832 if (arg == null || "all".equals(arg)) { 2833 pw.println(mDeepEnabled && mLightEnabled ? "1" : 0); 2834 } else if ("deep".equals(arg)) { 2835 pw.println(mDeepEnabled ? "1" : 0); 2836 } else if ("light".equals(arg)) { 2837 pw.println(mLightEnabled ? "1" : 0); 2838 } else { 2839 pw.println("Unknown idle mode: " + arg); 2840 } 2841 } 2842 } else if ("whitelist".equals(cmd)) { 2843 String arg = shell.getNextArg(); 2844 if (arg != null) { 2845 getContext().enforceCallingOrSelfPermission( 2846 android.Manifest.permission.DEVICE_POWER, null); 2847 long token = Binder.clearCallingIdentity(); 2848 try { 2849 do { 2850 if (arg.length() < 1 || (arg.charAt(0) != '-' 2851 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) { 2852 pw.println("Package must be prefixed with +, -, or =: " + arg); 2853 return -1; 2854 } 2855 char op = arg.charAt(0); 2856 String pkg = arg.substring(1); 2857 if (op == '+') { 2858 if (addPowerSaveWhitelistAppInternal(pkg)) { 2859 pw.println("Added: " + pkg); 2860 } else { 2861 pw.println("Unknown package: " + pkg); 2862 } 2863 } else if (op == '-') { 2864 if (removePowerSaveWhitelistAppInternal(pkg)) { 2865 pw.println("Removed: " + pkg); 2866 } 2867 } else { 2868 pw.println(getPowerSaveWhitelistAppInternal(pkg)); 2869 } 2870 } while ((arg=shell.getNextArg()) != null); 2871 } finally { 2872 Binder.restoreCallingIdentity(token); 2873 } 2874 } else { 2875 synchronized (this) { 2876 for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) { 2877 pw.print("system-excidle,"); 2878 pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j)); 2879 pw.print(","); 2880 pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j)); 2881 } 2882 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) { 2883 pw.print("system,"); 2884 pw.print(mPowerSaveWhitelistApps.keyAt(j)); 2885 pw.print(","); 2886 pw.println(mPowerSaveWhitelistApps.valueAt(j)); 2887 } 2888 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) { 2889 pw.print("user,"); 2890 pw.print(mPowerSaveWhitelistUserApps.keyAt(j)); 2891 pw.print(","); 2892 pw.println(mPowerSaveWhitelistUserApps.valueAt(j)); 2893 } 2894 } 2895 } 2896 } else if ("tempwhitelist".equals(cmd)) { 2897 long duration = 10000; 2898 String opt; 2899 while ((opt=shell.getNextOption()) != null) { 2900 if ("-u".equals(opt)) { 2901 opt = shell.getNextArg(); 2902 if (opt == null) { 2903 pw.println("-u requires a user number"); 2904 return -1; 2905 } 2906 shell.userId = Integer.parseInt(opt); 2907 } else if ("-d".equals(opt)) { 2908 opt = shell.getNextArg(); 2909 if (opt == null) { 2910 pw.println("-d requires a duration"); 2911 return -1; 2912 } 2913 duration = Long.parseLong(opt); 2914 } 2915 } 2916 String arg = shell.getNextArg(); 2917 if (arg != null) { 2918 try { 2919 addPowerSaveTempWhitelistAppChecked(arg, duration, shell.userId, "shell"); 2920 } catch (Exception e) { 2921 pw.println("Failed: " + e); 2922 return -1; 2923 } 2924 } else { 2925 dumpTempWhitelistSchedule(pw, false); 2926 } 2927 } else if ("except-idle-whitelist".equals(cmd)) { 2928 getContext().enforceCallingOrSelfPermission( 2929 android.Manifest.permission.DEVICE_POWER, null); 2930 final long token = Binder.clearCallingIdentity(); 2931 try { 2932 String arg = shell.getNextArg(); 2933 if (arg == null) { 2934 pw.println("No arguments given"); 2935 return -1; 2936 } else if ("reset".equals(arg)) { 2937 resetPowerSaveWhitelistExceptIdleInternal(); 2938 } else { 2939 do { 2940 if (arg.length() < 1 || (arg.charAt(0) != '-' 2941 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) { 2942 pw.println("Package must be prefixed with +, -, or =: " + arg); 2943 return -1; 2944 } 2945 char op = arg.charAt(0); 2946 String pkg = arg.substring(1); 2947 if (op == '+') { 2948 if (addPowerSaveWhitelistExceptIdleInternal(pkg)) { 2949 pw.println("Added: " + pkg); 2950 } else { 2951 pw.println("Unknown package: " + pkg); 2952 } 2953 } else if (op == '=') { 2954 pw.println(getPowerSaveWhitelistExceptIdleInternal(pkg)); 2955 } else { 2956 pw.println("Unknown argument: " + arg); 2957 return -1; 2958 } 2959 } while ((arg = shell.getNextArg()) != null); 2960 } 2961 } finally { 2962 Binder.restoreCallingIdentity(token); 2963 } 2964 } else { 2965 return shell.handleDefaultCommands(cmd); 2966 } 2967 return 0; 2968 } 2969 dump(FileDescriptor fd, PrintWriter pw, String[] args)2970 void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2971 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; 2972 2973 if (args != null) { 2974 int userId = UserHandle.USER_SYSTEM; 2975 for (int i=0; i<args.length; i++) { 2976 String arg = args[i]; 2977 if ("-h".equals(arg)) { 2978 dumpHelp(pw); 2979 return; 2980 } else if ("-u".equals(arg)) { 2981 i++; 2982 if (i < args.length) { 2983 arg = args[i]; 2984 userId = Integer.parseInt(arg); 2985 } 2986 } else if ("-a".equals(arg)) { 2987 // Ignore, we always dump all. 2988 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 2989 pw.println("Unknown option: " + arg); 2990 return; 2991 } else { 2992 Shell shell = new Shell(); 2993 shell.userId = userId; 2994 String[] newArgs = new String[args.length-i]; 2995 System.arraycopy(args, i, newArgs, 0, args.length-i); 2996 shell.exec(mBinderService, null, fd, null, newArgs, null, 2997 new ResultReceiver(null)); 2998 return; 2999 } 3000 } 3001 } 3002 3003 synchronized (this) { 3004 mConstants.dump(pw); 3005 3006 if (mEventCmds[0] != EVENT_NULL) { 3007 pw.println(" Idling history:"); 3008 long now = SystemClock.elapsedRealtime(); 3009 for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) { 3010 int cmd = mEventCmds[i]; 3011 if (cmd == EVENT_NULL) { 3012 continue; 3013 } 3014 String label; 3015 switch (mEventCmds[i]) { 3016 case EVENT_NORMAL: label = " normal"; break; 3017 case EVENT_LIGHT_IDLE: label = " light-idle"; break; 3018 case EVENT_LIGHT_MAINTENANCE: label = "light-maint"; break; 3019 case EVENT_DEEP_IDLE: label = " deep-idle"; break; 3020 case EVENT_DEEP_MAINTENANCE: label = " deep-maint"; break; 3021 default: label = " ??"; break; 3022 } 3023 pw.print(" "); 3024 pw.print(label); 3025 pw.print(": "); 3026 TimeUtils.formatDuration(mEventTimes[i], now, pw);; 3027 pw.println(); 3028 } 3029 } 3030 3031 int size = mPowerSaveWhitelistAppsExceptIdle.size(); 3032 if (size > 0) { 3033 pw.println(" Whitelist (except idle) system apps:"); 3034 for (int i = 0; i < size; i++) { 3035 pw.print(" "); 3036 pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i)); 3037 } 3038 } 3039 size = mPowerSaveWhitelistApps.size(); 3040 if (size > 0) { 3041 pw.println(" Whitelist system apps:"); 3042 for (int i = 0; i < size; i++) { 3043 pw.print(" "); 3044 pw.println(mPowerSaveWhitelistApps.keyAt(i)); 3045 } 3046 } 3047 size = mPowerSaveWhitelistUserApps.size(); 3048 if (size > 0) { 3049 pw.println(" Whitelist user apps:"); 3050 for (int i = 0; i < size; i++) { 3051 pw.print(" "); 3052 pw.println(mPowerSaveWhitelistUserApps.keyAt(i)); 3053 } 3054 } 3055 size = mPowerSaveWhitelistExceptIdleAppIds.size(); 3056 if (size > 0) { 3057 pw.println(" Whitelist (except idle) all app ids:"); 3058 for (int i = 0; i < size; i++) { 3059 pw.print(" "); 3060 pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i)); 3061 pw.println(); 3062 } 3063 } 3064 size = mPowerSaveWhitelistUserAppIds.size(); 3065 if (size > 0) { 3066 pw.println(" Whitelist user app ids:"); 3067 for (int i = 0; i < size; i++) { 3068 pw.print(" "); 3069 pw.print(mPowerSaveWhitelistUserAppIds.keyAt(i)); 3070 pw.println(); 3071 } 3072 } 3073 size = mPowerSaveWhitelistAllAppIds.size(); 3074 if (size > 0) { 3075 pw.println(" Whitelist all app ids:"); 3076 for (int i = 0; i < size; i++) { 3077 pw.print(" "); 3078 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i)); 3079 pw.println(); 3080 } 3081 } 3082 dumpTempWhitelistSchedule(pw, true); 3083 3084 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0; 3085 if (size > 0) { 3086 pw.println(" Temp whitelist app ids:"); 3087 for (int i = 0; i < size; i++) { 3088 pw.print(" "); 3089 pw.print(mTempWhitelistAppIdArray[i]); 3090 pw.println(); 3091 } 3092 } 3093 3094 pw.print(" mLightEnabled="); pw.print(mLightEnabled); 3095 pw.print(" mDeepEnabled="); pw.println(mDeepEnabled); 3096 pw.print(" mForceIdle="); pw.println(mForceIdle); 3097 pw.print(" mMotionSensor="); pw.println(mMotionSensor); 3098 pw.print(" mCurDisplay="); pw.println(mCurDisplay); 3099 pw.print(" mScreenOn="); pw.println(mScreenOn); 3100 pw.print(" mNetworkConnected="); pw.println(mNetworkConnected); 3101 pw.print(" mCharging="); pw.println(mCharging); 3102 pw.print(" mMotionActive="); pw.println(mMotionListener.active); 3103 pw.print(" mNotMoving="); pw.println(mNotMoving); 3104 pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps="); 3105 pw.print(mHasGps); pw.print(" mHasNetwork="); 3106 pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated); 3107 if (mLastGenericLocation != null) { 3108 pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation); 3109 } 3110 if (mLastGpsLocation != null) { 3111 pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation); 3112 } 3113 pw.print(" mState="); pw.print(stateToString(mState)); 3114 pw.print(" mLightState="); 3115 pw.println(lightStateToString(mLightState)); 3116 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw); 3117 pw.println(); 3118 if (mActiveIdleOpCount != 0) { 3119 pw.print(" mActiveIdleOpCount="); pw.println(mActiveIdleOpCount); 3120 } 3121 if (mNextAlarmTime != 0) { 3122 pw.print(" mNextAlarmTime="); 3123 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); 3124 pw.println(); 3125 } 3126 if (mNextIdlePendingDelay != 0) { 3127 pw.print(" mNextIdlePendingDelay="); 3128 TimeUtils.formatDuration(mNextIdlePendingDelay, pw); 3129 pw.println(); 3130 } 3131 if (mNextIdleDelay != 0) { 3132 pw.print(" mNextIdleDelay="); 3133 TimeUtils.formatDuration(mNextIdleDelay, pw); 3134 pw.println(); 3135 } 3136 if (mNextLightIdleDelay != 0) { 3137 pw.print(" mNextIdleDelay="); 3138 TimeUtils.formatDuration(mNextLightIdleDelay, pw); 3139 pw.println(); 3140 } 3141 if (mNextLightAlarmTime != 0) { 3142 pw.print(" mNextLightAlarmTime="); 3143 TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw); 3144 pw.println(); 3145 } 3146 if (mCurIdleBudget != 0) { 3147 pw.print(" mCurIdleBudget="); 3148 TimeUtils.formatDuration(mCurIdleBudget, pw); 3149 pw.println(); 3150 } 3151 if (mMaintenanceStartTime != 0) { 3152 pw.print(" mMaintenanceStartTime="); 3153 TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw); 3154 pw.println(); 3155 } 3156 if (mJobsActive) { 3157 pw.print(" mJobsActive="); pw.println(mJobsActive); 3158 } 3159 if (mAlarmsActive) { 3160 pw.print(" mAlarmsActive="); pw.println(mAlarmsActive); 3161 } 3162 } 3163 } 3164 dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle)3165 void dumpTempWhitelistSchedule(PrintWriter pw, boolean printTitle) { 3166 final int size = mTempWhitelistAppIdEndTimes.size(); 3167 if (size > 0) { 3168 String prefix = ""; 3169 if (printTitle) { 3170 pw.println(" Temp whitelist schedule:"); 3171 prefix = " "; 3172 } 3173 final long timeNow = SystemClock.elapsedRealtime(); 3174 for (int i = 0; i < size; i++) { 3175 pw.print(prefix); 3176 pw.print("UID="); 3177 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i)); 3178 pw.print(": "); 3179 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i); 3180 TimeUtils.formatDuration(entry.first.value, timeNow, pw); 3181 pw.print(" - "); 3182 pw.println(entry.second); 3183 } 3184 } 3185 } 3186 } 3187