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