BatterySaverPolicy.java revision a50bf78fdeecedb646a5bb34fe42343c68e25c96
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;
32import android.view.accessibility.AccessibilityManager;
33
34import com.android.internal.R;
35import com.android.internal.annotations.GuardedBy;
36import com.android.internal.annotations.VisibleForTesting;
37import com.android.internal.os.BackgroundThread;
38import com.android.internal.util.ConcurrentUtils;
39import com.android.server.power.batterysaver.BatterySavingStats;
40import com.android.server.power.batterysaver.CpuFrequencies;
41
42import java.io.PrintWriter;
43import java.util.ArrayList;
44import 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 */
55public 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 {
268        void onBatterySaverPolicyChanged(BatterySaverPolicy policy);
269    }
270
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     */
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
306    public void addListener(BatterySaverPolicyListener listener) {
307        synchronized (mLock) {
308            mListeners.add(listener);
309        }
310    }
311
312    @VisibleForTesting
313    String getGlobalSetting(String key) {
314        return Settings.Global.getString(mContentResolver, key);
315    }
316
317    @VisibleForTesting
318    int getDeviceSpecificConfigResId() {
319        return R.string.config_batterySaverDeviceSpecificConfig;
320    }
321
322    @Override
323    public void onChange(boolean selfChange, Uri uri) {
324        refreshSettings();
325    }
326
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
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     */
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
512    public int getGpsMode() {
513        synchronized (mLock) {
514            return mGpsMode;
515        }
516    }
517
518    public ArrayMap<String, String> getFileValues(boolean interactive) {
519        synchronized (mLock) {
520            return interactive ? mFilesForInteractive : mFilesForNoninteractive;
521        }
522    }
523
524    public boolean isLaunchBoostDisabled() {
525        synchronized (mLock) {
526            return mLaunchBoostDisabled;
527        }
528    }
529
530    public String toEventLogString() {
531        synchronized (mLock) {
532            return mEventLogKeys;
533        }
534    }
535
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
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
592    public void setAccessibilityEnabledForTest(boolean enabled) {
593        synchronized (mLock) {
594            mAccessibilityEnabled = enabled;
595        }
596    }
597}
598