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