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