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.app.PendingIntent; 23 import android.content.BroadcastReceiver; 24 import android.content.ContentResolver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.content.pm.ApplicationInfo; 29 import android.content.pm.PackageManager; 30 import android.content.pm.PackageManager.NameNotFoundException; 31 import android.database.ContentObserver; 32 import android.hardware.Sensor; 33 import android.hardware.SensorManager; 34 import android.hardware.TriggerEvent; 35 import android.hardware.TriggerEventListener; 36 import android.hardware.display.DisplayManager; 37 import android.location.LocationRequest; 38 import android.location.Location; 39 import android.location.LocationListener; 40 import android.location.LocationManager; 41 import android.net.INetworkPolicyManager; 42 import android.net.Uri; 43 import android.os.BatteryStats; 44 import android.os.Binder; 45 import android.os.Bundle; 46 import android.os.Environment; 47 import android.os.FileUtils; 48 import android.os.Handler; 49 import android.os.IDeviceIdleController; 50 import android.os.Looper; 51 import android.os.Message; 52 import android.os.PowerManager; 53 import android.os.PowerManagerInternal; 54 import android.os.Process; 55 import android.os.RemoteException; 56 import android.os.ServiceManager; 57 import android.os.SystemClock; 58 import android.os.UserHandle; 59 import android.provider.Settings; 60 import android.util.ArrayMap; 61 import android.util.ArraySet; 62 import android.util.KeyValueListParser; 63 import android.util.MutableLong; 64 import android.util.Pair; 65 import android.util.Slog; 66 import android.util.SparseArray; 67 import android.util.SparseBooleanArray; 68 import android.util.TimeUtils; 69 import android.util.Xml; 70 import android.view.Display; 71 72 import com.android.internal.app.IBatteryStats; 73 import com.android.internal.os.AtomicFile; 74 import com.android.internal.os.BackgroundThread; 75 import com.android.internal.util.FastXmlSerializer; 76 import com.android.internal.util.XmlUtils; 77 import com.android.server.am.BatteryStatsService; 78 79 import org.xmlpull.v1.XmlPullParser; 80 import org.xmlpull.v1.XmlPullParserException; 81 import org.xmlpull.v1.XmlSerializer; 82 83 import java.io.ByteArrayOutputStream; 84 import java.io.File; 85 import java.io.FileDescriptor; 86 import java.io.FileInputStream; 87 import java.io.FileNotFoundException; 88 import java.io.FileOutputStream; 89 import java.io.IOException; 90 import java.io.PrintWriter; 91 import java.nio.charset.StandardCharsets; 92 import java.util.Arrays; 93 94 /** 95 * Keeps track of device idleness and drives low power mode based on that. 96 */ 97 public class DeviceIdleController extends SystemService 98 implements AnyMotionDetector.DeviceIdleCallback { 99 private static final String TAG = "DeviceIdleController"; 100 101 private static final boolean DEBUG = false; 102 103 private static final boolean COMPRESS_TIME = false; 104 105 private static final String ACTION_STEP_IDLE_STATE = 106 "com.android.server.device_idle.STEP_IDLE_STATE"; 107 108 private AlarmManager mAlarmManager; 109 private IBatteryStats mBatteryStats; 110 private PowerManagerInternal mLocalPowerManager; 111 private INetworkPolicyManager mNetworkPolicyManager; 112 private DisplayManager mDisplayManager; 113 private SensorManager mSensorManager; 114 private Sensor mSigMotionSensor; 115 private LocationManager mLocationManager; 116 private LocationRequest mLocationRequest; 117 private PendingIntent mSensingAlarmIntent; 118 private PendingIntent mAlarmIntent; 119 private Intent mIdleIntent; 120 private Display mCurDisplay; 121 private AnyMotionDetector mAnyMotionDetector; 122 private boolean mEnabled; 123 private boolean mForceIdle; 124 private boolean mScreenOn; 125 private boolean mCharging; 126 private boolean mSigMotionActive; 127 private boolean mSensing; 128 private boolean mNotMoving; 129 private boolean mLocating; 130 private boolean mLocated; 131 private boolean mHaveGps; 132 private Location mLastGenericLocation; 133 private Location mLastGpsLocation; 134 135 /** Device is currently active. */ 136 private static final int STATE_ACTIVE = 0; 137 /** Device is inactve (screen off, no motion) and we are waiting to for idle. */ 138 private static final int STATE_INACTIVE = 1; 139 /** Device is past the initial inactive period, and waiting for the next idle period. */ 140 private static final int STATE_IDLE_PENDING = 2; 141 /** Device is currently sensing motion. */ 142 private static final int STATE_SENSING = 3; 143 /** Device is currently finding location (and may still be sensing). */ 144 private static final int STATE_LOCATING = 4; 145 /** Device is in the idle state, trying to stay asleep as much as possible. */ 146 private static final int STATE_IDLE = 5; 147 /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */ 148 private static final int STATE_IDLE_MAINTENANCE = 6; 149 private static String stateToString(int state) { 150 switch (state) { 151 case STATE_ACTIVE: return "ACTIVE"; 152 case STATE_INACTIVE: return "INACTIVE"; 153 case STATE_IDLE_PENDING: return "IDLE_PENDING"; 154 case STATE_SENSING: return "SENSING"; 155 case STATE_LOCATING: return "LOCATING"; 156 case STATE_IDLE: return "IDLE"; 157 case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE"; 158 default: return Integer.toString(state); 159 } 160 } 161 162 private int mState; 163 164 private long mInactiveTimeout; 165 private long mNextAlarmTime; 166 private long mNextIdlePendingDelay; 167 private long mNextIdleDelay; 168 169 public final AtomicFile mConfigFile; 170 171 /** 172 * Package names the system has white-listed to opt out of power save restrictions, 173 * except for device idle mode. 174 */ 175 private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>(); 176 177 /** 178 * Package names the system has white-listed to opt out of power save restrictions for 179 * all modes. 180 */ 181 private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>(); 182 183 /** 184 * Package names the user has white-listed to opt out of power save restrictions. 185 */ 186 private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>(); 187 188 /** 189 * App IDs of built-in system apps that have been white-listed except for idle modes. 190 */ 191 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle 192 = new SparseBooleanArray(); 193 194 /** 195 * App IDs of built-in system apps that have been white-listed. 196 */ 197 private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray(); 198 199 /** 200 * App IDs that have been white-listed to opt out of power save restrictions, except 201 * for device idle modes. 202 */ 203 private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray(); 204 205 /** 206 * Current app IDs that are in the complete power save white list, but shouldn't be 207 * excluded from idle modes. This array can be shared with others because it will not be 208 * modified once set. 209 */ 210 private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0]; 211 212 /** 213 * App IDs that have been white-listed to opt out of power save restrictions. 214 */ 215 private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray(); 216 217 /** 218 * Current app IDs that are in the complete power save white list. This array can 219 * be shared with others because it will not be modified once set. 220 */ 221 private int[] mPowerSaveWhitelistAllAppIdArray = new int[0]; 222 223 /** 224 * List of end times for UIDs that are temporarily marked as being allowed to access 225 * the network and acquire wakelocks. Times are in milliseconds. 226 */ 227 private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes 228 = new SparseArray<>(); 229 230 /** 231 * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed. 232 */ 233 Runnable mNetworkPolicyTempWhitelistCallback; 234 235 /** 236 * Current app IDs of temporarily whitelist apps for high-priority messages. 237 */ 238 private int[] mTempWhitelistAppIdArray = new int[0]; 239 240 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 241 @Override public void onReceive(Context context, Intent intent) { 242 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { 243 int plugged = intent.getIntExtra("plugged", 0); 244 updateChargingLocked(plugged != 0); 245 } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { 246 synchronized (DeviceIdleController.this) { 247 stepIdleStateLocked(); 248 } 249 } 250 } 251 }; 252 253 private final DisplayManager.DisplayListener mDisplayListener 254 = new DisplayManager.DisplayListener() { 255 @Override public void onDisplayAdded(int displayId) { 256 } 257 258 @Override public void onDisplayRemoved(int displayId) { 259 } 260 261 @Override public void onDisplayChanged(int displayId) { 262 if (displayId == Display.DEFAULT_DISPLAY) { 263 synchronized (DeviceIdleController.this) { 264 updateDisplayLocked(); 265 } 266 } 267 } 268 }; 269 270 private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { 271 @Override public void onTrigger(TriggerEvent event) { 272 synchronized (DeviceIdleController.this) { 273 significantMotionLocked(); 274 } 275 } 276 }; 277 278 private final LocationListener mGenericLocationListener = new LocationListener() { 279 @Override 280 public void onLocationChanged(Location location) { 281 synchronized (DeviceIdleController.this) { 282 receivedGenericLocationLocked(location); 283 } 284 } 285 286 @Override 287 public void onStatusChanged(String provider, int status, Bundle extras) { 288 } 289 290 @Override 291 public void onProviderEnabled(String provider) { 292 } 293 294 @Override 295 public void onProviderDisabled(String provider) { 296 } 297 }; 298 299 private final LocationListener mGpsLocationListener = new LocationListener() { 300 @Override 301 public void onLocationChanged(Location location) { 302 synchronized (DeviceIdleController.this) { 303 receivedGpsLocationLocked(location); 304 } 305 } 306 307 @Override 308 public void onStatusChanged(String provider, int status, Bundle extras) { 309 } 310 311 @Override 312 public void onProviderEnabled(String provider) { 313 } 314 315 @Override 316 public void onProviderDisabled(String provider) { 317 } 318 }; 319 320 /** 321 * All times are in milliseconds. These constants are kept synchronized with the system 322 * global Settings. Any access to this class or its fields should be done while 323 * holding the DeviceIdleController lock. 324 */ 325 private final class Constants extends ContentObserver { 326 // Key names stored in the settings value. 327 private static final String KEY_INACTIVE_TIMEOUT = "inactive_to"; 328 private static final String KEY_SENSING_TIMEOUT = "sensing_to"; 329 private static final String KEY_LOCATING_TIMEOUT = "locating_to"; 330 private static final String KEY_LOCATION_ACCURACY = "location_accuracy"; 331 private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to"; 332 private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to"; 333 private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to"; 334 private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to"; 335 private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor"; 336 private static final String KEY_IDLE_TIMEOUT = "idle_to"; 337 private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to"; 338 private static final String KEY_IDLE_FACTOR = "idle_factor"; 339 private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm"; 340 private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION = 341 "max_temp_app_whitelist_duration"; 342 private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION = 343 "mms_temp_app_whitelist_duration"; 344 private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION = 345 "sms_temp_app_whitelist_duration"; 346 347 /** 348 * This is the time, after becoming inactive, at which we start looking at the 349 * motion sensor to determine if the device is being left alone. We don't do this 350 * immediately after going inactive just because we don't want to be continually running 351 * the significant motion sensor whenever the screen is off. 352 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 353 * @see #KEY_INACTIVE_TIMEOUT 354 */ 355 public long INACTIVE_TIMEOUT; 356 357 /** 358 * If we don't receive a callback from AnyMotion in this amount of time + 359 * {@link #LOCATING_TIMEOUT}, we will change from 360 * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING 361 * will be ignored. 362 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 363 * @see #KEY_SENSING_TIMEOUT 364 */ 365 public long SENSING_TIMEOUT; 366 367 /** 368 * This is how long we will wait to try to get a good location fix before going in to 369 * idle mode. 370 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 371 * @see #KEY_LOCATING_TIMEOUT 372 */ 373 public long LOCATING_TIMEOUT; 374 375 /** 376 * The desired maximum accuracy (in meters) we consider the location to be good enough to go 377 * on to idle. We will be trying to get an accuracy fix at least this good or until 378 * {@link #LOCATING_TIMEOUT} expires. 379 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 380 * @see #KEY_LOCATION_ACCURACY 381 */ 382 public float LOCATION_ACCURACY; 383 384 /** 385 * This is the time, after seeing motion, that we wait after becoming inactive from 386 * that until we start looking for motion again. 387 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 388 * @see #KEY_MOTION_INACTIVE_TIMEOUT 389 */ 390 public long MOTION_INACTIVE_TIMEOUT; 391 392 /** 393 * This is the time, after the inactive timeout elapses, that we will wait looking 394 * for significant motion until we truly consider the device to be idle. 395 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 396 * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT 397 */ 398 public long IDLE_AFTER_INACTIVE_TIMEOUT; 399 400 /** 401 * This is the initial time, after being idle, that we will allow ourself to be back 402 * in the IDLE_PENDING state allowing the system to run normally until we return to idle. 403 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 404 * @see #KEY_IDLE_PENDING_TIMEOUT 405 */ 406 public long IDLE_PENDING_TIMEOUT; 407 408 /** 409 * Maximum pending idle timeout (time spent running) we will be allowed to use. 410 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 411 * @see #KEY_MAX_IDLE_PENDING_TIMEOUT 412 */ 413 public long MAX_IDLE_PENDING_TIMEOUT; 414 415 /** 416 * Scaling factor to apply to current pending idle timeout each time we cycle through 417 * that state. 418 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 419 * @see #KEY_IDLE_PENDING_FACTOR 420 */ 421 public float IDLE_PENDING_FACTOR; 422 423 /** 424 * This is the initial time that we want to sit in the idle state before waking up 425 * again to return to pending idle and allowing normal work to run. 426 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 427 * @see #KEY_IDLE_TIMEOUT 428 */ 429 public long IDLE_TIMEOUT; 430 431 /** 432 * Maximum idle duration we will be allowed to use. 433 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 434 * @see #KEY_MAX_IDLE_TIMEOUT 435 */ 436 public long MAX_IDLE_TIMEOUT; 437 438 /** 439 * Scaling factor to apply to current idle timeout each time we cycle through that state. 440 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 441 * @see #KEY_IDLE_FACTOR 442 */ 443 public float IDLE_FACTOR; 444 445 /** 446 * This is the minimum time we will allow until the next upcoming alarm for us to 447 * actually go in to idle mode. 448 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 449 * @see #KEY_MIN_TIME_TO_ALARM 450 */ 451 public long MIN_TIME_TO_ALARM; 452 453 /** 454 * Max amount of time to temporarily whitelist an app when it receives a high priority 455 * tickle. 456 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 457 * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION 458 */ 459 public long MAX_TEMP_APP_WHITELIST_DURATION; 460 461 /** 462 * Amount of time we would like to whitelist an app that is receiving an MMS. 463 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 464 * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION 465 */ 466 public long MMS_TEMP_APP_WHITELIST_DURATION; 467 468 /** 469 * Amount of time we would like to whitelist an app that is receiving an SMS. 470 * @see Settings.Global#DEVICE_IDLE_CONSTANTS 471 * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION 472 */ 473 public long SMS_TEMP_APP_WHITELIST_DURATION; 474 475 private final ContentResolver mResolver; 476 private final KeyValueListParser mParser = new KeyValueListParser(','); 477 478 public Constants(Handler handler, ContentResolver resolver) { 479 super(handler); 480 mResolver = resolver; 481 mResolver.registerContentObserver( 482 Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), false, this); 483 updateConstants(); 484 } 485 486 @Override 487 public void onChange(boolean selfChange, Uri uri) { 488 updateConstants(); 489 } 490 491 private void updateConstants() { 492 synchronized (DeviceIdleController.this) { 493 try { 494 mParser.setString(Settings.Global.getString(mResolver, 495 Settings.Global.DEVICE_IDLE_CONSTANTS)); 496 } catch (IllegalArgumentException e) { 497 // Failed to parse the settings string, log this and move on 498 // with defaults. 499 Slog.e(TAG, "Bad device idle settings", e); 500 } 501 502 INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT, 503 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L); 504 SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT, 505 !DEBUG ? 4 * 60 * 1000L : 60 * 1000L); 506 LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT, 507 !DEBUG ? 30 * 1000L : 15 * 1000L); 508 LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20); 509 MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT, 510 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L); 511 IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT, 512 !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L); 513 IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT, 514 !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L); 515 MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT, 516 !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L); 517 IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR, 518 2f); 519 IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT, 520 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L); 521 MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT, 522 !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L); 523 IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR, 524 2f); 525 MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM, 526 !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L); 527 MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong( 528 KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L); 529 MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong( 530 KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L); 531 SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong( 532 KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L); 533 } 534 } 535 536 void dump(PrintWriter pw) { 537 pw.println(" Settings:"); 538 539 pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("="); 540 TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw); 541 pw.println(); 542 543 pw.print(" "); pw.print(KEY_SENSING_TIMEOUT); pw.print("="); 544 TimeUtils.formatDuration(SENSING_TIMEOUT, pw); 545 pw.println(); 546 547 pw.print(" "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("="); 548 TimeUtils.formatDuration(LOCATING_TIMEOUT, pw); 549 pw.println(); 550 551 pw.print(" "); pw.print(KEY_LOCATION_ACCURACY); pw.print("="); 552 pw.print(LOCATION_ACCURACY); pw.print("m"); 553 pw.println(); 554 555 pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("="); 556 TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw); 557 pw.println(); 558 559 pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("="); 560 TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw); 561 pw.println(); 562 563 pw.print(" "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("="); 564 TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw); 565 pw.println(); 566 567 pw.print(" "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("="); 568 TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw); 569 pw.println(); 570 571 pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("="); 572 pw.println(IDLE_PENDING_FACTOR); 573 574 pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("="); 575 TimeUtils.formatDuration(IDLE_TIMEOUT, pw); 576 pw.println(); 577 578 pw.print(" "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("="); 579 TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw); 580 pw.println(); 581 582 pw.print(" "); pw.print(KEY_IDLE_FACTOR); pw.print("="); 583 pw.println(IDLE_FACTOR); 584 585 pw.print(" "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("="); 586 TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw); 587 pw.println(); 588 589 pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("="); 590 TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw); 591 pw.println(); 592 593 pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("="); 594 TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw); 595 pw.println(); 596 597 pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("="); 598 TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw); 599 pw.println(); 600 } 601 } 602 603 private Constants mConstants; 604 605 @Override 606 public void onAnyMotionResult(int result) { 607 if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")"); 608 if (result == AnyMotionDetector.RESULT_MOVED) { 609 if (DEBUG) Slog.d(TAG, "RESULT_MOVED received."); 610 synchronized (this) { 611 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion"); 612 } 613 } else if (result == AnyMotionDetector.RESULT_STATIONARY) { 614 if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received."); 615 if (mState == STATE_SENSING) { 616 // If we are currently sensing, it is time to move to locating. 617 synchronized (this) { 618 mNotMoving = true; 619 stepIdleStateLocked(); 620 } 621 } else if (mState == STATE_LOCATING) { 622 // If we are currently locating, note that we are not moving and step 623 // if we have located the position. 624 synchronized (this) { 625 mNotMoving = true; 626 if (mLocated) { 627 stepIdleStateLocked(); 628 } 629 } 630 } 631 } 632 } 633 634 static final int MSG_WRITE_CONFIG = 1; 635 static final int MSG_REPORT_IDLE_ON = 2; 636 static final int MSG_REPORT_IDLE_OFF = 3; 637 static final int MSG_REPORT_ACTIVE = 4; 638 static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5; 639 640 final class MyHandler extends Handler { 641 MyHandler(Looper looper) { 642 super(looper); 643 } 644 645 @Override public void handleMessage(Message msg) { 646 if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")"); 647 switch (msg.what) { 648 case MSG_WRITE_CONFIG: { 649 handleWriteConfigFile(); 650 } break; 651 case MSG_REPORT_IDLE_ON: { 652 EventLogTags.writeDeviceIdleOnStart(); 653 mLocalPowerManager.setDeviceIdleMode(true); 654 try { 655 mNetworkPolicyManager.setDeviceIdleMode(true); 656 mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid()); 657 } catch (RemoteException e) { 658 } 659 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); 660 EventLogTags.writeDeviceIdleOnComplete(); 661 } break; 662 case MSG_REPORT_IDLE_OFF: { 663 EventLogTags.writeDeviceIdleOffStart("unknown"); 664 mLocalPowerManager.setDeviceIdleMode(false); 665 try { 666 mNetworkPolicyManager.setDeviceIdleMode(false); 667 mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid()); 668 } catch (RemoteException e) { 669 } 670 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); 671 EventLogTags.writeDeviceIdleOffComplete(); 672 } break; 673 case MSG_REPORT_ACTIVE: { 674 String activeReason = (String)msg.obj; 675 int activeUid = msg.arg1; 676 boolean needBroadcast = msg.arg2 != 0; 677 EventLogTags.writeDeviceIdleOffStart( 678 activeReason != null ? activeReason : "unknown"); 679 mLocalPowerManager.setDeviceIdleMode(false); 680 try { 681 mNetworkPolicyManager.setDeviceIdleMode(false); 682 mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid); 683 } catch (RemoteException e) { 684 } 685 if (needBroadcast) { 686 getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); 687 } 688 EventLogTags.writeDeviceIdleOffComplete(); 689 } break; 690 case MSG_TEMP_APP_WHITELIST_TIMEOUT: { 691 int uid = msg.arg1; 692 checkTempAppWhitelistTimeout(uid); 693 } break; 694 } 695 } 696 } 697 698 final MyHandler mHandler; 699 700 private final class BinderService extends IDeviceIdleController.Stub { 701 @Override public void addPowerSaveWhitelistApp(String name) { 702 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 703 null); 704 addPowerSaveWhitelistAppInternal(name); 705 } 706 707 @Override public void removePowerSaveWhitelistApp(String name) { 708 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 709 null); 710 removePowerSaveWhitelistAppInternal(name); 711 } 712 713 @Override public String[] getSystemPowerWhitelistExceptIdle() { 714 return getSystemPowerWhitelistExceptIdleInternal(); 715 } 716 717 @Override public String[] getSystemPowerWhitelist() { 718 return getSystemPowerWhitelistInternal(); 719 } 720 721 @Override public String[] getFullPowerWhitelistExceptIdle() { 722 return getFullPowerWhitelistExceptIdleInternal(); 723 } 724 725 @Override public String[] getFullPowerWhitelist() { 726 return getFullPowerWhitelistInternal(); 727 } 728 729 @Override public int[] getAppIdWhitelistExceptIdle() { 730 return getAppIdWhitelistExceptIdleInternal(); 731 } 732 733 @Override public int[] getAppIdWhitelist() { 734 return getAppIdWhitelistInternal(); 735 } 736 737 @Override public int[] getAppIdTempWhitelist() { 738 return getAppIdTempWhitelistInternal(); 739 } 740 741 @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) { 742 return isPowerSaveWhitelistExceptIdleAppInternal(name); 743 } 744 745 @Override public boolean isPowerSaveWhitelistApp(String name) { 746 return isPowerSaveWhitelistAppInternal(name); 747 } 748 749 @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration, 750 int userId, String reason) throws RemoteException { 751 getContext().enforceCallingPermission( 752 Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, 753 "No permission to change device idle whitelist"); 754 final int callingUid = Binder.getCallingUid(); 755 userId = ActivityManagerNative.getDefault().handleIncomingUser( 756 Binder.getCallingPid(), 757 callingUid, 758 userId, 759 /*allowAll=*/ false, 760 /*requireFull=*/ false, 761 "addPowerSaveTempWhitelistApp", null); 762 final long token = Binder.clearCallingIdentity(); 763 try { 764 DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid, 765 packageName, duration, userId, true, reason); 766 } finally { 767 Binder.restoreCallingIdentity(token); 768 } 769 } 770 771 @Override public long addPowerSaveTempWhitelistAppForMms(String packageName, 772 int userId, String reason) throws RemoteException { 773 long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION; 774 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason); 775 return duration; 776 } 777 778 @Override public long addPowerSaveTempWhitelistAppForSms(String packageName, 779 int userId, String reason) throws RemoteException { 780 long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION; 781 addPowerSaveTempWhitelistApp(packageName, duration, userId, reason); 782 return duration; 783 } 784 785 @Override public void exitIdle(String reason) { 786 getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, 787 null); 788 exitIdleInternal(reason); 789 } 790 791 @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 792 DeviceIdleController.this.dump(fd, pw, args); 793 } 794 } 795 796 public final class LocalService { 797 public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync, 798 String reason) { 799 addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason); 800 } 801 802 public void setNetworkPolicyTempWhitelistCallback(Runnable callback) { 803 setNetworkPolicyTempWhitelistCallbackInternal(callback); 804 } 805 } 806 807 public DeviceIdleController(Context context) { 808 super(context); 809 mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml")); 810 mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); 811 } 812 813 private static File getSystemDir() { 814 return new File(Environment.getDataDirectory(), "system"); 815 } 816 817 @Override 818 public void onStart() { 819 final PackageManager pm = getContext().getPackageManager(); 820 821 synchronized (this) { 822 mEnabled = getContext().getResources().getBoolean( 823 com.android.internal.R.bool.config_enableAutoPowerModes); 824 SystemConfig sysConfig = SystemConfig.getInstance(); 825 ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle(); 826 for (int i=0; i<allowPowerExceptIdle.size(); i++) { 827 String pkg = allowPowerExceptIdle.valueAt(i); 828 try { 829 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); 830 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { 831 int appid = UserHandle.getAppId(ai.uid); 832 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid); 833 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true); 834 } 835 } catch (PackageManager.NameNotFoundException e) { 836 } 837 } 838 ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); 839 for (int i=0; i<allowPower.size(); i++) { 840 String pkg = allowPower.valueAt(i); 841 try { 842 ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); 843 if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { 844 int appid = UserHandle.getAppId(ai.uid); 845 // These apps are on both the whitelist-except-idle as well 846 // as the full whitelist, so they apply in all cases. 847 mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid); 848 mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true); 849 mPowerSaveWhitelistApps.put(ai.packageName, appid); 850 mPowerSaveWhitelistSystemAppIds.put(appid, true); 851 } 852 } catch (PackageManager.NameNotFoundException e) { 853 } 854 } 855 856 mConstants = new Constants(mHandler, getContext().getContentResolver()); 857 858 readConfigFileLocked(); 859 updateWhitelistAppIdsLocked(); 860 861 mScreenOn = true; 862 // Start out assuming we are charging. If we aren't, we will at least get 863 // a battery update the next time the level drops. 864 mCharging = true; 865 mState = STATE_ACTIVE; 866 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT; 867 } 868 869 publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService()); 870 publishLocalService(LocalService.class, new LocalService()); 871 } 872 873 @Override 874 public void onBootPhase(int phase) { 875 if (phase == PHASE_SYSTEM_SERVICES_READY) { 876 synchronized (this) { 877 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); 878 mBatteryStats = BatteryStatsService.getService(); 879 mLocalPowerManager = getLocalService(PowerManagerInternal.class); 880 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( 881 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); 882 mDisplayManager = (DisplayManager) getContext().getSystemService( 883 Context.DISPLAY_SERVICE); 884 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); 885 mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); 886 mLocationManager = (LocationManager) getContext().getSystemService( 887 Context.LOCATION_SERVICE); 888 mLocationRequest = new LocationRequest() 889 .setQuality(LocationRequest.ACCURACY_FINE) 890 .setInterval(0) 891 .setFastestInterval(0) 892 .setNumUpdates(1); 893 mAnyMotionDetector = new AnyMotionDetector( 894 (PowerManager) getContext().getSystemService(Context.POWER_SERVICE), 895 mHandler, mSensorManager, this); 896 897 Intent intent = new Intent(ACTION_STEP_IDLE_STATE) 898 .setPackage("android") 899 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 900 mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); 901 902 Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE) 903 .setPackage("android") 904 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 905 mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0); 906 907 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 908 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY 909 | Intent.FLAG_RECEIVER_FOREGROUND); 910 911 IntentFilter filter = new IntentFilter(); 912 filter.addAction(Intent.ACTION_BATTERY_CHANGED); 913 filter.addAction(ACTION_STEP_IDLE_STATE); 914 getContext().registerReceiver(mReceiver, filter); 915 916 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); 917 918 mDisplayManager.registerDisplayListener(mDisplayListener, null); 919 updateDisplayLocked(); 920 } 921 } 922 } 923 924 public boolean addPowerSaveWhitelistAppInternal(String name) { 925 synchronized (this) { 926 try { 927 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0); 928 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) { 929 reportPowerSaveWhitelistChangedLocked(); 930 updateWhitelistAppIdsLocked(); 931 writeConfigFileLocked(); 932 } 933 return true; 934 } catch (PackageManager.NameNotFoundException e) { 935 return false; 936 } 937 } 938 } 939 940 public boolean removePowerSaveWhitelistAppInternal(String name) { 941 synchronized (this) { 942 if (mPowerSaveWhitelistUserApps.remove(name) != null) { 943 reportPowerSaveWhitelistChangedLocked(); 944 updateWhitelistAppIdsLocked(); 945 writeConfigFileLocked(); 946 return true; 947 } 948 } 949 return false; 950 } 951 952 public String[] getSystemPowerWhitelistExceptIdleInternal() { 953 synchronized (this) { 954 int size = mPowerSaveWhitelistAppsExceptIdle.size(); 955 String[] apps = new String[size]; 956 for (int i = 0; i < size; i++) { 957 apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i); 958 } 959 return apps; 960 } 961 } 962 963 public String[] getSystemPowerWhitelistInternal() { 964 synchronized (this) { 965 int size = mPowerSaveWhitelistApps.size(); 966 String[] apps = new String[size]; 967 for (int i = 0; i < size; i++) { 968 apps[i] = mPowerSaveWhitelistApps.keyAt(i); 969 } 970 return apps; 971 } 972 } 973 974 public String[] getFullPowerWhitelistExceptIdleInternal() { 975 synchronized (this) { 976 int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size(); 977 String[] apps = new String[size]; 978 int cur = 0; 979 for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) { 980 apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i); 981 cur++; 982 } 983 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) { 984 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i); 985 cur++; 986 } 987 return apps; 988 } 989 } 990 991 public String[] getFullPowerWhitelistInternal() { 992 synchronized (this) { 993 int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size(); 994 String[] apps = new String[size]; 995 int cur = 0; 996 for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) { 997 apps[cur] = mPowerSaveWhitelistApps.keyAt(i); 998 cur++; 999 } 1000 for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) { 1001 apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i); 1002 cur++; 1003 } 1004 return apps; 1005 } 1006 } 1007 1008 public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) { 1009 synchronized (this) { 1010 return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName) 1011 || mPowerSaveWhitelistUserApps.containsKey(packageName); 1012 } 1013 } 1014 1015 public boolean isPowerSaveWhitelistAppInternal(String packageName) { 1016 synchronized (this) { 1017 return mPowerSaveWhitelistApps.containsKey(packageName) 1018 || mPowerSaveWhitelistUserApps.containsKey(packageName); 1019 } 1020 } 1021 1022 public int[] getAppIdWhitelistExceptIdleInternal() { 1023 synchronized (this) { 1024 return mPowerSaveWhitelistExceptIdleAppIdArray; 1025 } 1026 } 1027 1028 public int[] getAppIdWhitelistInternal() { 1029 synchronized (this) { 1030 return mPowerSaveWhitelistAllAppIdArray; 1031 } 1032 } 1033 1034 public int[] getAppIdTempWhitelistInternal() { 1035 synchronized (this) { 1036 return mTempWhitelistAppIdArray; 1037 } 1038 } 1039 1040 /** 1041 * Adds an app to the temporary whitelist and resets the endTime for granting the 1042 * app an exemption to access network and acquire wakelocks. 1043 */ 1044 public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName, 1045 long duration, int userId, boolean sync, String reason) { 1046 try { 1047 int uid = getContext().getPackageManager().getPackageUid(packageName, userId); 1048 int appId = UserHandle.getAppId(uid); 1049 addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason); 1050 } catch (NameNotFoundException e) { 1051 } 1052 } 1053 1054 /** 1055 * Adds an app to the temporary whitelist and resets the endTime for granting the 1056 * app an exemption to access network and acquire wakelocks. 1057 */ 1058 public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId, 1059 long duration, boolean sync, String reason) { 1060 final long timeNow = SystemClock.elapsedRealtime(); 1061 Runnable networkPolicyTempWhitelistCallback = null; 1062 synchronized (this) { 1063 int callingAppId = UserHandle.getAppId(callingUid); 1064 if (callingAppId >= Process.FIRST_APPLICATION_UID) { 1065 if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) { 1066 throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid) 1067 + " is not on whitelist"); 1068 } 1069 } 1070 duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION); 1071 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId); 1072 final boolean newEntry = entry == null; 1073 // Set the new end time 1074 if (newEntry) { 1075 entry = new Pair<>(new MutableLong(0), reason); 1076 mTempWhitelistAppIdEndTimes.put(appId, entry); 1077 } 1078 entry.first.value = timeNow + duration; 1079 if (DEBUG) { 1080 Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist"); 1081 } 1082 if (newEntry) { 1083 // No pending timeout for the app id, post a delayed message 1084 try { 1085 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START, 1086 reason, appId); 1087 } catch (RemoteException e) { 1088 } 1089 postTempActiveTimeoutMessage(appId, duration); 1090 updateTempWhitelistAppIdsLocked(); 1091 if (mNetworkPolicyTempWhitelistCallback != null) { 1092 if (!sync) { 1093 mHandler.post(mNetworkPolicyTempWhitelistCallback); 1094 } else { 1095 networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback; 1096 } 1097 } 1098 reportTempWhitelistChangedLocked(); 1099 } 1100 } 1101 if (networkPolicyTempWhitelistCallback != null) { 1102 networkPolicyTempWhitelistCallback.run(); 1103 } 1104 } 1105 1106 public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) { 1107 synchronized (this) { 1108 mNetworkPolicyTempWhitelistCallback = callback; 1109 } 1110 } 1111 1112 private void postTempActiveTimeoutMessage(int uid, long delay) { 1113 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0), 1114 delay); 1115 } 1116 1117 void checkTempAppWhitelistTimeout(int uid) { 1118 final long timeNow = SystemClock.elapsedRealtime(); 1119 synchronized (this) { 1120 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid); 1121 if (entry == null) { 1122 // Nothing to do 1123 return; 1124 } 1125 if (timeNow >= entry.first.value) { 1126 mTempWhitelistAppIdEndTimes.delete(uid); 1127 if (DEBUG) { 1128 Slog.d(TAG, "Removing UID " + uid + " from temp whitelist"); 1129 } 1130 updateTempWhitelistAppIdsLocked(); 1131 if (mNetworkPolicyTempWhitelistCallback != null) { 1132 mHandler.post(mNetworkPolicyTempWhitelistCallback); 1133 } 1134 reportTempWhitelistChangedLocked(); 1135 try { 1136 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH, 1137 entry.second, uid); 1138 } catch (RemoteException e) { 1139 } 1140 } else { 1141 // Need more time 1142 postTempActiveTimeoutMessage(uid, entry.first.value - timeNow); 1143 } 1144 } 1145 } 1146 1147 public void exitIdleInternal(String reason) { 1148 synchronized (this) { 1149 becomeActiveLocked(reason, Binder.getCallingUid()); 1150 } 1151 } 1152 1153 void updateDisplayLocked() { 1154 mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); 1155 // We consider any situation where the display is showing something to be it on, 1156 // because if there is anything shown we are going to be updating it at some 1157 // frequency so can't be allowed to go into deep sleeps. 1158 boolean screenOn = mCurDisplay.getState() == Display.STATE_ON; 1159 if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn); 1160 if (!screenOn && mScreenOn) { 1161 mScreenOn = false; 1162 if (!mForceIdle) { 1163 becomeInactiveIfAppropriateLocked(); 1164 } 1165 } else if (screenOn) { 1166 mScreenOn = true; 1167 if (!mForceIdle) { 1168 becomeActiveLocked("screen", Process.myUid()); 1169 } 1170 } 1171 } 1172 1173 void updateChargingLocked(boolean charging) { 1174 if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging); 1175 if (!charging && mCharging) { 1176 mCharging = false; 1177 if (!mForceIdle) { 1178 becomeInactiveIfAppropriateLocked(); 1179 } 1180 } else if (charging) { 1181 mCharging = charging; 1182 if (!mForceIdle) { 1183 becomeActiveLocked("charging", Process.myUid()); 1184 } 1185 } 1186 } 1187 1188 void scheduleReportActiveLocked(String activeReason, int activeUid) { 1189 Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 1190 mState == STATE_IDLE ? 1 : 0, activeReason); 1191 mHandler.sendMessage(msg); 1192 } 1193 1194 void becomeActiveLocked(String activeReason, int activeUid) { 1195 if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason); 1196 if (mState != STATE_ACTIVE) { 1197 EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason); 1198 scheduleReportActiveLocked(activeReason, activeUid); 1199 mState = STATE_ACTIVE; 1200 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT; 1201 resetIdleManagementLocked(); 1202 } 1203 } 1204 1205 void becomeInactiveIfAppropriateLocked() { 1206 if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()"); 1207 if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) { 1208 // Screen has turned off; we are now going to become inactive and start 1209 // waiting to see if we will ultimately go idle. 1210 mState = STATE_INACTIVE; 1211 if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE"); 1212 resetIdleManagementLocked(); 1213 scheduleAlarmLocked(mInactiveTimeout, false); 1214 EventLogTags.writeDeviceIdle(mState, "no activity"); 1215 } 1216 } 1217 1218 void resetIdleManagementLocked() { 1219 mNextIdlePendingDelay = 0; 1220 mNextIdleDelay = 0; 1221 cancelAlarmLocked(); 1222 cancelSensingAlarmLocked(); 1223 cancelLocatingLocked(); 1224 stopMonitoringSignificantMotion(); 1225 mAnyMotionDetector.stop(); 1226 } 1227 1228 void exitForceIdleLocked() { 1229 if (mForceIdle) { 1230 mForceIdle = false; 1231 if (mScreenOn || mCharging) { 1232 becomeActiveLocked("exit-force-idle", Process.myUid()); 1233 } 1234 } 1235 } 1236 1237 void stepIdleStateLocked() { 1238 if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState); 1239 EventLogTags.writeDeviceIdleStep(); 1240 1241 final long now = SystemClock.elapsedRealtime(); 1242 if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { 1243 // Whoops, there is an upcoming alarm. We don't actually want to go idle. 1244 if (mState != STATE_ACTIVE) { 1245 becomeActiveLocked("alarm", Process.myUid()); 1246 } 1247 return; 1248 } 1249 1250 switch (mState) { 1251 case STATE_INACTIVE: 1252 // We have now been inactive long enough, it is time to start looking 1253 // for significant motion and sleep some more while doing so. 1254 startMonitoringSignificantMotion(); 1255 scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false); 1256 // Reset the upcoming idle delays. 1257 mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT; 1258 mNextIdleDelay = mConstants.IDLE_TIMEOUT; 1259 mState = STATE_IDLE_PENDING; 1260 if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING."); 1261 EventLogTags.writeDeviceIdle(mState, "step"); 1262 break; 1263 case STATE_IDLE_PENDING: 1264 mState = STATE_SENSING; 1265 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING."); 1266 EventLogTags.writeDeviceIdle(mState, "step"); 1267 scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT); 1268 cancelSensingAlarmLocked(); 1269 cancelLocatingLocked(); 1270 mAnyMotionDetector.checkForAnyMotion(); 1271 mNotMoving = false; 1272 mLocated = false; 1273 mLastGenericLocation = null; 1274 mLastGpsLocation = null; 1275 break; 1276 case STATE_SENSING: 1277 mState = STATE_LOCATING; 1278 if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING."); 1279 EventLogTags.writeDeviceIdle(mState, "step"); 1280 cancelSensingAlarmLocked(); 1281 scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT); 1282 mLocating = true; 1283 mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener, 1284 mHandler.getLooper()); 1285 if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { 1286 mHaveGps = true; 1287 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5, 1288 mGpsLocationListener, mHandler.getLooper()); 1289 } else { 1290 mHaveGps = false; 1291 } 1292 break; 1293 case STATE_LOCATING: 1294 cancelSensingAlarmLocked(); 1295 cancelLocatingLocked(); 1296 mAnyMotionDetector.stop(); 1297 case STATE_IDLE_MAINTENANCE: 1298 scheduleAlarmLocked(mNextIdleDelay, true); 1299 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay + 1300 " ms."); 1301 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR); 1302 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay); 1303 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT); 1304 mState = STATE_IDLE; 1305 EventLogTags.writeDeviceIdle(mState, "step"); 1306 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON); 1307 break; 1308 case STATE_IDLE: 1309 // We have been idling long enough, now it is time to do some work. 1310 scheduleAlarmLocked(mNextIdlePendingDelay, false); 1311 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " + 1312 "Next alarm in " + mNextIdlePendingDelay + " ms."); 1313 mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT, 1314 (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR)); 1315 mState = STATE_IDLE_MAINTENANCE; 1316 EventLogTags.writeDeviceIdle(mState, "step"); 1317 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF); 1318 break; 1319 } 1320 } 1321 1322 void significantMotionLocked() { 1323 if (DEBUG) Slog.d(TAG, "significantMotionLocked()"); 1324 // When the sensor goes off, its trigger is automatically removed. 1325 mSigMotionActive = false; 1326 handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion"); 1327 } 1328 1329 void handleMotionDetectedLocked(long timeout, String type) { 1330 // The device is not yet active, so we want to go back to the pending idle 1331 // state to wait again for no motion. Note that we only monitor for significant 1332 // motion after moving out of the inactive state, so no need to worry about that. 1333 if (mState != STATE_ACTIVE) { 1334 scheduleReportActiveLocked(type, Process.myUid()); 1335 mState = STATE_ACTIVE; 1336 mInactiveTimeout = timeout; 1337 EventLogTags.writeDeviceIdle(mState, type); 1338 becomeInactiveIfAppropriateLocked(); 1339 } 1340 } 1341 1342 void receivedGenericLocationLocked(Location location) { 1343 if (mState != STATE_LOCATING) { 1344 cancelLocatingLocked(); 1345 return; 1346 } 1347 if (DEBUG) Slog.d(TAG, "Generic location: " + location); 1348 mLastGenericLocation = new Location(location); 1349 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHaveGps) { 1350 return; 1351 } 1352 mLocated = true; 1353 if (mNotMoving) { 1354 stepIdleStateLocked(); 1355 } 1356 } 1357 1358 void receivedGpsLocationLocked(Location location) { 1359 if (mState != STATE_LOCATING) { 1360 cancelLocatingLocked(); 1361 return; 1362 } 1363 if (DEBUG) Slog.d(TAG, "GPS location: " + location); 1364 mLastGpsLocation = new Location(location); 1365 if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) { 1366 return; 1367 } 1368 mLocated = true; 1369 if (mNotMoving) { 1370 stepIdleStateLocked(); 1371 } 1372 } 1373 1374 void startMonitoringSignificantMotion() { 1375 if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()"); 1376 if (mSigMotionSensor != null && !mSigMotionActive) { 1377 mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); 1378 mSigMotionActive = true; 1379 } 1380 } 1381 1382 void stopMonitoringSignificantMotion() { 1383 if (DEBUG) Slog.d(TAG, "stopMonitoringSignificantMotion()"); 1384 if (mSigMotionActive) { 1385 mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); 1386 mSigMotionActive = false; 1387 } 1388 } 1389 1390 void cancelAlarmLocked() { 1391 if (mNextAlarmTime != 0) { 1392 mNextAlarmTime = 0; 1393 mAlarmManager.cancel(mAlarmIntent); 1394 } 1395 } 1396 1397 void cancelSensingAlarmLocked() { 1398 if (mSensing) { 1399 if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()"); 1400 mAlarmManager.cancel(mSensingAlarmIntent); 1401 mSensing = false; 1402 } 1403 } 1404 1405 void cancelLocatingLocked() { 1406 if (mLocating) { 1407 mLocationManager.removeUpdates(mGenericLocationListener); 1408 mLocationManager.removeUpdates(mGpsLocationListener); 1409 mLocating = false; 1410 } 1411 } 1412 1413 void scheduleAlarmLocked(long delay, boolean idleUntil) { 1414 if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")"); 1415 if (mSigMotionSensor == null) { 1416 // If there is no significant motion sensor on this device, then we won't schedule 1417 // alarms, because we can't determine if the device is not moving. This effectively 1418 // turns off normal exeuction of device idling, although it is still possible to 1419 // manually poke it by pretending like the alarm is going off. 1420 return; 1421 } 1422 mNextAlarmTime = SystemClock.elapsedRealtime() + delay; 1423 if (idleUntil) { 1424 mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1425 mNextAlarmTime, mAlarmIntent); 1426 } else { 1427 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1428 mNextAlarmTime, mAlarmIntent); 1429 } 1430 } 1431 1432 void scheduleSensingAlarmLocked(long delay) { 1433 if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")"); 1434 cancelSensingAlarmLocked(); 1435 mNextAlarmTime = SystemClock.elapsedRealtime() + delay; 1436 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1437 mNextAlarmTime, mSensingAlarmIntent); 1438 mSensing = true; 1439 } 1440 1441 private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps, 1442 ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) { 1443 outAppIds.clear(); 1444 for (int i=0; i<systemApps.size(); i++) { 1445 outAppIds.put(systemApps.valueAt(i), true); 1446 } 1447 for (int i=0; i<userApps.size(); i++) { 1448 outAppIds.put(userApps.valueAt(i), true); 1449 } 1450 int size = outAppIds.size(); 1451 int[] appids = new int[size]; 1452 for (int i = 0; i < size; i++) { 1453 appids[i] = outAppIds.keyAt(i); 1454 } 1455 return appids; 1456 } 1457 1458 private void updateWhitelistAppIdsLocked() { 1459 mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle, 1460 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds); 1461 mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps, 1462 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds); 1463 if (mLocalPowerManager != null) { 1464 if (DEBUG) { 1465 Slog.d(TAG, "Setting wakelock whitelist to " 1466 + Arrays.toString(mPowerSaveWhitelistAllAppIdArray)); 1467 } 1468 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); 1469 } 1470 } 1471 1472 private void updateTempWhitelistAppIdsLocked() { 1473 final int size = mTempWhitelistAppIdEndTimes.size(); 1474 if (mTempWhitelistAppIdArray.length != size) { 1475 mTempWhitelistAppIdArray = new int[size]; 1476 } 1477 for (int i = 0; i < size; i++) { 1478 mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i); 1479 } 1480 if (mLocalPowerManager != null) { 1481 if (DEBUG) { 1482 Slog.d(TAG, "Setting wakelock temp whitelist to " 1483 + Arrays.toString(mTempWhitelistAppIdArray)); 1484 } 1485 mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray); 1486 } 1487 } 1488 1489 private void reportPowerSaveWhitelistChangedLocked() { 1490 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); 1491 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 1492 getContext().sendBroadcastAsUser(intent, UserHandle.OWNER); 1493 } 1494 1495 private void reportTempWhitelistChangedLocked() { 1496 Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED); 1497 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 1498 getContext().sendBroadcastAsUser(intent, UserHandle.OWNER); 1499 } 1500 1501 void readConfigFileLocked() { 1502 if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile()); 1503 mPowerSaveWhitelistUserApps.clear(); 1504 FileInputStream stream; 1505 try { 1506 stream = mConfigFile.openRead(); 1507 } catch (FileNotFoundException e) { 1508 return; 1509 } 1510 try { 1511 XmlPullParser parser = Xml.newPullParser(); 1512 parser.setInput(stream, StandardCharsets.UTF_8.name()); 1513 readConfigFileLocked(parser); 1514 } catch (XmlPullParserException e) { 1515 } finally { 1516 try { 1517 stream.close(); 1518 } catch (IOException e) { 1519 } 1520 } 1521 1522 } 1523 1524 private void readConfigFileLocked(XmlPullParser parser) { 1525 final PackageManager pm = getContext().getPackageManager(); 1526 1527 try { 1528 int type; 1529 while ((type = parser.next()) != XmlPullParser.START_TAG 1530 && type != XmlPullParser.END_DOCUMENT) { 1531 ; 1532 } 1533 1534 if (type != XmlPullParser.START_TAG) { 1535 throw new IllegalStateException("no start tag found"); 1536 } 1537 1538 int outerDepth = parser.getDepth(); 1539 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1540 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1541 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1542 continue; 1543 } 1544 1545 String tagName = parser.getName(); 1546 if (tagName.equals("wl")) { 1547 String name = parser.getAttributeValue(null, "n"); 1548 if (name != null) { 1549 try { 1550 ApplicationInfo ai = pm.getApplicationInfo(name, 0); 1551 mPowerSaveWhitelistUserApps.put(ai.packageName, 1552 UserHandle.getAppId(ai.uid)); 1553 } catch (PackageManager.NameNotFoundException e) { 1554 } 1555 } 1556 } else { 1557 Slog.w(TAG, "Unknown element under <config>: " 1558 + parser.getName()); 1559 XmlUtils.skipCurrentTag(parser); 1560 } 1561 } 1562 1563 } catch (IllegalStateException e) { 1564 Slog.w(TAG, "Failed parsing config " + e); 1565 } catch (NullPointerException e) { 1566 Slog.w(TAG, "Failed parsing config " + e); 1567 } catch (NumberFormatException e) { 1568 Slog.w(TAG, "Failed parsing config " + e); 1569 } catch (XmlPullParserException e) { 1570 Slog.w(TAG, "Failed parsing config " + e); 1571 } catch (IOException e) { 1572 Slog.w(TAG, "Failed parsing config " + e); 1573 } catch (IndexOutOfBoundsException e) { 1574 Slog.w(TAG, "Failed parsing config " + e); 1575 } 1576 } 1577 1578 void writeConfigFileLocked() { 1579 mHandler.removeMessages(MSG_WRITE_CONFIG); 1580 mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000); 1581 } 1582 1583 void handleWriteConfigFile() { 1584 final ByteArrayOutputStream memStream = new ByteArrayOutputStream(); 1585 1586 try { 1587 synchronized (this) { 1588 XmlSerializer out = new FastXmlSerializer(); 1589 out.setOutput(memStream, StandardCharsets.UTF_8.name()); 1590 writeConfigFileLocked(out); 1591 } 1592 } catch (IOException e) { 1593 } 1594 1595 synchronized (mConfigFile) { 1596 FileOutputStream stream = null; 1597 try { 1598 stream = mConfigFile.startWrite(); 1599 memStream.writeTo(stream); 1600 stream.flush(); 1601 FileUtils.sync(stream); 1602 stream.close(); 1603 mConfigFile.finishWrite(stream); 1604 } catch (IOException e) { 1605 Slog.w(TAG, "Error writing config file", e); 1606 mConfigFile.failWrite(stream); 1607 } 1608 } 1609 } 1610 1611 void writeConfigFileLocked(XmlSerializer out) throws IOException { 1612 out.startDocument(null, true); 1613 out.startTag(null, "config"); 1614 for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { 1615 String name = mPowerSaveWhitelistUserApps.keyAt(i); 1616 out.startTag(null, "wl"); 1617 out.attribute(null, "n", name); 1618 out.endTag(null, "wl"); 1619 } 1620 out.endTag(null, "config"); 1621 out.endDocument(); 1622 } 1623 1624 private void dumpHelp(PrintWriter pw) { 1625 pw.println("Device idle controller (deviceidle) dump options:"); 1626 pw.println(" [-h] [CMD]"); 1627 pw.println(" -h: print this help text."); 1628 pw.println("Commands:"); 1629 pw.println(" step"); 1630 pw.println(" Immediately step to next state, without waiting for alarm."); 1631 pw.println(" force-idle"); 1632 pw.println(" Force directly into idle mode, regardless of other device state."); 1633 pw.println(" Use \"step\" to get out."); 1634 pw.println(" disable"); 1635 pw.println(" Completely disable device idle mode."); 1636 pw.println(" enable"); 1637 pw.println(" Re-enable device idle mode after it had previously been disabled."); 1638 pw.println(" enabled"); 1639 pw.println(" Print 1 if device idle mode is currently enabled, else 0."); 1640 pw.println(" whitelist"); 1641 pw.println(" Print currently whitelisted apps."); 1642 pw.println(" whitelist [package ...]"); 1643 pw.println(" Add (prefix with +) or remove (prefix with -) packages."); 1644 pw.println(" tempwhitelist [package ..]"); 1645 pw.println(" Temporarily place packages in whitelist for 10 seconds."); 1646 } 1647 1648 void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1649 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1650 != PackageManager.PERMISSION_GRANTED) { 1651 pw.println("Permission Denial: can't dump DeviceIdleController from from pid=" 1652 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 1653 + " without permission " + android.Manifest.permission.DUMP); 1654 return; 1655 } 1656 1657 if (args != null) { 1658 int userId = UserHandle.USER_OWNER; 1659 for (int i=0; i<args.length; i++) { 1660 String arg = args[i]; 1661 if ("-h".equals(arg)) { 1662 dumpHelp(pw); 1663 return; 1664 } else if ("-u".equals(arg)) { 1665 i++; 1666 if (i < args.length) { 1667 arg = args[i]; 1668 userId = Integer.parseInt(arg); 1669 } 1670 } else if ("-a".equals(arg)) { 1671 // Ignore, we always dump all. 1672 } else if ("step".equals(arg)) { 1673 synchronized (this) { 1674 long token = Binder.clearCallingIdentity(); 1675 try { 1676 exitForceIdleLocked(); 1677 stepIdleStateLocked(); 1678 pw.print("Stepped to: "); pw.println(stateToString(mState)); 1679 } finally { 1680 Binder.restoreCallingIdentity(token); 1681 } 1682 } 1683 return; 1684 } else if ("force-idle".equals(arg)) { 1685 synchronized (this) { 1686 long token = Binder.clearCallingIdentity(); 1687 try { 1688 if (!mEnabled) { 1689 pw.println("Unable to go idle; not enabled"); 1690 return; 1691 } 1692 mForceIdle = true; 1693 becomeInactiveIfAppropriateLocked(); 1694 int curState = mState; 1695 while (curState != STATE_IDLE) { 1696 stepIdleStateLocked(); 1697 if (curState == mState) { 1698 pw.print("Unable to go idle; stopped at "); 1699 pw.println(stateToString(mState)); 1700 exitForceIdleLocked(); 1701 return; 1702 } 1703 curState = mState; 1704 } 1705 pw.println("Now forced in to idle mode"); 1706 } finally { 1707 Binder.restoreCallingIdentity(token); 1708 } 1709 } 1710 return; 1711 } else if ("disable".equals(arg)) { 1712 synchronized (this) { 1713 long token = Binder.clearCallingIdentity(); 1714 try { 1715 if (mEnabled) { 1716 mEnabled = false; 1717 becomeActiveLocked("disabled", Process.myUid()); 1718 pw.println("Idle mode disabled"); 1719 } 1720 } finally { 1721 Binder.restoreCallingIdentity(token); 1722 } 1723 } 1724 return; 1725 } else if ("enable".equals(arg)) { 1726 synchronized (this) { 1727 long token = Binder.clearCallingIdentity(); 1728 try { 1729 exitForceIdleLocked(); 1730 if (!mEnabled) { 1731 mEnabled = true; 1732 becomeInactiveIfAppropriateLocked(); 1733 pw.println("Idle mode enabled"); 1734 } 1735 } finally { 1736 Binder.restoreCallingIdentity(token); 1737 } 1738 } 1739 return; 1740 } else if ("enabled".equals(arg)) { 1741 synchronized (this) { 1742 pw.println(mEnabled ? "1" : " 0"); 1743 } 1744 return; 1745 } else if ("whitelist".equals(arg)) { 1746 long token = Binder.clearCallingIdentity(); 1747 try { 1748 i++; 1749 if (i < args.length) { 1750 while (i < args.length) { 1751 arg = args[i]; 1752 i++; 1753 if (arg.length() < 1 || (arg.charAt(0) != '-' 1754 && arg.charAt(0) != '+')) { 1755 pw.println("Package must be prefixed with + or -: " + arg); 1756 return; 1757 } 1758 char op = arg.charAt(0); 1759 String pkg = arg.substring(1); 1760 if (op == '+') { 1761 if (addPowerSaveWhitelistAppInternal(pkg)) { 1762 pw.println("Added: " + pkg); 1763 } else { 1764 pw.println("Unknown package: " + pkg); 1765 } 1766 } else { 1767 if (removePowerSaveWhitelistAppInternal(pkg)) { 1768 pw.println("Removed: " + pkg); 1769 } 1770 } 1771 } 1772 } else { 1773 synchronized (this) { 1774 for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) { 1775 pw.print("system-excidle,"); 1776 pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j)); 1777 pw.print(","); 1778 pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j)); 1779 } 1780 for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) { 1781 pw.print("system,"); 1782 pw.print(mPowerSaveWhitelistApps.keyAt(j)); 1783 pw.print(","); 1784 pw.println(mPowerSaveWhitelistApps.valueAt(j)); 1785 } 1786 for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) { 1787 pw.print("user,"); 1788 pw.print(mPowerSaveWhitelistUserApps.keyAt(j)); 1789 pw.print(","); 1790 pw.println(mPowerSaveWhitelistUserApps.valueAt(j)); 1791 } 1792 } 1793 } 1794 } finally { 1795 Binder.restoreCallingIdentity(token); 1796 } 1797 return; 1798 } else if ("tempwhitelist".equals(arg)) { 1799 long token = Binder.clearCallingIdentity(); 1800 try { 1801 i++; 1802 if (i >= args.length) { 1803 pw.println("At least one package name must be specified"); 1804 return; 1805 } 1806 while (i < args.length) { 1807 arg = args[i]; 1808 i++; 1809 addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId, true, 1810 "shell"); 1811 pw.println("Added: " + arg); 1812 } 1813 } finally { 1814 Binder.restoreCallingIdentity(token); 1815 } 1816 return; 1817 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 1818 pw.println("Unknown option: " + arg); 1819 return; 1820 } else { 1821 pw.println("Unknown command: " + arg); 1822 return; 1823 } 1824 } 1825 } 1826 1827 synchronized (this) { 1828 mConstants.dump(pw); 1829 1830 int size = mPowerSaveWhitelistAppsExceptIdle.size(); 1831 if (size > 0) { 1832 pw.println(" Whitelist (except idle) system apps:"); 1833 for (int i = 0; i < size; i++) { 1834 pw.print(" "); 1835 pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i)); 1836 } 1837 } 1838 size = mPowerSaveWhitelistApps.size(); 1839 if (size > 0) { 1840 pw.println(" Whitelist system apps:"); 1841 for (int i = 0; i < size; i++) { 1842 pw.print(" "); 1843 pw.println(mPowerSaveWhitelistApps.keyAt(i)); 1844 } 1845 } 1846 size = mPowerSaveWhitelistUserApps.size(); 1847 if (size > 0) { 1848 pw.println(" Whitelist user apps:"); 1849 for (int i = 0; i < size; i++) { 1850 pw.print(" "); 1851 pw.println(mPowerSaveWhitelistUserApps.keyAt(i)); 1852 } 1853 } 1854 size = mPowerSaveWhitelistExceptIdleAppIds.size(); 1855 if (size > 0) { 1856 pw.println(" Whitelist (except idle) all app ids:"); 1857 for (int i = 0; i < size; i++) { 1858 pw.print(" "); 1859 pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i)); 1860 pw.println(); 1861 } 1862 } 1863 size = mPowerSaveWhitelistAllAppIds.size(); 1864 if (size > 0) { 1865 pw.println(" Whitelist all app ids:"); 1866 for (int i = 0; i < size; i++) { 1867 pw.print(" "); 1868 pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i)); 1869 pw.println(); 1870 } 1871 } 1872 size = mTempWhitelistAppIdEndTimes.size(); 1873 if (size > 0) { 1874 pw.println(" Temp whitelist schedule:"); 1875 final long timeNow = SystemClock.elapsedRealtime(); 1876 for (int i = 0; i < size; i++) { 1877 pw.print(" UID="); 1878 pw.print(mTempWhitelistAppIdEndTimes.keyAt(i)); 1879 pw.print(": "); 1880 Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i); 1881 TimeUtils.formatDuration(entry.first.value, timeNow, pw); 1882 pw.print(" - "); 1883 pw.println(entry.second); 1884 } 1885 } 1886 size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0; 1887 if (size > 0) { 1888 pw.println(" Temp whitelist app ids:"); 1889 for (int i = 0; i < size; i++) { 1890 pw.print(" "); 1891 pw.print(mTempWhitelistAppIdArray[i]); 1892 pw.println(); 1893 } 1894 } 1895 1896 pw.print(" mEnabled="); pw.println(mEnabled); 1897 pw.print(" mForceIdle="); pw.println(mForceIdle); 1898 pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); 1899 pw.print(" mCurDisplay="); pw.println(mCurDisplay); 1900 pw.print(" mScreenOn="); pw.println(mScreenOn); 1901 pw.print(" mCharging="); pw.println(mCharging); 1902 pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); 1903 pw.print(" mSensing="); pw.print(mSensing); pw.print(" mNotMoving="); 1904 pw.println(mNotMoving); 1905 pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHaveGps="); 1906 pw.print(mHaveGps); pw.print(" mLocated="); pw.println(mLocated); 1907 if (mLastGenericLocation != null) { 1908 pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation); 1909 } 1910 if (mLastGpsLocation != null) { 1911 pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation); 1912 } 1913 pw.print(" mState="); pw.println(stateToString(mState)); 1914 pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw); 1915 pw.println(); 1916 if (mNextAlarmTime != 0) { 1917 pw.print(" mNextAlarmTime="); 1918 TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); 1919 pw.println(); 1920 } 1921 if (mNextIdlePendingDelay != 0) { 1922 pw.print(" mNextIdlePendingDelay="); 1923 TimeUtils.formatDuration(mNextIdlePendingDelay, pw); 1924 pw.println(); 1925 } 1926 if (mNextIdleDelay != 0) { 1927 pw.print(" mNextIdleDelay="); 1928 TimeUtils.formatDuration(mNextIdleDelay, pw); 1929 pw.println(); 1930 } 1931 } 1932 } 1933 } 1934