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