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