1 /* 2 * Copyright (C) 2017 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 package com.android.server.power.batterysaver; 17 18 import android.annotation.IntDef; 19 import android.content.ContentResolver; 20 import android.content.Context; 21 import android.database.ContentObserver; 22 import android.net.Uri; 23 import android.os.BatterySaverPolicyConfig; 24 import android.os.Handler; 25 import android.os.PowerManager; 26 import android.os.PowerManager.ServiceType; 27 import android.os.PowerSaveState; 28 import android.provider.Settings; 29 import android.text.TextUtils; 30 import android.util.ArrayMap; 31 import android.util.KeyValueListParser; 32 import android.util.Slog; 33 import android.view.accessibility.AccessibilityManager; 34 35 import com.android.internal.R; 36 import com.android.internal.annotations.GuardedBy; 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.internal.os.BackgroundThread; 39 import com.android.internal.util.ConcurrentUtils; 40 import com.android.server.power.PowerManagerService; 41 42 import java.io.PrintWriter; 43 import java.lang.annotation.Retention; 44 import java.lang.annotation.RetentionPolicy; 45 import java.util.ArrayList; 46 import java.util.List; 47 import java.util.Map; 48 import java.util.Objects; 49 50 /** 51 * Class to decide whether to turn on battery saver mode for specific services. 52 * 53 * IMPORTANT: This class shares the power manager lock, which is very low in the lock hierarchy. 54 * Do not call out with the lock held, such as AccessibilityManager. (Settings provider is okay.) 55 * 56 * Test: atest com.android.server.power.batterysaver.BatterySaverPolicyTest 57 */ 58 public class BatterySaverPolicy extends ContentObserver { 59 private static final String TAG = "BatterySaverPolicy"; 60 61 static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE. 62 63 private static final String KEY_GPS_MODE = "gps_mode"; 64 private static final String KEY_VIBRATION_DISABLED = "vibration_disabled"; 65 private static final String KEY_ANIMATION_DISABLED = "animation_disabled"; 66 private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled"; 67 68 /** 69 * Disable turning on the network firewall when Battery Saver is turned on. 70 * If set to false, the firewall WILL be turned on when Battery Saver is turned on. 71 * If set to true, the firewall WILL NOT be turned on when Battery Saver is turned on. 72 */ 73 private static final String KEY_ACTIVATE_FIREWALL_DISABLED = "firewall_disabled"; 74 75 /** 76 * Disable turning on the special low power screen brightness dimming when Battery Saver is 77 * turned on. 78 * If set to false, the screen brightness dimming WILL be turned on by Battery Saver. 79 * If set to true, the screen brightness WILL NOT be turned on by Battery Saver. 80 */ 81 private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled"; 82 83 /** 84 * Disable turning on Data Saver when Battery Saver is turned on. 85 * If set to false, Data Saver WILL be turned on when Battery Saver is turned on. 86 * If set to true, Data Saver WILL NOT be turned on when Battery Saver is turned on. 87 */ 88 private static final String KEY_ACTIVATE_DATASAVER_DISABLED = "datasaver_disabled"; 89 90 /** 91 * {@code true} if the Policy should advertise to the rest of the system that battery saver 92 * is enabled. This advertising could cause other system components to change their 93 * behavior. This will not affect other policy flags and what they change. 94 */ 95 private static final String KEY_ADVERTISE_IS_ENABLED = "advertise_is_enabled"; 96 97 private static final String KEY_LAUNCH_BOOST_DISABLED = "launch_boost_disabled"; 98 private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor"; 99 private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred"; 100 private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred"; 101 private static final String KEY_FORCE_ALL_APPS_STANDBY = "force_all_apps_standby"; 102 private static final String KEY_FORCE_BACKGROUND_CHECK = "force_background_check"; 103 private static final String KEY_OPTIONAL_SENSORS_DISABLED = "optional_sensors_disabled"; 104 private static final String KEY_AOD_DISABLED = "aod_disabled"; 105 // Go into deep Doze as soon as the screen turns off. 106 private static final String KEY_QUICK_DOZE_ENABLED = "quick_doze_enabled"; 107 private static final String KEY_ENABLE_NIGHT_MODE = "enable_night_mode"; 108 109 private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i"; 110 private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n"; 111 112 @VisibleForTesting 113 static final Policy OFF_POLICY = new Policy( 114 1f, /* adjustBrightnessFactor */ 115 false, /* advertiseIsEnabled */ 116 false, /* deferFullBackup */ 117 false, /* deferKeyValueBackup */ 118 false, /* disableAnimation */ 119 false, /* disableAod */ 120 false, /* disableLaunchBoost */ 121 false, /* disableOptionalSensors */ 122 false, /* disableSoundTrigger */ 123 false, /* disableVibration */ 124 false, /* enableAdjustBrightness */ 125 false, /* enableDataSaver */ 126 false, /* enableFireWall */ 127 false, /* enableNightMode */ 128 false, /* enableQuickDoze */ 129 new ArrayMap<>(), /* filesForInteractive */ 130 new ArrayMap<>(), /* filesForNoninteractive */ 131 false, /* forceAllAppsStandby */ 132 false, /* forceBackgroundCheck */ 133 PowerManager.LOCATION_MODE_NO_CHANGE /* locationMode */ 134 ); 135 136 private static final Policy DEFAULT_ADAPTIVE_POLICY = OFF_POLICY; 137 138 private static final Policy DEFAULT_FULL_POLICY = new Policy( 139 0.5f, /* adjustBrightnessFactor */ 140 true, /* advertiseIsEnabled */ 141 true, /* deferFullBackup */ 142 true, /* deferKeyValueBackup */ 143 false, /* disableAnimation */ 144 true, /* disableAod */ 145 true, /* disableLaunchBoost */ 146 true, /* disableOptionalSensors */ 147 true, /* disableSoundTrigger */ 148 true, /* disableVibration */ 149 false, /* enableAdjustBrightness */ 150 false, /* enableDataSaver */ 151 true, /* enableFirewall */ 152 true, /* enableNightMode */ 153 true, /* enableQuickDoze */ 154 new ArrayMap<>(), /* filesForInteractive */ 155 new ArrayMap<>(), /* filesForNoninteractive */ 156 true, /* forceAllAppsStandby */ 157 true, /* forceBackgroundCheck */ 158 PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF /* locationMode */ 159 ); 160 161 private final Object mLock; 162 private final Handler mHandler; 163 164 @GuardedBy("mLock") 165 private String mSettings; 166 167 @GuardedBy("mLock") 168 private String mDeviceSpecificSettings; 169 170 @GuardedBy("mLock") 171 private String mDeviceSpecificSettingsSource; // For dump() only. 172 173 @GuardedBy("mLock") 174 private String mAdaptiveSettings; 175 176 @GuardedBy("mLock") 177 private String mAdaptiveDeviceSpecificSettings; 178 179 /** 180 * A short string describing which battery saver is now enabled, which we dump in the eventlog. 181 */ 182 @GuardedBy("mLock") 183 private String mEventLogKeys; 184 185 /** 186 * Whether vibration should *really* be disabled -- i.e. {@link Policy#disableVibration} 187 * is true *and* {@link #mAccessibilityEnabled} is false. 188 */ 189 @GuardedBy("mLock") 190 private boolean mDisableVibrationEffective; 191 192 /** 193 * Whether accessibility is currently enabled or not. 194 */ 195 @GuardedBy("mLock") 196 private boolean mAccessibilityEnabled; 197 198 /** The current default adaptive policy. */ 199 @GuardedBy("mLock") 200 private Policy mDefaultAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY; 201 202 /** The policy that will be used for adaptive battery saver. */ 203 @GuardedBy("mLock") 204 private Policy mAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY; 205 206 /** The policy to be used for full battery saver. */ 207 @GuardedBy("mLock") 208 private Policy mFullPolicy = DEFAULT_FULL_POLICY; 209 210 @IntDef(prefix = {"POLICY_LEVEL_"}, value = { 211 POLICY_LEVEL_OFF, 212 POLICY_LEVEL_ADAPTIVE, 213 POLICY_LEVEL_FULL, 214 }) 215 @Retention(RetentionPolicy.SOURCE) 216 @interface PolicyLevel {} 217 218 static final int POLICY_LEVEL_OFF = 0; 219 static final int POLICY_LEVEL_ADAPTIVE = 1; 220 static final int POLICY_LEVEL_FULL = 2; 221 222 @GuardedBy("mLock") 223 private int mPolicyLevel = POLICY_LEVEL_OFF; 224 225 private final Context mContext; 226 private final ContentResolver mContentResolver; 227 private final BatterySavingStats mBatterySavingStats; 228 229 @GuardedBy("mLock") 230 private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>(); 231 232 public interface BatterySaverPolicyListener { onBatterySaverPolicyChanged(BatterySaverPolicy policy)233 void onBatterySaverPolicyChanged(BatterySaverPolicy policy); 234 } 235 BatterySaverPolicy(Object lock, Context context, BatterySavingStats batterySavingStats)236 public BatterySaverPolicy(Object lock, Context context, BatterySavingStats batterySavingStats) { 237 super(BackgroundThread.getHandler()); 238 mLock = lock; 239 mHandler = BackgroundThread.getHandler(); 240 mContext = context; 241 mContentResolver = context.getContentResolver(); 242 mBatterySavingStats = batterySavingStats; 243 } 244 245 /** 246 * Called by {@link PowerManagerService#systemReady}, *with no lock held.* 247 */ systemReady()248 public void systemReady() { 249 ConcurrentUtils.wtfIfLockHeld(TAG, mLock); 250 251 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 252 Settings.Global.BATTERY_SAVER_CONSTANTS), false, this); 253 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 254 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this); 255 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 256 Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS), false, this); 257 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 258 Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS), false, this); 259 260 final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class); 261 262 acm.addAccessibilityStateChangeListener((enabled) -> { 263 synchronized (mLock) { 264 mAccessibilityEnabled = enabled; 265 } 266 refreshSettings(); 267 }); 268 final boolean enabled = acm.isEnabled(); 269 synchronized (mLock) { 270 mAccessibilityEnabled = enabled; 271 } 272 onChange(true, null); 273 } 274 275 @VisibleForTesting addListener(BatterySaverPolicyListener listener)276 public void addListener(BatterySaverPolicyListener listener) { 277 synchronized (mLock) { 278 // TODO: set this in the constructor instead 279 mListeners.add(listener); 280 } 281 } 282 283 @VisibleForTesting getGlobalSetting(String key)284 String getGlobalSetting(String key) { 285 return Settings.Global.getString(mContentResolver, key); 286 } 287 288 @VisibleForTesting getDeviceSpecificConfigResId()289 int getDeviceSpecificConfigResId() { 290 return R.string.config_batterySaverDeviceSpecificConfig; 291 } 292 293 @Override onChange(boolean selfChange, Uri uri)294 public void onChange(boolean selfChange, Uri uri) { 295 refreshSettings(); 296 } 297 refreshSettings()298 private void refreshSettings() { 299 final BatterySaverPolicyListener[] listeners; 300 synchronized (mLock) { 301 // Load the non-device-specific setting. 302 final String setting = getGlobalSetting(Settings.Global.BATTERY_SAVER_CONSTANTS); 303 304 // Load the device specific setting. 305 // We first check the global setting, and if it's empty or the string "null" is set, 306 // use the default value from config.xml. 307 String deviceSpecificSetting = getGlobalSetting( 308 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS); 309 mDeviceSpecificSettingsSource = 310 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS; 311 312 if (TextUtils.isEmpty(deviceSpecificSetting) || "null".equals(deviceSpecificSetting)) { 313 deviceSpecificSetting = 314 mContext.getString(getDeviceSpecificConfigResId()); 315 mDeviceSpecificSettingsSource = "(overlay)"; 316 } 317 318 final String adaptiveSetting = 319 getGlobalSetting(Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS); 320 final String adaptiveDeviceSpecificSetting = getGlobalSetting( 321 Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS); 322 323 if (!updateConstantsLocked(setting, deviceSpecificSetting, 324 adaptiveSetting, adaptiveDeviceSpecificSetting)) { 325 // Nothing of note changed. 326 return; 327 } 328 329 listeners = mListeners.toArray(new BatterySaverPolicyListener[0]); 330 } 331 332 // Notify the listeners. 333 mHandler.post(() -> { 334 for (BatterySaverPolicyListener listener : listeners) { 335 listener.onBatterySaverPolicyChanged(this); 336 } 337 }); 338 } 339 340 @GuardedBy("mLock") 341 @VisibleForTesting updateConstantsLocked(final String setting, final String deviceSpecificSetting)342 void updateConstantsLocked(final String setting, final String deviceSpecificSetting) { 343 updateConstantsLocked(setting, deviceSpecificSetting, "", ""); 344 } 345 346 /** @return true if the currently active policy changed. */ updateConstantsLocked(String setting, String deviceSpecificSetting, String adaptiveSetting, String adaptiveDeviceSpecificSetting)347 private boolean updateConstantsLocked(String setting, String deviceSpecificSetting, 348 String adaptiveSetting, String adaptiveDeviceSpecificSetting) { 349 setting = TextUtils.emptyIfNull(setting); 350 deviceSpecificSetting = TextUtils.emptyIfNull(deviceSpecificSetting); 351 adaptiveSetting = TextUtils.emptyIfNull(adaptiveSetting); 352 adaptiveDeviceSpecificSetting = TextUtils.emptyIfNull(adaptiveDeviceSpecificSetting); 353 354 if (setting.equals(mSettings) 355 && deviceSpecificSetting.equals(mDeviceSpecificSettings) 356 && adaptiveSetting.equals(mAdaptiveSettings) 357 && adaptiveDeviceSpecificSetting.equals(mAdaptiveDeviceSpecificSettings)) { 358 return false; 359 } 360 361 mSettings = setting; 362 mDeviceSpecificSettings = deviceSpecificSetting; 363 mAdaptiveSettings = adaptiveSetting; 364 mAdaptiveDeviceSpecificSettings = adaptiveDeviceSpecificSetting; 365 366 if (DEBUG) { 367 Slog.i(TAG, "mSettings=" + mSettings); 368 Slog.i(TAG, "mDeviceSpecificSettings=" + mDeviceSpecificSettings); 369 Slog.i(TAG, "mAdaptiveSettings=" + mAdaptiveSettings); 370 Slog.i(TAG, "mAdaptiveDeviceSpecificSettings=" + mAdaptiveDeviceSpecificSettings); 371 } 372 373 boolean changed = false; 374 Policy newFullPolicy = Policy.fromSettings(setting, deviceSpecificSetting, 375 DEFAULT_FULL_POLICY); 376 if (mPolicyLevel == POLICY_LEVEL_FULL && !mFullPolicy.equals(newFullPolicy)) { 377 changed = true; 378 } 379 mFullPolicy = newFullPolicy; 380 381 mDefaultAdaptivePolicy = Policy.fromSettings(adaptiveSetting, adaptiveDeviceSpecificSetting, 382 DEFAULT_ADAPTIVE_POLICY); 383 if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE 384 && !mAdaptivePolicy.equals(mDefaultAdaptivePolicy)) { 385 changed = true; 386 } 387 // This will override any config set by an external source. This should be fine for now. 388 // TODO: make sure it doesn't override what's set externally 389 mAdaptivePolicy = mDefaultAdaptivePolicy; 390 391 updatePolicyDependenciesLocked(); 392 393 return changed; 394 } 395 396 @GuardedBy("mLock") updatePolicyDependenciesLocked()397 private void updatePolicyDependenciesLocked() { 398 final Policy currPolicy = getCurrentPolicyLocked(); 399 // Update the effective vibration policy. 400 mDisableVibrationEffective = currPolicy.disableVibration 401 && !mAccessibilityEnabled; // Don't disable vibration when accessibility is on. 402 403 final StringBuilder sb = new StringBuilder(); 404 405 if (currPolicy.forceAllAppsStandby) sb.append("A"); 406 if (currPolicy.forceBackgroundCheck) sb.append("B"); 407 408 if (mDisableVibrationEffective) sb.append("v"); 409 if (currPolicy.disableAnimation) sb.append("a"); 410 if (currPolicy.disableSoundTrigger) sb.append("s"); 411 if (currPolicy.deferFullBackup) sb.append("F"); 412 if (currPolicy.deferKeyValueBackup) sb.append("K"); 413 if (currPolicy.enableFirewall) sb.append("f"); 414 if (currPolicy.enableDataSaver) sb.append("d"); 415 if (currPolicy.enableAdjustBrightness) sb.append("b"); 416 417 if (currPolicy.disableLaunchBoost) sb.append("l"); 418 if (currPolicy.disableOptionalSensors) sb.append("S"); 419 if (currPolicy.disableAod) sb.append("o"); 420 if (currPolicy.enableQuickDoze) sb.append("q"); 421 422 sb.append(currPolicy.locationMode); 423 424 mEventLogKeys = sb.toString(); 425 } 426 427 static class Policy { 428 /** 429 * This is the flag to decide the how much to adjust the screen brightness. This is 430 * the float value from 0 to 1 where 1 means don't change brightness. 431 * 432 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 433 * @see #KEY_ADJUST_BRIGHTNESS_FACTOR 434 */ 435 public final float adjustBrightnessFactor; 436 437 /** 438 * {@code true} if the Policy should advertise to the rest of the system that battery saver 439 * is enabled. This advertising could cause other system components to change their 440 * behavior. This will not affect other policy flags and what they change. 441 * 442 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 443 * @see #KEY_ADVERTISE_IS_ENABLED 444 */ 445 public final boolean advertiseIsEnabled; 446 447 /** 448 * {@code true} if full backup is deferred in battery saver mode. 449 * 450 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 451 * @see #KEY_FULLBACKUP_DEFERRED 452 */ 453 public final boolean deferFullBackup; 454 455 /** 456 * {@code true} if key value backup is deferred in battery saver mode. 457 * 458 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 459 * @see #KEY_KEYVALUE_DEFERRED 460 */ 461 public final boolean deferKeyValueBackup; 462 463 /** 464 * {@code true} if animation is disabled in battery saver mode. 465 * 466 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 467 * @see #KEY_ANIMATION_DISABLED 468 */ 469 public final boolean disableAnimation; 470 471 /** 472 * {@code true} if AOD is disabled in battery saver mode. 473 */ 474 public final boolean disableAod; 475 476 /** 477 * {@code true} if launch boost should be disabled on battery saver. 478 */ 479 public final boolean disableLaunchBoost; 480 481 /** 482 * Whether to show non-essential sensors (e.g. edge sensors) or not. 483 */ 484 public final boolean disableOptionalSensors; 485 486 /** 487 * {@code true} if sound trigger is disabled in battery saver mode 488 * in battery saver mode. 489 * 490 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 491 * @see #KEY_SOUNDTRIGGER_DISABLED 492 */ 493 public final boolean disableSoundTrigger; 494 495 /** 496 * {@code true} if vibration is disabled in battery saver mode. 497 * 498 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 499 * @see #KEY_VIBRATION_DISABLED 500 */ 501 public final boolean disableVibration; 502 503 /** 504 * {@code true} if low power mode brightness adjustment should be turned on in battery saver 505 * mode. 506 * 507 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 508 * @see #KEY_ADJUST_BRIGHTNESS_DISABLED 509 */ 510 public final boolean enableAdjustBrightness; 511 512 /** 513 * {@code true} if data saver should be turned on in battery saver mode. 514 * 515 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 516 * @see #KEY_ACTIVATE_DATASAVER_DISABLED 517 */ 518 public final boolean enableDataSaver; 519 520 /** 521 * {@code true} if network policy firewall should be turned on in battery saver mode. 522 * 523 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 524 * @see #KEY_ACTIVATE_FIREWALL_DISABLED 525 */ 526 public final boolean enableFirewall; 527 528 /** 529 * Whether to enable night mode or not. 530 */ 531 public final boolean enableNightMode; 532 533 /** 534 * Whether Quick Doze is enabled or not. 535 */ 536 public final boolean enableQuickDoze; 537 538 /** 539 * List of [Filename -> content] that should be written when battery saver is activated 540 * and the device is interactive. 541 * 542 * We use this to change the max CPU frequencies. 543 */ 544 public final ArrayMap<String, String> filesForInteractive; 545 546 /** 547 * List of [Filename -> content] that should be written when battery saver is activated 548 * and the device is non-interactive. 549 * 550 * We use this to change the max CPU frequencies. 551 */ 552 public final ArrayMap<String, String> filesForNoninteractive; 553 554 /** 555 * Whether to put all apps in the stand-by mode. 556 */ 557 public final boolean forceAllAppsStandby; 558 559 /** 560 * Whether to force background check. 561 */ 562 public final boolean forceBackgroundCheck; 563 564 /** 565 * This is the flag to decide the location mode in battery saver mode. This was 566 * previously called gpsMode. 567 * 568 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 569 * @see #KEY_GPS_MODE 570 */ 571 public final int locationMode; 572 573 private final int mHashCode; 574 Policy( float adjustBrightnessFactor, boolean advertiseIsEnabled, boolean deferFullBackup, boolean deferKeyValueBackup, boolean disableAnimation, boolean disableAod, boolean disableLaunchBoost, boolean disableOptionalSensors, boolean disableSoundTrigger, boolean disableVibration, boolean enableAdjustBrightness, boolean enableDataSaver, boolean enableFirewall, boolean enableNightMode, boolean enableQuickDoze, ArrayMap<String, String> filesForInteractive, ArrayMap<String, String> filesForNoninteractive, boolean forceAllAppsStandby, boolean forceBackgroundCheck, int locationMode)575 Policy( 576 float adjustBrightnessFactor, 577 boolean advertiseIsEnabled, 578 boolean deferFullBackup, 579 boolean deferKeyValueBackup, 580 boolean disableAnimation, 581 boolean disableAod, 582 boolean disableLaunchBoost, 583 boolean disableOptionalSensors, 584 boolean disableSoundTrigger, 585 boolean disableVibration, 586 boolean enableAdjustBrightness, 587 boolean enableDataSaver, 588 boolean enableFirewall, 589 boolean enableNightMode, 590 boolean enableQuickDoze, 591 ArrayMap<String, String> filesForInteractive, 592 ArrayMap<String, String> filesForNoninteractive, 593 boolean forceAllAppsStandby, 594 boolean forceBackgroundCheck, 595 int locationMode) { 596 597 this.adjustBrightnessFactor = Math.min(1, Math.max(0, adjustBrightnessFactor)); 598 this.advertiseIsEnabled = advertiseIsEnabled; 599 this.deferFullBackup = deferFullBackup; 600 this.deferKeyValueBackup = deferKeyValueBackup; 601 this.disableAnimation = disableAnimation; 602 this.disableAod = disableAod; 603 this.disableLaunchBoost = disableLaunchBoost; 604 this.disableOptionalSensors = disableOptionalSensors; 605 this.disableSoundTrigger = disableSoundTrigger; 606 this.disableVibration = disableVibration; 607 this.enableAdjustBrightness = enableAdjustBrightness; 608 this.enableDataSaver = enableDataSaver; 609 this.enableFirewall = enableFirewall; 610 this.enableNightMode = enableNightMode; 611 this.enableQuickDoze = enableQuickDoze; 612 this.filesForInteractive = filesForInteractive; 613 this.filesForNoninteractive = filesForNoninteractive; 614 this.forceAllAppsStandby = forceAllAppsStandby; 615 this.forceBackgroundCheck = forceBackgroundCheck; 616 617 if (locationMode < PowerManager.MIN_LOCATION_MODE 618 || PowerManager.MAX_LOCATION_MODE < locationMode) { 619 Slog.e(TAG, "Invalid location mode: " + locationMode); 620 this.locationMode = PowerManager.LOCATION_MODE_NO_CHANGE; 621 } else { 622 this.locationMode = locationMode; 623 } 624 625 mHashCode = Objects.hash( 626 adjustBrightnessFactor, 627 advertiseIsEnabled, 628 deferFullBackup, 629 deferKeyValueBackup, 630 disableAnimation, 631 disableAod, 632 disableLaunchBoost, 633 disableOptionalSensors, 634 disableSoundTrigger, 635 disableVibration, 636 enableAdjustBrightness, 637 enableDataSaver, 638 enableFirewall, 639 enableNightMode, 640 enableQuickDoze, 641 filesForInteractive, 642 filesForNoninteractive, 643 forceAllAppsStandby, 644 forceBackgroundCheck, 645 locationMode); 646 } 647 fromConfig(BatterySaverPolicyConfig config)648 static Policy fromConfig(BatterySaverPolicyConfig config) { 649 if (config == null) { 650 Slog.e(TAG, "Null config passed down to BatterySaverPolicy"); 651 return OFF_POLICY; 652 } 653 654 // Device-specific parameters. 655 Map<String, String> deviceSpecificSettings = config.getDeviceSpecificSettings(); 656 final String cpuFreqInteractive = 657 deviceSpecificSettings.getOrDefault(KEY_CPU_FREQ_INTERACTIVE, ""); 658 final String cpuFreqNoninteractive = 659 deviceSpecificSettings.getOrDefault(KEY_CPU_FREQ_NONINTERACTIVE, ""); 660 661 return new Policy( 662 config.getAdjustBrightnessFactor(), 663 config.getAdvertiseIsEnabled(), 664 config.getDeferFullBackup(), 665 config.getDeferKeyValueBackup(), 666 config.getDisableAnimation(), 667 config.getDisableAod(), 668 config.getDisableLaunchBoost(), 669 config.getDisableOptionalSensors(), 670 config.getDisableSoundTrigger(), 671 config.getDisableVibration(), 672 config.getEnableAdjustBrightness(), 673 config.getEnableDataSaver(), 674 config.getEnableFirewall(), 675 config.getEnableNightMode(), 676 config.getEnableQuickDoze(), 677 /* filesForInteractive */ 678 (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(), 679 /* filesForNoninteractive */ 680 (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(), 681 config.getForceAllAppsStandby(), 682 config.getForceBackgroundCheck(), 683 config.getLocationMode() 684 ); 685 } 686 fromSettings(String settings, String deviceSpecificSettings)687 static Policy fromSettings(String settings, String deviceSpecificSettings) { 688 return fromSettings(settings, deviceSpecificSettings, OFF_POLICY); 689 } 690 fromSettings(String settings, String deviceSpecificSettings, Policy defaultPolicy)691 static Policy fromSettings(String settings, String deviceSpecificSettings, 692 Policy defaultPolicy) { 693 final KeyValueListParser parser = new KeyValueListParser(','); 694 695 // Device-specific parameters. 696 try { 697 parser.setString(deviceSpecificSettings == null ? "" : deviceSpecificSettings); 698 } catch (IllegalArgumentException e) { 699 Slog.wtf(TAG, "Bad device specific battery saver constants: " 700 + deviceSpecificSettings); 701 } 702 703 final String cpuFreqInteractive = parser.getString(KEY_CPU_FREQ_INTERACTIVE, ""); 704 final String cpuFreqNoninteractive = parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, ""); 705 706 // Non-device-specific parameters. 707 try { 708 parser.setString(settings == null ? "" : settings); 709 } catch (IllegalArgumentException e) { 710 Slog.wtf(TAG, "Bad battery saver constants: " + settings); 711 } 712 713 float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 714 defaultPolicy.adjustBrightnessFactor); 715 boolean advertiseIsEnabled = parser.getBoolean(KEY_ADVERTISE_IS_ENABLED, 716 defaultPolicy.advertiseIsEnabled); 717 boolean deferFullBackup = parser.getBoolean(KEY_FULLBACKUP_DEFERRED, 718 defaultPolicy.deferFullBackup); 719 boolean deferKeyValueBackup = parser.getBoolean(KEY_KEYVALUE_DEFERRED, 720 defaultPolicy.deferKeyValueBackup); 721 boolean disableAnimation = parser.getBoolean(KEY_ANIMATION_DISABLED, 722 defaultPolicy.disableAnimation); 723 boolean disableAod = parser.getBoolean(KEY_AOD_DISABLED, defaultPolicy.disableAod); 724 boolean disableLaunchBoost = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED, 725 defaultPolicy.disableLaunchBoost); 726 boolean disableOptionalSensors = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, 727 defaultPolicy.disableOptionalSensors); 728 boolean disableSoundTrigger = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, 729 defaultPolicy.disableSoundTrigger); 730 boolean disableVibrationConfig = parser.getBoolean(KEY_VIBRATION_DISABLED, 731 defaultPolicy.disableVibration); 732 boolean enableAdjustBrightness = !parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, 733 !defaultPolicy.enableAdjustBrightness); 734 boolean enableDataSaver = !parser.getBoolean(KEY_ACTIVATE_DATASAVER_DISABLED, 735 !defaultPolicy.enableDataSaver); 736 boolean enableFirewall = !parser.getBoolean(KEY_ACTIVATE_FIREWALL_DISABLED, 737 !defaultPolicy.enableFirewall); 738 boolean enableNightMode = parser.getBoolean(KEY_ENABLE_NIGHT_MODE, 739 defaultPolicy.enableNightMode); 740 boolean enableQuickDoze = parser.getBoolean(KEY_QUICK_DOZE_ENABLED, 741 defaultPolicy.enableQuickDoze); 742 boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY, 743 defaultPolicy.forceAllAppsStandby); 744 boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, 745 defaultPolicy.forceBackgroundCheck); 746 int locationMode = parser.getInt(KEY_GPS_MODE, defaultPolicy.locationMode); 747 748 return new Policy( 749 adjustBrightnessFactor, 750 advertiseIsEnabled, 751 deferFullBackup, 752 deferKeyValueBackup, 753 disableAnimation, 754 disableAod, 755 disableLaunchBoost, 756 disableOptionalSensors, 757 disableSoundTrigger, 758 /* disableVibration */ 759 disableVibrationConfig, 760 enableAdjustBrightness, 761 enableDataSaver, 762 enableFirewall, 763 enableNightMode, 764 enableQuickDoze, 765 /* filesForInteractive */ 766 (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(), 767 /* filesForNoninteractive */ 768 (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(), 769 forceAllAppsStandby, 770 forceBackgroundCheck, 771 locationMode 772 ); 773 } 774 775 @Override equals(Object obj)776 public boolean equals(Object obj) { 777 if (this == obj) return true; 778 if (!(obj instanceof Policy)) return false; 779 Policy other = (Policy) obj; 780 return Float.compare(other.adjustBrightnessFactor, adjustBrightnessFactor) == 0 781 && advertiseIsEnabled == other.advertiseIsEnabled 782 && deferFullBackup == other.deferFullBackup 783 && deferKeyValueBackup == other.deferKeyValueBackup 784 && disableAnimation == other.disableAnimation 785 && disableAod == other.disableAod 786 && disableLaunchBoost == other.disableLaunchBoost 787 && disableOptionalSensors == other.disableOptionalSensors 788 && disableSoundTrigger == other.disableSoundTrigger 789 && disableVibration == other.disableVibration 790 && enableAdjustBrightness == other.enableAdjustBrightness 791 && enableDataSaver == other.enableDataSaver 792 && enableFirewall == other.enableFirewall 793 && enableNightMode == other.enableNightMode 794 && enableQuickDoze == other.enableQuickDoze 795 && forceAllAppsStandby == other.forceAllAppsStandby 796 && forceBackgroundCheck == other.forceBackgroundCheck 797 && locationMode == other.locationMode 798 && filesForInteractive.equals(other.filesForInteractive) 799 && filesForNoninteractive.equals(other.filesForNoninteractive); 800 } 801 802 @Override hashCode()803 public int hashCode() { 804 return mHashCode; 805 } 806 } 807 808 /** 809 * Get the {@link PowerSaveState} based on the current policy level. 810 * The result will have {@link PowerSaveState#batterySaverEnabled} and some other 811 * parameters when necessary. 812 * 813 * @param type type of the service, one of {@link ServiceType} 814 * @return State data that contains battery saver data 815 */ getBatterySaverPolicy(@erviceType int type)816 public PowerSaveState getBatterySaverPolicy(@ServiceType int type) { 817 synchronized (mLock) { 818 final Policy currPolicy = getCurrentPolicyLocked(); 819 final PowerSaveState.Builder builder = new PowerSaveState.Builder() 820 .setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled); 821 switch (type) { 822 case ServiceType.LOCATION: 823 boolean isEnabled = currPolicy.advertiseIsEnabled 824 || currPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE; 825 return builder.setBatterySaverEnabled(isEnabled) 826 .setLocationMode(currPolicy.locationMode) 827 .build(); 828 case ServiceType.ANIMATION: 829 return builder.setBatterySaverEnabled(currPolicy.disableAnimation) 830 .build(); 831 case ServiceType.FULL_BACKUP: 832 return builder.setBatterySaverEnabled(currPolicy.deferFullBackup) 833 .build(); 834 case ServiceType.KEYVALUE_BACKUP: 835 return builder.setBatterySaverEnabled(currPolicy.deferKeyValueBackup) 836 .build(); 837 case ServiceType.NETWORK_FIREWALL: 838 return builder.setBatterySaverEnabled(currPolicy.enableFirewall) 839 .build(); 840 case ServiceType.SCREEN_BRIGHTNESS: 841 return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness) 842 .setBrightnessFactor(currPolicy.adjustBrightnessFactor) 843 .build(); 844 case ServiceType.DATA_SAVER: 845 return builder.setBatterySaverEnabled(currPolicy.enableDataSaver) 846 .build(); 847 case ServiceType.SOUND: 848 return builder.setBatterySaverEnabled(currPolicy.disableSoundTrigger) 849 .build(); 850 case ServiceType.VIBRATION: 851 return builder.setBatterySaverEnabled(mDisableVibrationEffective) 852 .build(); 853 case ServiceType.FORCE_ALL_APPS_STANDBY: 854 return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby) 855 .build(); 856 case ServiceType.FORCE_BACKGROUND_CHECK: 857 return builder.setBatterySaverEnabled(currPolicy.forceBackgroundCheck) 858 .build(); 859 case ServiceType.NIGHT_MODE: 860 return builder.setBatterySaverEnabled(currPolicy.enableNightMode) 861 .build(); 862 case ServiceType.OPTIONAL_SENSORS: 863 return builder.setBatterySaverEnabled(currPolicy.disableOptionalSensors) 864 .build(); 865 case ServiceType.AOD: 866 return builder.setBatterySaverEnabled(currPolicy.disableAod) 867 .build(); 868 case ServiceType.QUICK_DOZE: 869 return builder.setBatterySaverEnabled(currPolicy.enableQuickDoze) 870 .build(); 871 default: 872 return builder.setBatterySaverEnabled(currPolicy.advertiseIsEnabled) 873 .build(); 874 } 875 } 876 } 877 878 /** 879 * Sets the current policy. 880 * 881 * @return true if the policy level was changed. 882 */ setPolicyLevel(@olicyLevel int level)883 boolean setPolicyLevel(@PolicyLevel int level) { 884 synchronized (mLock) { 885 if (mPolicyLevel == level) { 886 return false; 887 } 888 switch (level) { 889 case POLICY_LEVEL_FULL: 890 case POLICY_LEVEL_ADAPTIVE: 891 case POLICY_LEVEL_OFF: 892 mPolicyLevel = level; 893 break; 894 default: 895 Slog.wtf(TAG, "setPolicyLevel invalid level given: " + level); 896 return false; 897 } 898 updatePolicyDependenciesLocked(); 899 return true; 900 } 901 } 902 903 /** @return true if the current policy changed and the policy level is ADAPTIVE. */ setAdaptivePolicyLocked(Policy p)904 boolean setAdaptivePolicyLocked(Policy p) { 905 if (p == null) { 906 Slog.wtf(TAG, "setAdaptivePolicy given null policy"); 907 return false; 908 } 909 if (mAdaptivePolicy.equals(p)) { 910 return false; 911 } 912 913 mAdaptivePolicy = p; 914 if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE) { 915 updatePolicyDependenciesLocked(); 916 return true; 917 } 918 return false; 919 } 920 921 /** @return true if the current policy changed and the policy level is ADAPTIVE. */ resetAdaptivePolicyLocked()922 boolean resetAdaptivePolicyLocked() { 923 return setAdaptivePolicyLocked(mDefaultAdaptivePolicy); 924 } 925 getCurrentPolicyLocked()926 private Policy getCurrentPolicyLocked() { 927 switch (mPolicyLevel) { 928 case POLICY_LEVEL_FULL: 929 return mFullPolicy; 930 case POLICY_LEVEL_ADAPTIVE: 931 return mAdaptivePolicy; 932 case POLICY_LEVEL_OFF: 933 default: 934 return OFF_POLICY; 935 } 936 } 937 getGpsMode()938 public int getGpsMode() { 939 synchronized (mLock) { 940 return getCurrentPolicyLocked().locationMode; 941 } 942 } 943 getFileValues(boolean interactive)944 public ArrayMap<String, String> getFileValues(boolean interactive) { 945 synchronized (mLock) { 946 return interactive ? getCurrentPolicyLocked().filesForInteractive 947 : getCurrentPolicyLocked().filesForNoninteractive; 948 } 949 } 950 isLaunchBoostDisabled()951 public boolean isLaunchBoostDisabled() { 952 synchronized (mLock) { 953 return getCurrentPolicyLocked().disableLaunchBoost; 954 } 955 } 956 shouldAdvertiseIsEnabled()957 boolean shouldAdvertiseIsEnabled() { 958 synchronized (mLock) { 959 return getCurrentPolicyLocked().advertiseIsEnabled; 960 } 961 } 962 toEventLogString()963 public String toEventLogString() { 964 synchronized (mLock) { 965 return mEventLogKeys; 966 } 967 } 968 dump(PrintWriter pw)969 public void dump(PrintWriter pw) { 970 synchronized (mLock) { 971 pw.println(); 972 mBatterySavingStats.dump(pw, ""); 973 974 pw.println(); 975 pw.println("Battery saver policy (*NOTE* they only apply when battery saver is ON):"); 976 pw.println(" Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS); 977 pw.println(" value: " + mSettings); 978 pw.println(" Settings: " + mDeviceSpecificSettingsSource); 979 pw.println(" value: " + mDeviceSpecificSettings); 980 981 pw.println(" Adaptive Settings: " + Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS); 982 pw.println(" value: " + mAdaptiveSettings); 983 pw.println(" Adaptive Device Specific Settings: " 984 + Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS); 985 pw.println(" value: " + mAdaptiveDeviceSpecificSettings); 986 987 pw.println(" mAccessibilityEnabled=" + mAccessibilityEnabled); 988 pw.println(" mPolicyLevel=" + mPolicyLevel); 989 990 dumpPolicyLocked(pw, " ", "full", mFullPolicy); 991 dumpPolicyLocked(pw, " ", "default adaptive", mDefaultAdaptivePolicy); 992 dumpPolicyLocked(pw, " ", "current adaptive", mAdaptivePolicy); 993 } 994 } 995 dumpPolicyLocked(PrintWriter pw, String indent, String label, Policy p)996 private void dumpPolicyLocked(PrintWriter pw, String indent, String label, Policy p) { 997 pw.println(); 998 pw.print(indent); 999 pw.println("Policy '" + label + "'"); 1000 pw.print(indent); 1001 pw.println(" " + KEY_ADVERTISE_IS_ENABLED + "=" + p.advertiseIsEnabled); 1002 pw.print(indent); 1003 pw.println(" " + KEY_VIBRATION_DISABLED + ":config=" + p.disableVibration); 1004 // mDisableVibrationEffective is based on the currently selected policy 1005 pw.print(indent); 1006 pw.println(" " + KEY_VIBRATION_DISABLED + ":effective=" + (p.disableVibration 1007 && !mAccessibilityEnabled)); 1008 pw.print(indent); 1009 pw.println(" " + KEY_ANIMATION_DISABLED + "=" + p.disableAnimation); 1010 pw.print(indent); 1011 pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + p.deferFullBackup); 1012 pw.print(indent); 1013 pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + p.deferKeyValueBackup); 1014 pw.print(indent); 1015 pw.println(" " + KEY_ACTIVATE_FIREWALL_DISABLED + "=" + !p.enableFirewall); 1016 pw.print(indent); 1017 pw.println(" " + KEY_ACTIVATE_DATASAVER_DISABLED + "=" + !p.enableDataSaver); 1018 pw.print(indent); 1019 pw.println(" " + KEY_LAUNCH_BOOST_DISABLED + "=" + p.disableLaunchBoost); 1020 pw.println( 1021 " " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + !p.enableAdjustBrightness); 1022 pw.print(indent); 1023 pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + p.adjustBrightnessFactor); 1024 pw.print(indent); 1025 pw.println(" " + KEY_GPS_MODE + "=" + p.locationMode); 1026 pw.print(indent); 1027 pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + p.forceAllAppsStandby); 1028 pw.print(indent); 1029 pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + p.forceBackgroundCheck); 1030 pw.println( 1031 " " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + p.disableOptionalSensors); 1032 pw.print(indent); 1033 pw.println(" " + KEY_AOD_DISABLED + "=" + p.disableAod); 1034 pw.print(indent); 1035 pw.println(" " + KEY_SOUNDTRIGGER_DISABLED + "=" + p.disableSoundTrigger); 1036 pw.print(indent); 1037 pw.println(" " + KEY_QUICK_DOZE_ENABLED + "=" + p.enableQuickDoze); 1038 pw.print(indent); 1039 pw.println(" " + KEY_ENABLE_NIGHT_MODE + "=" + p.enableNightMode); 1040 1041 pw.print(" Interactive File values:\n"); 1042 dumpMap(pw, " ", p.filesForInteractive); 1043 pw.println(); 1044 1045 pw.print(" Noninteractive File values:\n"); 1046 dumpMap(pw, " ", p.filesForNoninteractive); 1047 } 1048 dumpMap(PrintWriter pw, String prefix, ArrayMap<String, String> map)1049 private void dumpMap(PrintWriter pw, String prefix, ArrayMap<String, String> map) { 1050 if (map == null) { 1051 return; 1052 } 1053 final int size = map.size(); 1054 for (int i = 0; i < size; i++) { 1055 pw.print(prefix); 1056 pw.print(map.keyAt(i)); 1057 pw.print(": '"); 1058 pw.print(map.valueAt(i)); 1059 pw.println("'"); 1060 } 1061 } 1062 1063 @VisibleForTesting setAccessibilityEnabledForTest(boolean enabled)1064 public void setAccessibilityEnabledForTest(boolean enabled) { 1065 synchronized (mLock) { 1066 mAccessibilityEnabled = enabled; 1067 updatePolicyDependenciesLocked(); 1068 } 1069 } 1070 } 1071