BatterySaverPolicy.java revision 97e5a71838f07721a6622e4de837ffbbdf9ba7f7
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 * {@code true} if vibration is disabled in battery saver mode. 91 * 92 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 93 * @see #KEY_VIBRATION_DISABLED 94 */ 95 @GuardedBy("mLock") 96 private boolean mVibrationDisabled; 97 98 /** 99 * {@code true} if animation is disabled in battery saver mode. 100 * 101 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 102 * @see #KEY_ANIMATION_DISABLED 103 */ 104 @GuardedBy("mLock") 105 private boolean mAnimationDisabled; 106 107 /** 108 * {@code true} if sound trigger is disabled in battery saver mode 109 * in battery saver mode. 110 * 111 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 112 * @see #KEY_SOUNDTRIGGER_DISABLED 113 */ 114 @GuardedBy("mLock") 115 private boolean mSoundTriggerDisabled; 116 117 /** 118 * {@code true} if full backup is deferred in battery saver mode. 119 * 120 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 121 * @see #KEY_FULLBACKUP_DEFERRED 122 */ 123 @GuardedBy("mLock") 124 private boolean mFullBackupDeferred; 125 126 /** 127 * {@code true} if key value backup is deferred in battery saver mode. 128 * 129 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 130 * @see #KEY_KEYVALUE_DEFERRED 131 */ 132 @GuardedBy("mLock") 133 private boolean mKeyValueBackupDeferred; 134 135 /** 136 * {@code true} if network policy firewall is disabled in battery saver mode. 137 * 138 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 139 * @see #KEY_FIREWALL_DISABLED 140 */ 141 @GuardedBy("mLock") 142 private boolean mFireWallDisabled; 143 144 /** 145 * {@code true} if adjust brightness is disabled in battery saver mode. 146 * 147 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 148 * @see #KEY_ADJUST_BRIGHTNESS_DISABLED 149 */ 150 @GuardedBy("mLock") 151 private boolean mAdjustBrightnessDisabled; 152 153 /** 154 * {@code true} if data saver is disabled in battery saver mode. 155 * 156 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 157 * @see #KEY_DATASAVER_DISABLED 158 */ 159 @GuardedBy("mLock") 160 private boolean mDataSaverDisabled; 161 162 /** 163 * {@code true} if launch boost should be disabled on battery saver. 164 */ 165 @GuardedBy("mLock") 166 private boolean mLaunchBoostDisabled; 167 168 /** 169 * This is the flag to decide the gps mode in battery saver mode. 170 * 171 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 172 * @see #KEY_GPS_MODE 173 */ 174 @GuardedBy("mLock") 175 private int mGpsMode; 176 177 /** 178 * This is the flag to decide the how much to adjust the screen brightness. This is 179 * the float value from 0 to 1 where 1 means don't change brightness. 180 * 181 * @see Settings.Global#BATTERY_SAVER_CONSTANTS 182 * @see #KEY_ADJUST_BRIGHTNESS_FACTOR 183 */ 184 @GuardedBy("mLock") 185 private float mAdjustBrightnessFactor; 186 187 /** 188 * Whether to put all apps in the stand-by mode. 189 */ 190 @GuardedBy("mLock") 191 private boolean mForceAllAppsStandby; 192 193 /** 194 * Whether to put all apps in the stand-by mode. 195 */ 196 @GuardedBy("mLock") 197 private boolean mForceBackgroundCheck; 198 199 /** 200 * Weather to show non-essential sensors (e.g. edge sensors) or not. 201 */ 202 @GuardedBy("mLock") 203 private boolean mOptionalSensorsDisabled; 204 205 @GuardedBy("mLock") 206 private Context mContext; 207 208 @GuardedBy("mLock") 209 private ContentResolver mContentResolver; 210 211 @GuardedBy("mLock") 212 private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>(); 213 214 /** 215 * List of [Filename -> content] that should be written when battery saver is activated 216 * and the device is interactive. 217 * 218 * We use this to change the max CPU frequencies. 219 */ 220 @GuardedBy("mLock") 221 private ArrayMap<String, String> mFilesForInteractive; 222 223 /** 224 * List of [Filename -> content] that should be written when battery saver is activated 225 * and the device is non-interactive. 226 * 227 * We use this to change the max CPU frequencies. 228 */ 229 @GuardedBy("mLock") 230 private ArrayMap<String, String> mFilesForNoninteractive; 231 232 public interface BatterySaverPolicyListener { 233 void onBatterySaverPolicyChanged(BatterySaverPolicy policy); 234 } 235 236 public BatterySaverPolicy(Handler handler) { 237 super(handler); 238 } 239 240 public void systemReady(Context context) { 241 synchronized (mLock) { 242 mContext = context; 243 mContentResolver = context.getContentResolver(); 244 245 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 246 Settings.Global.BATTERY_SAVER_CONSTANTS), false, this); 247 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 248 Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this); 249 } 250 onChange(true, null); 251 } 252 253 public void addListener(BatterySaverPolicyListener listener) { 254 synchronized (mLock) { 255 mListeners.add(listener); 256 } 257 } 258 259 @VisibleForTesting 260 String getGlobalSetting(String key) { 261 final ContentResolver cr; 262 synchronized (mLock) { 263 cr = mContentResolver; 264 } 265 return Settings.Global.getString(cr, key); 266 } 267 268 @VisibleForTesting 269 int getDeviceSpecificConfigResId() { 270 return R.string.config_batterySaverDeviceSpecificConfig; 271 } 272 273 @Override 274 public void onChange(boolean selfChange, Uri uri) { 275 final BatterySaverPolicyListener[] listeners; 276 synchronized (mLock) { 277 // Load the non-device-specific setting. 278 final String setting = getGlobalSetting(Settings.Global.BATTERY_SAVER_CONSTANTS); 279 280 // Load the device specific setting. 281 // We first check the global setting, and if it's empty or the string "null" is set, 282 // use the default value from config.xml. 283 String deviceSpecificSetting = getGlobalSetting( 284 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS); 285 mDeviceSpecificSettingsSource = 286 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS; 287 288 if (TextUtils.isEmpty(deviceSpecificSetting) || "null".equals(deviceSpecificSetting)) { 289 deviceSpecificSetting = 290 mContext.getString(getDeviceSpecificConfigResId()); 291 mDeviceSpecificSettingsSource = "(overlay)"; 292 } 293 294 // Update. 295 updateConstantsLocked(setting, deviceSpecificSetting); 296 297 listeners = mListeners.toArray(new BatterySaverPolicyListener[mListeners.size()]); 298 } 299 300 // Notify the listeners. 301 for (BatterySaverPolicyListener listener : listeners) { 302 listener.onBatterySaverPolicyChanged(this); 303 } 304 } 305 306 @VisibleForTesting 307 void updateConstantsLocked(final String setting, final String deviceSpecificSetting) { 308 mSettings = setting; 309 mDeviceSpecificSettings = deviceSpecificSetting; 310 311 if (DEBUG) { 312 Slog.i(TAG, "mSettings=" + mSettings); 313 Slog.i(TAG, "mDeviceSpecificSettings=" + mDeviceSpecificSettings); 314 } 315 316 final KeyValueListParser parser = new KeyValueListParser(','); 317 318 // Non-device-specific parameters. 319 try { 320 parser.setString(setting); 321 } catch (IllegalArgumentException e) { 322 Slog.wtf(TAG, "Bad battery saver constants: " + setting); 323 } 324 325 mVibrationDisabled = parser.getBoolean(KEY_VIBRATION_DISABLED, true); 326 mAnimationDisabled = parser.getBoolean(KEY_ANIMATION_DISABLED, true); 327 mSoundTriggerDisabled = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, true); 328 mFullBackupDeferred = parser.getBoolean(KEY_FULLBACKUP_DEFERRED, true); 329 mKeyValueBackupDeferred = parser.getBoolean(KEY_KEYVALUE_DEFERRED, true); 330 mFireWallDisabled = parser.getBoolean(KEY_FIREWALL_DISABLED, false); 331 mAdjustBrightnessDisabled = parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, true); 332 mAdjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f); 333 mDataSaverDisabled = parser.getBoolean(KEY_DATASAVER_DISABLED, true); 334 mLaunchBoostDisabled = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED, true); 335 mForceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY, true); 336 mForceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, true); 337 mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true); 338 339 // Get default value from Settings.Secure 340 final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE, 341 GPS_MODE_NO_CHANGE); 342 mGpsMode = parser.getInt(KEY_GPS_MODE, defaultGpsMode); 343 344 // Non-device-specific parameters. 345 try { 346 parser.setString(deviceSpecificSetting); 347 } catch (IllegalArgumentException e) { 348 Slog.wtf(TAG, "Bad device specific battery saver constants: " 349 + deviceSpecificSetting); 350 } 351 352 mFilesForInteractive = (new CpuFrequencies()).parseString( 353 parser.getString(KEY_CPU_FREQ_INTERACTIVE, "")).toSysFileMap(); 354 355 mFilesForNoninteractive = (new CpuFrequencies()).parseString( 356 parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "")).toSysFileMap(); 357 } 358 359 /** 360 * Get the {@link PowerSaveState} based on {@paramref type} and {@paramref realMode}. 361 * The result will have {@link PowerSaveState#batterySaverEnabled} and some other 362 * parameters when necessary. 363 * 364 * @param type type of the service, one of {@link ServiceType} 365 * @param realMode whether the battery saver is on by default 366 * @return State data that contains battery saver data 367 */ 368 public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) { 369 synchronized (mLock) { 370 final PowerSaveState.Builder builder = new PowerSaveState.Builder() 371 .setGlobalBatterySaverEnabled(realMode); 372 if (!realMode) { 373 return builder.setBatterySaverEnabled(realMode) 374 .build(); 375 } 376 switch (type) { 377 case ServiceType.GPS: 378 return builder.setBatterySaverEnabled(realMode) 379 .setGpsMode(mGpsMode) 380 .build(); 381 case ServiceType.ANIMATION: 382 return builder.setBatterySaverEnabled(mAnimationDisabled) 383 .build(); 384 case ServiceType.FULL_BACKUP: 385 return builder.setBatterySaverEnabled(mFullBackupDeferred) 386 .build(); 387 case ServiceType.KEYVALUE_BACKUP: 388 return builder.setBatterySaverEnabled(mKeyValueBackupDeferred) 389 .build(); 390 case ServiceType.NETWORK_FIREWALL: 391 return builder.setBatterySaverEnabled(!mFireWallDisabled) 392 .build(); 393 case ServiceType.SCREEN_BRIGHTNESS: 394 return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled) 395 .setBrightnessFactor(mAdjustBrightnessFactor) 396 .build(); 397 case ServiceType.DATA_SAVER: 398 return builder.setBatterySaverEnabled(!mDataSaverDisabled) 399 .build(); 400 case ServiceType.SOUND: 401 return builder.setBatterySaverEnabled(mSoundTriggerDisabled) 402 .build(); 403 case ServiceType.VIBRATION: 404 return builder.setBatterySaverEnabled(mVibrationDisabled) 405 .build(); 406 case ServiceType.FORCE_ALL_APPS_STANDBY: 407 return builder.setBatterySaverEnabled(mForceAllAppsStandby) 408 .build(); 409 case ServiceType.FORCE_BACKGROUND_CHECK: 410 return builder.setBatterySaverEnabled(mForceBackgroundCheck) 411 .build(); 412 case ServiceType.OPTIONAL_SENSORS: 413 return builder.setBatterySaverEnabled(mOptionalSensorsDisabled) 414 .build(); 415 default: 416 return builder.setBatterySaverEnabled(realMode) 417 .build(); 418 } 419 } 420 } 421 422 public ArrayMap<String, String> getFileValues(boolean interactive) { 423 synchronized (mLock) { 424 return interactive ? mFilesForInteractive : mFilesForNoninteractive; 425 } 426 } 427 428 public boolean isLaunchBoostDisabled() { 429 synchronized (mLock) { 430 return mLaunchBoostDisabled; 431 } 432 } 433 434 public void dump(PrintWriter pw) { 435 synchronized (mLock) { 436 pw.println(); 437 pw.println("Battery saver policy"); 438 pw.println(" Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS); 439 pw.println(" value: " + mSettings); 440 pw.println(" Settings: " + mDeviceSpecificSettingsSource); 441 pw.println(" value: " + mDeviceSpecificSettings); 442 443 pw.println(); 444 pw.println(" " + KEY_VIBRATION_DISABLED + "=" + mVibrationDisabled); 445 pw.println(" " + KEY_ANIMATION_DISABLED + "=" + mAnimationDisabled); 446 pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred); 447 pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred); 448 pw.println(" " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled); 449 pw.println(" " + KEY_DATASAVER_DISABLED + "=" + mDataSaverDisabled); 450 pw.println(" " + KEY_LAUNCH_BOOST_DISABLED + "=" + mLaunchBoostDisabled); 451 pw.println(" " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled); 452 pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor); 453 pw.println(" " + KEY_GPS_MODE + "=" + mGpsMode); 454 pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + mForceAllAppsStandby); 455 pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + mForceBackgroundCheck); 456 pw.println(" " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + mOptionalSensorsDisabled); 457 pw.println(); 458 459 pw.print(" Interactive File values:\n"); 460 dumpMap(pw, " ", mFilesForInteractive); 461 pw.println(); 462 463 pw.print(" Noninteractive File values:\n"); 464 dumpMap(pw, " ", mFilesForNoninteractive); 465 pw.println(); 466 } 467 } 468 469 private void dumpMap(PrintWriter pw, String prefix, ArrayMap<String, String> map) { 470 if (map == null) { 471 return; 472 } 473 final int size = map.size(); 474 for (int i = 0; i < size; i++) { 475 pw.print(prefix); 476 pw.print(map.keyAt(i)); 477 pw.print(": '"); 478 pw.print(map.valueAt(i)); 479 pw.println("'"); 480 } 481 } 482} 483