From 55bc49860b4ed5a91e31b055a2c50e5fba094ce7 Mon Sep 17 00:00:00 2001 From: Daniel Hsieh Date: Mon, 17 Jan 2022 05:03:41 +0000 Subject: [PATCH] Refactor SettingsContentObserver and add it to follow typing feature. Refactor SettingsContentObserver and rename it to AccessibilitySettingsContentObserver. Besides, we register it to observe follow typing feature preference value. The reasons behind refactor: 1. We change callback signature due to the consistency for register it by preference key, not by Uri. 2. We refactor the default preference key to a seperate method. Since the default value is related to accessibility, we rename it with accessibility prefix. 3. We can register different callback for difference collections of preference keys. Default preference keys: They existed in the previous constructor. 1. Settings.Secure.ACCESSIBILITY_ENABLED 2. Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES Bug: 194668976 Test: make RunSettingsRoboTests ROBOTEST_FILTER= AccessibilitySettingsTest AccessibilitySettingsContentObserverTest AccessibilityShortcutPreferenceFragmentTest MagnificationFollowTypingPreferenceControllerTest ToggleFeaturePreferenceFragmentTest ToggleScreenMagnificationPreferenceFragmentTest Change-Id: Iafd27e044ebe2536ae7ae55c1c80af54f7f0f822 --- .../accessibility/AccessibilitySettings.java | 12 +- .../AccessibilitySettingsContentObserver.java | 132 +++++++++++++++ ...cessibilityShortcutPreferenceFragment.java | 15 +- ...ationFollowTypingPreferenceController.java | 10 ++ .../SettingsContentObserver.java | 55 ------ ...ccessibilityServicePreferenceFragment.java | 50 +++--- ...oggleColorInversionPreferenceFragment.java | 25 ++- .../ToggleDaltonizerPreferenceFragment.java | 27 ++- .../ToggleFeaturePreferenceFragment.java | 24 +-- ...eReduceBrightColorsPreferenceFragment.java | 24 ++- ...ScreenMagnificationPreferenceFragment.java | 29 +++- ...essibilitySettingsContentObserverTest.java | 160 ++++++++++++++++++ .../AccessibilitySettingsTest.java | 7 +- ...nFollowTypingPreferenceControllerTest.java | 11 ++ .../ToggleFeaturePreferenceFragmentTest.java | 38 ++++- ...enMagnificationPreferenceFragmentTest.java | 38 ++++- 16 files changed, 489 insertions(+), 168 deletions(-) create mode 100644 src/com/android/settings/accessibility/AccessibilitySettingsContentObserver.java delete mode 100644 src/com/android/settings/accessibility/SettingsContentObserver.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsContentObserverTest.java diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java index 8e8c7e45039..c08e6690ac4 100644 --- a/src/com/android/settings/accessibility/AccessibilitySettings.java +++ b/src/com/android/settings/accessibility/AccessibilitySettings.java @@ -30,7 +30,6 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.graphics.Color; import android.graphics.drawable.Drawable; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; @@ -147,7 +146,7 @@ public class AccessibilitySettings extends DashboardFragment { }; @VisibleForTesting - final SettingsContentObserver mSettingsContentObserver; + final AccessibilitySettingsContentObserver mSettingsContentObserver; private final Map mCategoryToPrefCategoryMap = new ArrayMap<>(); @@ -171,12 +170,9 @@ public class AccessibilitySettings extends DashboardFragment { // Observe changes from accessibility selection menu shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); - mSettingsContentObserver = new SettingsContentObserver(mHandler, shortcutFeatureKeys) { - @Override - public void onChange(boolean selfChange, Uri uri) { - onContentChanged(); - } - }; + mSettingsContentObserver = new AccessibilitySettingsContentObserver(mHandler); + mSettingsContentObserver.registerKeysToObserverCallback(shortcutFeatureKeys, + key -> onContentChanged()); } @Override diff --git a/src/com/android/settings/accessibility/AccessibilitySettingsContentObserver.java b/src/com/android/settings/accessibility/AccessibilitySettingsContentObserver.java new file mode 100644 index 00000000000..d2ca75437b3 --- /dev/null +++ b/src/com/android/settings/accessibility/AccessibilitySettingsContentObserver.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.accessibility; + +import android.content.ContentResolver; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.provider.Settings; +import android.util.Log; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class AccessibilitySettingsContentObserver extends ContentObserver { + + private static final String TAG = "AccessibilitySettingsContentObserver"; + + public interface ContentObserverCallback { + void onChange(String key); + } + + // Key: Preference key's uri, Value: Preference key + private final Map mUriToKey = new HashMap<>(2); + + // Key: Collection of preference keys, Value: onChange callback for keys + private final Map, ContentObserverCallback> mUrisToCallback = new HashMap<>(); + + AccessibilitySettingsContentObserver(Handler handler) { + super(handler); + + // default key to be observed + addDefaultKeysToMap(); + } + + public void register(ContentResolver contentResolver) { + for (Uri uri : mUriToKey.keySet()) { + contentResolver.registerContentObserver(uri, false, this); + } + } + + public void unregister(ContentResolver contentResolver) { + contentResolver.unregisterContentObserver(this); + } + + private void addDefaultKeysToMap() { + addKeyToMap(Settings.Secure.ACCESSIBILITY_ENABLED); + addKeyToMap(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + } + + private boolean isDefaultKey(String key) { + return Settings.Secure.ACCESSIBILITY_ENABLED.equals(key) + || Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(key); + } + + private void addKeyToMap(String key) { + mUriToKey.put(Settings.Secure.getUriFor(key), key); + } + + /** + * {@link ContentObserverCallback} is added to {@link ContentObserver} to handle the + * onChange event triggered by the key collection of {@code keysToObserve} and the default + * keys. + * + * Note: The following key are default to be observed. + * {@link Settings.Secure.ACCESSIBILITY_ENABLED} + * {@link Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES} + * + * @param keysToObserve A collection of keys which are going to be observed. + * @param observerCallback A callback which is used to handle the onChange event triggered + * by the key collection of {@code keysToObserve}. + */ + public void registerKeysToObserverCallback(List keysToObserve, + ContentObserverCallback observerCallback) { + + for (String key: keysToObserve) { + addKeyToMap(key); + } + + mUrisToCallback.put(keysToObserve, observerCallback); + } + + /** + * {@link ContentObserverCallback} is added to {@link ContentObserver} to handle the + * onChange event triggered by the default keys. + * + * Note: The following key are default to be observed. + * {@link Settings.Secure.ACCESSIBILITY_ENABLED} + * {@link Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES} + * + * @param observerCallback A callback which is used to handle the onChange event triggered + * * by the key collection of {@code keysToObserve}. + */ + public void registerObserverCallback(ContentObserverCallback observerCallback) { + mUrisToCallback.put(Collections.emptyList(), observerCallback); + } + + @Override + public final void onChange(boolean selfChange, Uri uri) { + + final String key = mUriToKey.get(uri); + + if (key == null) { + Log.w(TAG, "AccessibilitySettingsContentObserver can not find the key for " + + "uri: " + uri); + return; + } + + for (List keys : mUrisToCallback.keySet()) { + final boolean isDefaultKey = isDefaultKey(key); + if (isDefaultKey || keys.contains(key)) { + mUrisToCallback.get(keys).onChange(key); + } + } + } +} diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java index 22f037b1f4b..115f44f0c14 100644 --- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java @@ -25,7 +25,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.icu.text.CaseMap; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; @@ -64,7 +63,7 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF protected ShortcutPreference mShortcutPreference; private AccessibilityManager.TouchExplorationStateChangeListener mTouchExplorationStateChangeListener; - private SettingsContentObserver mSettingsContentObserver; + private AccessibilitySettingsContentObserver mSettingsContentObserver; private CheckBox mSoftwareTypeCheckBox; private CheckBox mHardwareTypeCheckBox; @@ -98,13 +97,11 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF final List shortcutFeatureKeys = new ArrayList<>(); shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); - mSettingsContentObserver = new SettingsContentObserver(new Handler(), shortcutFeatureKeys) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateShortcutPreferenceData(); - updateShortcutPreference(); - } - }; + mSettingsContentObserver = new AccessibilitySettingsContentObserver(new Handler()); + mSettingsContentObserver.registerKeysToObserverCallback(shortcutFeatureKeys, key -> { + updateShortcutPreferenceData(); + updateShortcutPreference(); + }); } @Override diff --git a/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceController.java b/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceController.java index 8757fdfaa43..a758276afbe 100644 --- a/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceController.java @@ -35,6 +35,8 @@ import com.android.settings.core.TogglePreferenceController; public class MagnificationFollowTypingPreferenceController extends TogglePreferenceController implements LifecycleObserver { + private static final String TAG = + MagnificationFollowTypingPreferenceController.class.getSimpleName(); static final String PREF_KEY = "magnification_follow_typing"; private SwitchPreference mFollowTypingPreference; @@ -75,6 +77,14 @@ public class MagnificationFollowTypingPreferenceController extends TogglePrefere // TODO(b/186731461): Remove it when this controller is used in DashBoardFragment only. @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) void onResume() { + updateState(); + } + + /** + * Updates the state of preference components which has been displayed by + * {@link MagnificationFollowTypingPreferenceController#displayPreference}. + */ + void updateState() { updateState(mFollowTypingPreference); } } diff --git a/src/com/android/settings/accessibility/SettingsContentObserver.java b/src/com/android/settings/accessibility/SettingsContentObserver.java deleted file mode 100644 index de67f6c4e3d..00000000000 --- a/src/com/android/settings/accessibility/SettingsContentObserver.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.accessibility; - -import android.content.ContentResolver; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.provider.Settings; - -import java.util.ArrayList; -import java.util.List; - -abstract class SettingsContentObserver extends ContentObserver { - private final List mKeysToObserve = new ArrayList<>(2); - - public SettingsContentObserver(Handler handler) { - super(handler); - mKeysToObserve.add(Settings.Secure.ACCESSIBILITY_ENABLED); - mKeysToObserve.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); - } - - public SettingsContentObserver(Handler handler, List keysToObserve) { - this(handler); - mKeysToObserve.addAll(keysToObserve); - } - - public void register(ContentResolver contentResolver) { - for (int i = 0; i < mKeysToObserve.size(); i++) { - contentResolver.registerContentObserver( - Settings.Secure.getUriFor(mKeysToObserve.get(i)), false, this); - } - } - - public void unregister(ContentResolver contentResolver) { - contentResolver.unregisterContentObserver(this); - } - - @Override - public abstract void onChange(boolean selfChange, Uri uri); -} diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java index 04b5347346e..0632d3f84bb 100644 --- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java @@ -35,7 +35,6 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; @@ -65,15 +64,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends private static final String EMPTY_STRING = ""; - private final SettingsContentObserver mSettingsContentObserver = - new SettingsContentObserver(new Handler()) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateSwitchBarToggleSwitch(); - } - }; - - private Dialog mDialog; + private Dialog mWarningDialog; private BroadcastReceiver mPackageRemovedReceiver; private boolean mDisabledStateLogged = false; private long mStartTimeMillsForLogging = 0; @@ -108,6 +99,13 @@ public class ToggleAccessibilityServicePreferenceFragment extends } } + @Override + protected void registerKeysToObserverCallback( + AccessibilitySettingsContentObserver contentObserver) { + super.registerKeysToObserverCallback(contentObserver); + contentObserver.registerObserverCallback(key -> updateSwitchBarToggleSwitch()); + } + @Override public void onStart() { super.onStart(); @@ -123,7 +121,11 @@ public class ToggleAccessibilityServicePreferenceFragment extends public void onResume() { super.onResume(); updateSwitchBarToggleSwitch(); - mSettingsContentObserver.register(getContentResolver()); + } + + @Override + public void onPause() { + super.onPause(); } @Override @@ -172,7 +174,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends if (info == null) { return null; } - mDialog = AccessibilityServiceWarning + mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromEnableToggleClicked, this::onDialogButtonFromUninstallClicked); @@ -183,7 +185,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends if (info == null) { return null; } - mDialog = AccessibilityServiceWarning + mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromShortcutToggleClicked, this::onDialogButtonFromUninstallClicked); @@ -194,7 +196,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends if (info == null) { return null; } - mDialog = AccessibilityServiceWarning + mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromShortcutClicked, this::onDialogButtonFromUninstallClicked); @@ -205,16 +207,16 @@ public class ToggleAccessibilityServicePreferenceFragment extends if (info == null) { return null; } - mDialog = AccessibilityServiceWarning + mWarningDialog = AccessibilityServiceWarning .createDisableDialog(getPrefContext(), info, this::onDialogButtonFromDisableToggleClicked); break; } default: { - mDialog = super.onCreateDialog(dialogId); + mWarningDialog = super.onCreateDialog(dialogId); } } - return mDialog; + return mWarningDialog; } @Override @@ -402,7 +404,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends } private void onDialogButtonFromUninstallClicked() { - mDialog.dismiss(); + mWarningDialog.dismiss(); final Intent uninstallIntent = createUninstallPackageActivityIntent(); if (uninstallIntent == null) { return; @@ -436,12 +438,12 @@ public class ToggleAccessibilityServicePreferenceFragment extends mIsDialogShown.set(false); showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL); } - mDialog.dismiss(); + mWarningDialog.dismiss(); } private void onDenyButtonFromEnableToggleClicked() { handleConfirmServiceEnabled(/* confirmed= */ false); - mDialog.dismiss(); + mWarningDialog.dismiss(); } void onDialogButtonFromShortcutToggleClicked(View view) { @@ -465,7 +467,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends mIsDialogShown.set(false); showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL); - mDialog.dismiss(); + mWarningDialog.dismiss(); mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); } @@ -473,7 +475,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends private void onDenyButtonFromShortcutToggleClicked() { mShortcutPreference.setChecked(false); - mDialog.dismiss(); + mWarningDialog.dismiss(); } void onDialogButtonFromShortcutClicked(View view) { @@ -491,11 +493,11 @@ public class ToggleAccessibilityServicePreferenceFragment extends mIsDialogShown.set(false); showPopupDialog(DialogEnums.EDIT_SHORTCUT); - mDialog.dismiss(); + mWarningDialog.dismiss(); } private void onDenyButtonFromShortcutClicked() { - mDialog.dismiss(); + mWarningDialog.dismiss(); } private boolean onPreferenceClick(boolean isChecked) { diff --git a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java index 419514f4ed4..e65c9c5b2bb 100644 --- a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java @@ -25,7 +25,6 @@ import android.app.settings.SettingsEnums; import android.content.ContentResolver; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; @@ -41,8 +40,6 @@ import java.util.List; public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePreferenceFragment { private static final String ENABLED = Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED; - private final Handler mHandler = new Handler(); - private SettingsContentObserver mSettingsContentObserver; @Override public int getMetricsCategory() { @@ -86,20 +83,22 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere .authority(getPrefContext().getPackageName()) .appendPath(String.valueOf(R.raw.accessibility_color_inversion_banner)) .build(); - final List enableServiceFeatureKeys = new ArrayList<>(/* initialCapacity= */ 1); - enableServiceFeatureKeys.add(ENABLED); - mSettingsContentObserver = new SettingsContentObserver(mHandler, enableServiceFeatureKeys) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateSwitchBarToggleSwitch(); - } - }; - final View view = super.onCreateView(inflater, container, savedInstanceState); updateFooterPreference(); return view; } + @Override + protected void registerKeysToObserverCallback( + AccessibilitySettingsContentObserver contentObserver) { + super.registerKeysToObserverCallback(contentObserver); + + final List enableServiceFeatureKeys = new ArrayList<>(/* initialCapacity= */ 1); + enableServiceFeatureKeys.add(ENABLED); + contentObserver.registerKeysToObserverCallback(enableServiceFeatureKeys, + key -> updateSwitchBarToggleSwitch()); + } + private void updateFooterPreference() { final String title = getPrefContext().getString( R.string.accessibility_color_inversion_about_title); @@ -114,12 +113,10 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere public void onResume() { super.onResume(); updateSwitchBarToggleSwitch(); - mSettingsContentObserver.register(getContentResolver()); } @Override public void onPause() { - mSettingsContentObserver.unregister(getContentResolver()); super.onPause(); } diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java index c9449d24109..f0a4f0a151e 100644 --- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java @@ -24,9 +24,7 @@ import static com.android.settings.accessibility.AccessibilityUtil.State.ON; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.res.Resources; -import android.net.Uri; import android.os.Bundle; -import android.os.Handler; import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; @@ -53,8 +51,6 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe private static final String KEY_PREVIEW = "daltonizer_preview"; private static final String KEY_CATEGORY_MODE = "daltonizer_mode_category"; private static final List sControllers = new ArrayList<>(); - private final Handler mHandler = new Handler(); - private SettingsContentObserver mSettingsContentObserver; private static List buildPreferenceControllers(Context context, Lifecycle lifecycle) { @@ -84,20 +80,22 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe mComponentName = DALTONIZER_COMPONENT_NAME; mPackageName = getText(R.string.accessibility_display_daltonizer_preference_title); mHtmlDescription = getText(R.string.accessibility_display_daltonizer_preference_subtitle); - final List enableServiceFeatureKeys = new ArrayList<>(/* initialCapacity= */ 1); - enableServiceFeatureKeys.add(ENABLED); - mSettingsContentObserver = new SettingsContentObserver(mHandler, enableServiceFeatureKeys) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateSwitchBarToggleSwitch(); - } - }; - final View view = super.onCreateView(inflater, container, savedInstanceState); updateFooterPreference(); return view; } + @Override + protected void registerKeysToObserverCallback( + AccessibilitySettingsContentObserver contentObserver) { + super.registerKeysToObserverCallback(contentObserver); + + final List enableServiceFeatureKeys = new ArrayList<>(/* initialCapacity= */ 1); + enableServiceFeatureKeys.add(ENABLED); + contentObserver.registerKeysToObserverCallback(enableServiceFeatureKeys, + key -> updateSwitchBarToggleSwitch()); + } + private void updateFooterPreference() { final String title = getPrefContext() .getString(R.string.accessibility_daltonizer_about_title); @@ -123,8 +121,6 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe public void onResume() { super.onResume(); updateSwitchBarToggleSwitch(); - mSettingsContentObserver.register(getContentResolver()); - for (AbstractPreferenceController controller : buildPreferenceControllers(getPrefContext(), getSettingsLifecycle())) { ((DaltonizerRadioButtonPreferenceController) controller).setOnChangeListener(this); @@ -135,7 +131,6 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe @Override public void onPause() { - mSettingsContentObserver.unregister(getContentResolver()); for (AbstractPreferenceController controller : buildPreferenceControllers(getPrefContext(), getSettingsLifecycle())) { ((DaltonizerRadioButtonPreferenceController) controller).setOnChangeListener(null); diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index 233b7ee2997..cba5d83150a 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -99,7 +99,7 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference protected static final String KEY_ANIMATED_IMAGE = "animated_image"; private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener; - private SettingsContentObserver mSettingsContentObserver; + private AccessibilitySettingsContentObserver mSettingsContentObserver; private CheckBox mSoftwareTypeCheckBox; private CheckBox mHardwareTypeCheckBox; @@ -143,17 +143,21 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference setPreferenceScreen(preferenceScreen); } - final List shortcutFeatureKeys = getFeatureSettingsKeys(); - mSettingsContentObserver = new SettingsContentObserver(new Handler(), shortcutFeatureKeys) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateShortcutPreferenceData(); - updateShortcutPreference(); - } - }; + mSettingsContentObserver = new AccessibilitySettingsContentObserver(new Handler()); + registerKeysToObserverCallback(mSettingsContentObserver); } - protected List getFeatureSettingsKeys() { + protected void registerKeysToObserverCallback( + AccessibilitySettingsContentObserver contentObserver) { + final List shortcutFeatureKeys = getShortcutFeatureSettingsKeys(); + + contentObserver.registerKeysToObserverCallback(shortcutFeatureKeys, key -> { + updateShortcutPreferenceData(); + updateShortcutPreference(); + }); + } + + protected List getShortcutFeatureSettingsKeys() { final List shortcutFeatureKeys = new ArrayList<>(); shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); diff --git a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java index 81bd45a0541..feb41a19463 100644 --- a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java @@ -22,7 +22,6 @@ import android.content.Context; import android.hardware.display.ColorDisplayManager; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; @@ -50,8 +49,6 @@ public class ToggleReduceBrightColorsPreferenceFragment extends ToggleFeaturePre private static final String KEY_INTENSITY = "rbc_intensity"; private static final String KEY_PERSIST = "rbc_persist"; - private final Handler mHandler = new Handler(); - private SettingsContentObserver mSettingsContentObserver; private ReduceBrightColorsIntensityPreferenceController mRbcIntensityPreferenceController; private ReduceBrightColorsPersistencePreferenceController mRbcPersistencePreferenceController; private ColorDisplayManager mColorDisplayManager; @@ -67,20 +64,12 @@ public class ToggleReduceBrightColorsPreferenceFragment extends ToggleFeaturePre mComponentName = AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME; mPackageName = getText(R.string.reduce_bright_colors_preference_title); mHtmlDescription = getText(R.string.reduce_bright_colors_preference_subtitle); - final List enableServiceFeatureKeys = new ArrayList<>(/* initialCapacity= */ 1); - enableServiceFeatureKeys.add(REDUCE_BRIGHT_COLORS_ACTIVATED_KEY); mRbcIntensityPreferenceController = new ReduceBrightColorsIntensityPreferenceController(getContext(), KEY_INTENSITY); mRbcPersistencePreferenceController = new ReduceBrightColorsPersistencePreferenceController(getContext(), KEY_PERSIST); mRbcIntensityPreferenceController.displayPreference(getPreferenceScreen()); mRbcPersistencePreferenceController.displayPreference(getPreferenceScreen()); - mSettingsContentObserver = new SettingsContentObserver(mHandler, enableServiceFeatureKeys) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateSwitchBarToggleSwitch(); - } - }; mColorDisplayManager = getContext().getSystemService(ColorDisplayManager.class); final View view = super.onCreateView(inflater, container, savedInstanceState); // Parent sets the title when creating the view, so set it after calling super @@ -90,6 +79,17 @@ public class ToggleReduceBrightColorsPreferenceFragment extends ToggleFeaturePre return view; } + @Override + protected void registerKeysToObserverCallback( + AccessibilitySettingsContentObserver contentObserver) { + super.registerKeysToObserverCallback(contentObserver); + + final List enableServiceFeatureKeys = new ArrayList<>(/* initialCapacity= */ 1); + enableServiceFeatureKeys.add(REDUCE_BRIGHT_COLORS_ACTIVATED_KEY); + contentObserver.registerKeysToObserverCallback(enableServiceFeatureKeys, + key -> updateSwitchBarToggleSwitch()); + } + private void updateGeneralCategoryOrder() { final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY); final SeekBarPreference intensity = findPreference(KEY_INTENSITY); @@ -117,12 +117,10 @@ public class ToggleReduceBrightColorsPreferenceFragment extends ToggleFeaturePre public void onResume() { super.onResume(); updateSwitchBarToggleSwitch(); - mSettingsContentObserver.register(getContentResolver()); } @Override public void onPause() { - mSettingsContentObserver.unregister(getContentResolver()); super.onPause(); } diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index d1e9b565805..08679180184 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -75,6 +75,7 @@ public class ToggleScreenMagnificationPreferenceFragment extends new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); private DialogCreatable mDialogDelegate; + private MagnificationFollowTypingPreferenceController mFollowTypingPreferenceController; @Override public void onCreate(Bundle savedInstanceState) { @@ -187,11 +188,10 @@ public class ToggleScreenMagnificationPreferenceFragment extends MagnificationFollowTypingPreferenceController.PREF_KEY); generalCategory.addPreference(followingTypingSwitchPreference); - final MagnificationFollowTypingPreferenceController followTypingPreferenceController = - new MagnificationFollowTypingPreferenceController(getContext(), - MagnificationFollowTypingPreferenceController.PREF_KEY); - getSettingsLifecycle().addObserver(followTypingPreferenceController); - followTypingPreferenceController.displayPreference(getPreferenceScreen()); + mFollowTypingPreferenceController = new MagnificationFollowTypingPreferenceController( + getContext(), MagnificationFollowTypingPreferenceController.PREF_KEY); + getSettingsLifecycle().addObserver(mFollowTypingPreferenceController); + mFollowTypingPreferenceController.displayPreference(getPreferenceScreen()); } @Override @@ -293,8 +293,23 @@ public class ToggleScreenMagnificationPreferenceFragment extends } @Override - protected List getFeatureSettingsKeys() { - final List shortcutKeys = super.getFeatureSettingsKeys(); + protected void registerKeysToObserverCallback( + AccessibilitySettingsContentObserver contentObserver) { + super.registerKeysToObserverCallback(contentObserver); + + final List followingTypingKeys = new ArrayList<>(); + followingTypingKeys.add(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED); + contentObserver.registerKeysToObserverCallback(followingTypingKeys, + key -> updateFollowTypingState()); + } + + private void updateFollowTypingState() { + mFollowTypingPreferenceController.updateState(); + } + + @Override + protected List getShortcutFeatureSettingsKeys() { + final List shortcutKeys = super.getShortcutFeatureSettingsKeys(); shortcutKeys.add(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); return shortcutKeys; } diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsContentObserverTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsContentObserverTest.java new file mode 100644 index 00000000000..e23d2d798f8 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsContentObserverTest.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.accessibility; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowContentResolver; + +import java.util.Collection; +import java.util.List; + +/** Test for {@link AccessibilitySettingsContentObserver}. */ +@RunWith(RobolectricTestRunner.class) +public class AccessibilitySettingsContentObserverTest { + + private static final String SPECIFIC_KEY_A_1 = "SPECIFIC_KEY_A_1"; + private static final String SPECIFIC_KEY_A_2 = "SPECIFIC_KEY_A_2"; + private static final String SPECIFIC_KEY_B_1 = "SPECIFIC_KEY_B_1"; + + private final Context mContext = ApplicationProvider.getApplicationContext(); + private final AccessibilitySettingsContentObserver mObserver = + new AccessibilitySettingsContentObserver(new Handler()); + private final AccessibilitySettingsContentObserver.ContentObserverCallback mObserverCallbackA = + spy(new TestableContentObserverCallback()); + private final AccessibilitySettingsContentObserver.ContentObserverCallback mObserverCallbackB = + spy(new TestableContentObserverCallback()); + private final ContentResolver mContentResolver = mContext.getContentResolver(); + + @Test + public void register_shouldRegisterContentObserverForDefaultKeys() { + mObserver.register(mContentResolver); + + ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver); + assertObserverToUri(shadowContentResolver, + Settings.Secure.ACCESSIBILITY_ENABLED, mObserver); + assertObserverToUri(shadowContentResolver, + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, mObserver); + } + + @Test + public void unregister_shouldUnregisterContentObserver() { + mObserver.register(mContentResolver); + + mObserver.unregister(mContentResolver); + + ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver); + assertNotObserverToUri(shadowContentResolver, Settings.Secure.ACCESSIBILITY_ENABLED); + assertNotObserverToUri(shadowContentResolver, + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + } + + @Test + public void register_addSpecificKeys_shouldRegisterContentObserverForSpecificAndDefaultKeys() { + mObserver.registerKeysToObserverCallback(List.of(SPECIFIC_KEY_A_1), mObserverCallbackA); + + mObserver.register(mContentResolver); + + ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver); + assertObserverToUri(shadowContentResolver, + Settings.Secure.ACCESSIBILITY_ENABLED, mObserver); + assertObserverToUri(shadowContentResolver, + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, mObserver); + assertObserverToUri(shadowContentResolver, SPECIFIC_KEY_A_1, mObserver); + } + + @Test + public void onChange_shouldTriggerCallbackOnDefaultKey() { + mObserver.registerObserverCallback(mObserverCallbackA); + mObserver.register(mContentResolver); + + mObserver.onChange(/* selfChange= */ false, + Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_ENABLED)); + + verify(mObserverCallbackA).onChange(Settings.Secure.ACCESSIBILITY_ENABLED); + } + + @Test + public void onChange_registerSpecificKeys_shouldTriggerSpecificCallback() { + mObserver.registerKeysToObserverCallback( + List.of(SPECIFIC_KEY_A_1, SPECIFIC_KEY_A_2), mObserverCallbackA); + mObserver.register(mContentResolver); + + mObserver.onChange(/* selfChange= */ false, + Settings.Secure.getUriFor(SPECIFIC_KEY_A_2)); + + verify(mObserverCallbackA).onChange(SPECIFIC_KEY_A_2); + } + + @Test + public void onChange_registerSpecificKeys_withoutTriggerOtherCallback() { + mObserver.registerKeysToObserverCallback( + List.of(SPECIFIC_KEY_A_1, SPECIFIC_KEY_A_2), mObserverCallbackA); + mObserver.registerKeysToObserverCallback( + List.of(SPECIFIC_KEY_B_1), mObserverCallbackB); + mObserver.register(mContentResolver); + + mObserver.onChange(/* selfChange= */ false, + Settings.Secure.getUriFor(SPECIFIC_KEY_B_1)); + + verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_A_1); + verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_A_2); + verify(mObserverCallbackA, never()).onChange(SPECIFIC_KEY_B_1); + verify(mObserverCallbackB).onChange(SPECIFIC_KEY_B_1); + } + + @After + public void tearDown() { + mObserver.unregister(mContentResolver); + } + + private void assertNotObserverToUri(ShadowContentResolver resolver, String key) { + assertThat(resolver.getContentObservers(Settings.Secure.getUriFor(key))).isEmpty(); + } + + private void assertObserverToUri(ShadowContentResolver resolver, + String key, ContentObserver observer) { + Collection observers = + resolver.getContentObservers(Settings.Secure.getUriFor(key)); + assertThat(observers).contains(observer); + } + + private static class TestableContentObserverCallback implements + AccessibilitySettingsContentObserver.ContentObserverCallback { + @Override + public void onChange(String key) { + // do nothing + } + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java index d1c59f708c9..5843265656e 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java @@ -281,10 +281,10 @@ public class AccessibilitySettingsTest { verify(mContentResolver).registerContentObserver( eq(Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS)), anyBoolean(), - any(SettingsContentObserver.class)); + any(AccessibilitySettingsContentObserver.class)); verify(mContentResolver).registerContentObserver(eq(Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)), anyBoolean(), - any(SettingsContentObserver.class)); + any(AccessibilitySettingsContentObserver.class)); verify(mActivity, atLeast(1)).registerReceiver(any(PackageMonitor.class), captor.capture(), isNull(), any()); intentFilter = captor.getAllValues().get(/* first time */ 0); @@ -301,7 +301,8 @@ public class AccessibilitySettingsTest { mFragment.onDestroy(); - verify(mContentResolver).unregisterContentObserver(any(SettingsContentObserver.class)); + verify(mContentResolver).unregisterContentObserver( + any(AccessibilitySettingsContentObserver.class)); verify(mActivity).unregisterReceiver(any(PackageMonitor.class)); } diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceControllerTest.java index ccb66addd62..fd282a06932 100644 --- a/tests/robotests/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceControllerTest.java @@ -94,4 +94,15 @@ public class MagnificationFollowTypingPreferenceControllerTest { assertThat(mController.isChecked()).isFalse(); assertThat(mSwitchPreference.isChecked()).isFalse(); } + + @Test + public void updateState_disableFollowTyping_shouldReturnFalse() { + Settings.Secure.putInt(mContext.getContentResolver(), KEY_FOLLOW_TYPING, OFF); + + mController.updateState(); + + verify(mSwitchPreference).setChecked(false); + assertThat(mController.isChecked()).isFalse(); + assertThat(mSwitchPreference.isChecked()).isFalse(); + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java index c47a7935de5..4584b159b20 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java @@ -20,6 +20,8 @@ import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -27,6 +29,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; @@ -75,12 +78,16 @@ public class ToggleFeaturePreferenceFragmentTest { Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE; private TestToggleFeaturePreferenceFragment mFragment; - private PreferenceScreen mScreen; - private Context mContext = ApplicationProvider.getApplicationContext(); + private final Context mContext = ApplicationProvider.getApplicationContext(); @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceManager mPreferenceManager; + @Mock + private FragmentActivity mActivity; + @Mock + private ContentResolver mContentResolver; + @Before public void setUpTestFragment() { MockitoAnnotations.initMocks(this); @@ -89,9 +96,11 @@ public class ToggleFeaturePreferenceFragmentTest { when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); when(mFragment.getContext()).thenReturn(mContext); - mScreen = spy(new PreferenceScreen(mContext, null)); - when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager); - doReturn(mScreen).when(mFragment).getPreferenceScreen(); + when(mFragment.getActivity()).thenReturn(mActivity); + when(mActivity.getContentResolver()).thenReturn(mContentResolver); + final PreferenceScreen screen = spy(new PreferenceScreen(mContext, null)); + when(screen.getPreferenceManager()).thenReturn(mPreferenceManager); + doReturn(screen).when(mFragment).getPreferenceScreen(); } @Test @@ -103,6 +112,25 @@ public class ToggleFeaturePreferenceFragmentTest { verify(mFragment).addPreferencesFromResource(R.xml.placeholder_prefs); } + @Test + @Config(shadows = {ShadowFragment.class}) + public void onResume_haveRegisterToSpecificUris() { + mFragment.onAttach(mContext); + mFragment.onCreate(Bundle.EMPTY); + + mFragment.onResume(); + + verify(mContentResolver).registerContentObserver( + eq(Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS)), + eq(false), + any(AccessibilitySettingsContentObserver.class)); + verify(mContentResolver).registerContentObserver( + eq(Settings.Secure.getUriFor( + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)), + eq(false), + any(AccessibilitySettingsContentObserver.class)); + } + @Test public void updateShortcutPreferenceData_assignDefaultValueToVariable() { mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME; diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java index 10495c5f00a..8500e61a9d8 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java @@ -25,14 +25,15 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; @@ -63,8 +64,8 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; @@ -96,17 +97,22 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { private Context mContext; private Resources mResources; + @Mock + private FragmentActivity mActivity; + @Mock + private ContentResolver mContentResolver; + @Before public void setUpTestFragment() { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); - final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class); mFragment = spy(new TestToggleScreenMagnificationPreferenceFragment(mContext)); mResources = spy(mContext.getResources()); when(mContext.getResources()).thenReturn(mResources); when(mFragment.getContext().getResources()).thenReturn(mResources); - doReturn(activity).when(mFragment).getActivity(); + when(mFragment.getActivity()).thenReturn(mActivity); + when(mActivity.getContentResolver()).thenReturn(mContentResolver); } @Ignore("Ignore it since a NPE is happened in ShadowWindowManagerGlobal. (Ref. b/214161063)") @@ -142,6 +148,30 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { assertThat(switchPreference.isChecked()).isFalse(); } + @Test + @Config(shadows = {ShadowFragment.class}) + public void onResume_haveRegisterToSpecificUris() { + mFragment.onAttach(mContext); + mFragment.onCreate(Bundle.EMPTY); + + mFragment.onResume(); + + verify(mContentResolver).registerContentObserver( + eq(Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS)), + eq(false), + any(AccessibilitySettingsContentObserver.class)); + verify(mContentResolver).registerContentObserver( + eq(Settings.Secure.getUriFor( + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)), + eq(false), + any(AccessibilitySettingsContentObserver.class)); + verify(mContentResolver).registerContentObserver( + eq(Settings.Secure.getUriFor( + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED)), + eq(false), + any(AccessibilitySettingsContentObserver.class)); + } + @Test public void hasValueInSettings_putValue_hasValue() { setMagnificationTripleTapEnabled(/* enabled= */ true);