BatterySaverPolicy.java revision 85dd0852fe506bcf800bea99aeb7af401e1485c4
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 */ 16package com.android.server.power; 17 18import android.content.ContentResolver; 19import android.content.Context; 20import android.database.ContentObserver; 21import android.net.Uri; 22import android.os.Handler; 23import android.os.PowerManager.ServiceType; 24import android.os.PowerSaveState; 25import android.provider.Settings; 26import android.provider.Settings.Global; 27import android.text.TextUtils; 28import android.util.ArrayMap; 29import android.util.KeyValueListParser; 30import android.util.Slog; 31 32import com.android.internal.R; 33import com.android.internal.annotations.GuardedBy; 34import com.android.internal.annotations.VisibleForTesting; 35import com.android.server.power.batterysaver.CpuFrequencies; 36 37import java.io.PrintWriter; 38import java.util.ArrayList; 39import java.util.List; 40 41/** 42 * Class to decide whether to turn on battery saver mode for specific service 43 * 44 * Test: 45 atest ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java 46 */ 47public class BatterySaverPolicy extends ContentObserver { 48 private static final String TAG = "BatterySaverPolicy"; 49 50 public static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE. 51 52 // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode. 53 public static final int GPS_MODE_NO_CHANGE = 0; 54 // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode 55 // is enabled and the screen is off. 56 public static final int GPS_MODE_DISABLED_WHEN_SCREEN_OFF = 1; 57 // Secure setting for GPS behavior when battery saver mode is on. 58 public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode"; 59 60 private static final String KEY_GPS_MODE = "gps_mode"; 61 private static final String KEY_VIBRATION_DISABLED = "vibration_disabled"; 62 private static final String KEY_ANIMATION_DISABLED = "animation_disabled"; 63 private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled"; 64 private static final String KEY_FIREWALL_DISABLED = "firewall_disabled"; 65 private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled"; 66 private static final String KEY_DATASAVER_DISABLED = "datasaver_disabled"; 67 private static final String KEY_LAUNCH_BOOST_DISABLED = "launch_boost_disabled"; 68 private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor"; 69 private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred"; 70 private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred"; 71 private static final String KEY_FORCE_ALL_APPS_STANDBY = "force_all_apps_standby"; 72 private static final String KEY_FORCE_BACKGROUND_CHECK = "force_background_check"; 73 private static final String KEY_OPTIONAL_SENSORS_DISABLED = "optional_sensors_disabled"; 74 75 private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i"; 76 private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n"; 77 78 private final Object mLock = new Object(); 79 80 @GuardedBy("mLock") 81 private String mSettings; 82 83 @GuardedBy("mLock") 84 private String mDeviceSpecificSettings; 85 86 @GuardedBy("mLock") 87 private String mDeviceSpecificSettingsSource; // For dump() only. 88 89 /** 90 * A short string describing which battery saver is now enabled, which we dump in the eventlog. 91 */ 92 @GuardedBy("mLock") 93 private String mEventLogKeys; 94 95 /** 96 * {@code true} if vibration is disabled in battery saver mode. 97 * 98 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 99 * @see #KEY_VIBRATION_DISABLED 100 */ 101 @GuardedBy("mLock") 102 private boolean mVibrationDisabled; 103 104 /** 105 * {@code true} if animation is disabled in battery saver mode. 106 * 107 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 108 * @see #KEY_ANIMATION_DISABLED 109 */ 110 @GuardedBy("mLock") 111 private boolean mAnimationDisabled; 112 113 /** 114 * {@code true} if sound trigger is disabled in battery saver mode 115 * in battery saver mode. 116 * 117 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 118 * @see #KEY_SOUNDTRIGGER_DISABLED 119 */ 120 @GuardedBy("mLock") 121 private boolean mSoundTriggerDisabled; 122 123 /** 124 * {@code true} if full backup is deferred in battery saver mode. 125 * 126 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 127 * @see #KEY_FULLBACKUP_DEFERRED 128 */ 129 @GuardedBy("mLock") 130 private boolean mFullBackupDeferred; 131 132 /** 133 * {@code true} if key value backup is deferred in battery saver mode. 134 * 135 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 136 * @see #KEY_KEYVALUE_DEFERRED 137 */ 138 @GuardedBy("mLock") 139 private boolean mKeyValueBackupDeferred; 140 141 /** 142 * {@code true} if network policy firewall is disabled in battery saver mode. 143 * 144 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 145 * @see #KEY_FIREWALL_DISABLED 146 */ 147 @GuardedBy("mLock") 148 private boolean mFireWallDisabled; 149 150 /** 151 * {@code true} if adjust brightness is disabled in battery saver mode. 152 * 153 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 154 * @see #KEY_ADJUST_BRIGHTNESS_DISABLED 155 */ 156 @GuardedBy("mLock") 157 private boolean mAdjustBrightnessDisabled; 158 159 /** 160 * {@code true} if data saver is disabled in battery saver mode. 161 * 162 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 163 * @see #KEY_DATASAVER_DISABLED 164 */ 165 @GuardedBy("mLock") 166 private boolean mDataSaverDisabled; 167 168 /** 169 * {@code true} if launch boost should be disabled on battery saver. 170 */ 171 @GuardedBy("mLock") 172 private boolean mLaunchBoostDisabled; 173 174 /** 175 * This is the flag to decide the gps mode in battery saver mode. 176 * 177 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 178 * @see #KEY_GPS_MODE 179 */ 180 @GuardedBy("mLock") 181 private int mGpsMode; 182 183 /** 184 * This is the flag to decide the how much to adjust the screen brightness. This is 185 * the float value from 0 to 1 where 1 means don't change brightness. 186 * 187 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 188 * @see #KEY_ADJUST_BRIGHTNESS_FACTOR 189 */ 190 @GuardedBy("mLock") 191 private float mAdjustBrightnessFactor; 192 193 /** 194 * Whether to put all apps in the stand-by mode. 195 */ 196 @GuardedBy("mLock") 197 private boolean mForceAllAppsStandby; 198 199 /** 200 * Whether to put all apps in the stand-by mode. 201 */ 202 @GuardedBy("mLock") 203 private boolean mForceBackgroundCheck; 204 205 /** 206 * Weather to show non-essential sensors (e.g. edge sensors) or not. 207 */ 208 @GuardedBy("mLock") 209 private boolean mOptionalSensorsDisabled; 210 211 @GuardedBy("mLock") 212 private Context mContext; 213 214 @GuardedBy("mLock") 215 private ContentResolver mContentResolver; 216 217 @GuardedBy("mLock") 218 private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>(); 219 220 /** 221 * List of [Filename -> content] that should be written when battery saver is activated 222 * and the device is interactive. 223 * 224 * We use this to change the max CPU frequencies. 225 */ 226 @GuardedBy("mLock") 227 private ArrayMap<String, String> mFilesForInteractive; 228 229 /** 230 * List of [Filename -> content] that should be written when battery saver is activated 231 * and the device is non-interactive. 232 * 233 * We use this to change the max CPU frequencies. 234 */ 235 @GuardedBy("mLock") 236 private ArrayMap<String, String> mFilesForNoninteractive; 237 238 public interface BatterySaverPolicyListener { 239 void onBatterySaverPolicyChanged(BatterySaverPolicy policy); 240 } 241 242 public BatterySaverPolicy(Handler handler) { 243 super(handler); 244 } 245 246 public void systemReady(Context context) { 247 synchronized (mLock) { 248 mContext = context; 249 mContentResolver = context.getContentResolver(); 250 251 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 252 Settings.Global.BATTERY_SAVER_CONSTANTS), false, this); 253 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 254 Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this); 255 } 256 onChange(true, null); 257 } 258 259 public void addListener(BatterySaverPolicyListener listener) { 260 synchronized (mLock) { 261 mListeners.add(listener); 262 } 263 } 264 265 @VisibleForTesting 266 String getGlobalSetting(String key) { 267 final ContentResolver cr; 268 synchronized (mLock) { 269 cr = mContentResolver; 270 } 271 return Settings.Global.getString(cr, key); 272 } 273 274 @VisibleForTesting 275 int getDeviceSpecificConfigResId() { 276 return R.string.config_batterySaverDeviceSpecificConfig; 277 } 278 279 @Override 280 public void onChange(boolean selfChange, Uri uri) { 281 final BatterySaverPolicyListener[] listeners; 282 synchronized (mLock) { 283 // Load the non-device-specific setting. 284 final String setting = getGlobalSetting(Settings.Global.BATTERY_SAVER_CONSTANTS); 285 286 // Load the device specific setting. 287 // We first check the global setting, and if it's empty or the string "null" is set, 288 // use the default value from config.xml. 289 String deviceSpecificSetting = getGlobalSetting( 290 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS); 291 mDeviceSpecificSettingsSource = 292 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS; 293 294 if (TextUtils.isEmpty(deviceSpecificSetting) || "null".equals(deviceSpecificSetting)) { 295 deviceSpecificSetting = 296 mContext.getString(getDeviceSpecificConfigResId()); 297 mDeviceSpecificSettingsSource = "(overlay)"; 298 } 299 300 // Update. 301 updateConstantsLocked(setting, deviceSpecificSetting); 302 303 listeners = mListeners.toArray(new BatterySaverPolicyListener[mListeners.size()]); 304 } 305 306 // Notify the listeners. 307 for (BatterySaverPolicyListener listener : listeners) { 308 listener.onBatterySaverPolicyChanged(this); 309 } 310 } 311 312 @VisibleForTesting 313 void updateConstantsLocked(final String setting, final String deviceSpecificSetting) { 314 mSettings = setting; 315 mDeviceSpecificSettings = deviceSpecificSetting; 316 317 if (DEBUG) { 318 Slog.i(TAG, "mSettings=" + mSettings); 319 Slog.i(TAG, "mDeviceSpecificSettings=" + mDeviceSpecificSettings); 320 } 321 322 final KeyValueListParser parser = new KeyValueListParser(','); 323 324 // Non-device-specific parameters. 325 try { 326 parser.setString(setting); 327 } catch (IllegalArgumentException e) { 328 Slog.wtf(TAG, "Bad battery saver constants: " + setting); 329 } 330 331 mVibrationDisabled = parser.getBoolean(KEY_VIBRATION_DISABLED, true); 332 mAnimationDisabled = parser.getBoolean(KEY_ANIMATION_DISABLED, true); 333 mSoundTriggerDisabled = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, true); 334 mFullBackupDeferred = parser.getBoolean(KEY_FULLBACKUP_DEFERRED, true); 335 mKeyValueBackupDeferred = parser.getBoolean(KEY_KEYVALUE_DEFERRED, true); 336 mFireWallDisabled = parser.getBoolean(KEY_FIREWALL_DISABLED, false); 337 mAdjustBrightnessDisabled = parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, false); 338 mAdjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f); 339 mDataSaverDisabled = parser.getBoolean(KEY_DATASAVER_DISABLED, true); 340 mLaunchBoostDisabled = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED, true); 341 mForceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY, true); 342 mForceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, true); 343 mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true); 344 345 // Get default value from Settings.Secure 346 final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE, 347 GPS_MODE_NO_CHANGE); 348 mGpsMode = parser.getInt(KEY_GPS_MODE, defaultGpsMode); 349 350 // Non-device-specific parameters. 351 try { 352 parser.setString(deviceSpecificSetting); 353 } catch (IllegalArgumentException e) { 354 Slog.wtf(TAG, "Bad device specific battery saver constants: " 355 + deviceSpecificSetting); 356 } 357 358 mFilesForInteractive = (new CpuFrequencies()).parseString( 359 parser.getString(KEY_CPU_FREQ_INTERACTIVE, "")).toSysFileMap(); 360 361 mFilesForNoninteractive = (new CpuFrequencies()).parseString( 362 parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "")).toSysFileMap(); 363 364 final StringBuilder sb = new StringBuilder(); 365 366 if (mForceAllAppsStandby) sb.append("A"); 367 if (mForceBackgroundCheck) sb.append("B"); 368 369 if (mVibrationDisabled) sb.append("v"); 370 if (mAnimationDisabled) sb.append("a"); 371 if (mSoundTriggerDisabled) sb.append("s"); 372 if (mFullBackupDeferred) sb.append("F"); 373 if (mKeyValueBackupDeferred) sb.append("K"); 374 if (!mFireWallDisabled) sb.append("f"); 375 if (!mDataSaverDisabled) sb.append("d"); 376 if (!mAdjustBrightnessDisabled) sb.append("b"); 377 378 if (mLaunchBoostDisabled) sb.append("l"); 379 if (mOptionalSensorsDisabled) sb.append("S"); 380 381 sb.append(mGpsMode); 382 383 mEventLogKeys = sb.toString(); 384 } 385 386 /** 387 * Get the {@link PowerSaveState} based on {@paramref type} and {@paramref realMode}. 388 * The result will have {@link PowerSaveState#batterySaverEnabled} and some other 389 * parameters when necessary. 390 * 391 * @param type type of the service, one of {@link ServiceType} 392 * @param realMode whether the battery saver is on by default 393 * @return State data that contains battery saver data 394 */ 395 public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) { 396 synchronized (mLock) { 397 final PowerSaveState.Builder builder = new PowerSaveState.Builder() 398 .setGlobalBatterySaverEnabled(realMode); 399 if (!realMode) { 400 return builder.setBatterySaverEnabled(realMode) 401 .build(); 402 } 403 switch (type) { 404 case ServiceType.GPS: 405 return builder.setBatterySaverEnabled(realMode) 406 .setGpsMode(mGpsMode) 407 .build(); 408 case ServiceType.ANIMATION: 409 return builder.setBatterySaverEnabled(mAnimationDisabled) 410 .build(); 411 case ServiceType.FULL_BACKUP: 412 return builder.setBatterySaverEnabled(mFullBackupDeferred) 413 .build(); 414 case ServiceType.KEYVALUE_BACKUP: 415 return builder.setBatterySaverEnabled(mKeyValueBackupDeferred) 416 .build(); 417 case ServiceType.NETWORK_FIREWALL: 418 return builder.setBatterySaverEnabled(!mFireWallDisabled) 419 .build(); 420 case ServiceType.SCREEN_BRIGHTNESS: 421 return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled) 422 .setBrightnessFactor(mAdjustBrightnessFactor) 423 .build(); 424 case ServiceType.DATA_SAVER: 425 return builder.setBatterySaverEnabled(!mDataSaverDisabled) 426 .build(); 427 case ServiceType.SOUND: 428 return builder.setBatterySaverEnabled(mSoundTriggerDisabled) 429 .build(); 430 case ServiceType.VIBRATION: 431 return builder.setBatterySaverEnabled(mVibrationDisabled) 432 .build(); 433 case ServiceType.FORCE_ALL_APPS_STANDBY: 434 return builder.setBatterySaverEnabled(mForceAllAppsStandby) 435 .build(); 436 case ServiceType.FORCE_BACKGROUND_CHECK: 437 return builder.setBatterySaverEnabled(mForceBackgroundCheck) 438 .build(); 439 case ServiceType.OPTIONAL_SENSORS: 440 return builder.setBatterySaverEnabled(mOptionalSensorsDisabled) 441 .build(); 442 default: 443 return builder.setBatterySaverEnabled(realMode) 444 .build(); 445 } 446 } 447 } 448 449 public ArrayMap<String, String> getFileValues(boolean interactive) { 450 synchronized (mLock) { 451 return interactive ? mFilesForInteractive : mFilesForNoninteractive; 452 } 453 } 454 455 public boolean isLaunchBoostDisabled() { 456 synchronized (mLock) { 457 return mLaunchBoostDisabled; 458 } 459 } 460 461 public String toEventLogString() { 462 synchronized (mLock) { 463 return mEventLogKeys; 464 } 465 } 466 467 public void dump(PrintWriter pw) { 468 synchronized (mLock) { 469 pw.println(); 470 pw.println("Battery saver policy"); 471 pw.println(" Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS); 472 pw.println(" value: " + mSettings); 473 pw.println(" Settings: " + mDeviceSpecificSettingsSource); 474 pw.println(" value: " + mDeviceSpecificSettings); 475 476 pw.println(); 477 pw.println(" " + KEY_VIBRATION_DISABLED + "=" + mVibrationDisabled); 478 pw.println(" " + KEY_ANIMATION_DISABLED + "=" + mAnimationDisabled); 479 pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred); 480 pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred); 481 pw.println(" " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled); 482 pw.println(" " + KEY_DATASAVER_DISABLED + "=" + mDataSaverDisabled); 483 pw.println(" " + KEY_LAUNCH_BOOST_DISABLED + "=" + mLaunchBoostDisabled); 484 pw.println(" " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled); 485 pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor); 486 pw.println(" " + KEY_GPS_MODE + "=" + mGpsMode); 487 pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + mForceAllAppsStandby); 488 pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + mForceBackgroundCheck); 489 pw.println(" " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + mOptionalSensorsDisabled); 490 pw.println(); 491 492 pw.print(" Interactive File values:\n"); 493 dumpMap(pw, " ", mFilesForInteractive); 494 pw.println(); 495 496 pw.print(" Noninteractive File values:\n"); 497 dumpMap(pw, " ", mFilesForNoninteractive); 498 pw.println(); 499 } 500 } 501 502 private void dumpMap(PrintWriter pw, String prefix, ArrayMap<String, String> map) { 503 if (map == null) { 504 return; 505 } 506 final int size = map.size(); 507 for (int i = 0; i < size; i++) { 508 pw.print(prefix); 509 pw.print(map.keyAt(i)); 510 pw.print(": '"); 511 pw.print(map.valueAt(i)); 512 pw.println("'"); 513 } 514 } 515} 516