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