diff --git a/res/xml/accessibility_autoclick_settings.xml b/res/xml/accessibility_autoclick_settings.xml index 943bc67b478..7a199285bb7 100644 --- a/res/xml/accessibility_autoclick_settings.xml +++ b/res/xml/accessibility_autoclick_settings.xml @@ -21,50 +21,52 @@ + android:title="@string/accessibility_autoclick_intro_text"/> + settings:lottie_rawRes="@drawable/accessibility_dwell"/> + android:title="@string/accessibility_autoclick_default_title" + settings:controller="com.android.settings.accessibility.ToggleAutoclickPreferenceController"/> + android:summary="@string/accessibility_autoclick_short_summary" + settings:controller="com.android.settings.accessibility.ToggleAutoclickPreferenceController"/> + android:summary="@string/accessibility_autoclick_medium_summary" + settings:controller="com.android.settings.accessibility.ToggleAutoclickPreferenceController"/> + android:summary="@string/accessibility_autoclick_long_summary" + settings:controller="com.android.settings.accessibility.ToggleAutoclickPreferenceController"/> + android:title="@string/accessibility_autoclick_custom_title" + settings:controller="com.android.settings.accessibility.ToggleAutoclickPreferenceController"/> + settings:controller="com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController"/> diff --git a/src/com/android/settings/accessibility/AutoclickPreferenceController.java b/src/com/android/settings/accessibility/AutoclickPreferenceController.java index b354aa6f494..5e6bc57256a 100644 --- a/src/com/android/settings/accessibility/AutoclickPreferenceController.java +++ b/src/com/android/settings/accessibility/AutoclickPreferenceController.java @@ -16,6 +16,9 @@ package com.android.settings.accessibility; +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + import android.content.Context; import android.provider.Settings; import android.view.accessibility.AccessibilityManager; @@ -23,8 +26,19 @@ import android.view.accessibility.AccessibilityManager; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +/** Preference controller for autoclick (dwell timing). */ public class AutoclickPreferenceController extends BasePreferenceController { + /** + * Resource ids from which autoclick preference summaries should be derived. The strings have + * placeholder for integer delay value. + */ + private static final int[] AUTOCLICK_PREFERENCE_SUMMARIES = { + R.plurals.accessibilty_autoclick_preference_subtitle_short_delay, + R.plurals.accessibilty_autoclick_preference_subtitle_medium_delay, + R.plurals.accessibilty_autoclick_preference_subtitle_long_delay + }; + public AutoclickPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); } @@ -37,14 +51,29 @@ public class AutoclickPreferenceController extends BasePreferenceController { @Override public CharSequence getSummary() { final boolean enabled = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 0) == 1; + Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, OFF) == ON; if (!enabled) { return mContext.getResources().getText(R.string.accessibility_feature_state_off); } - final int delay = Settings.Secure.getInt(mContext.getContentResolver(), + final int delayMillis = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, AccessibilityManager.AUTOCLICK_DELAY_DEFAULT); - return ToggleAutoclickPreferenceFragment.getAutoclickPreferenceSummary( - mContext.getResources(), delay); + final int summaryIndex = getAutoclickPreferenceSummaryIndex(delayMillis); + return AutoclickUtils.getAutoclickDelaySummary(mContext.getResources(), + AUTOCLICK_PREFERENCE_SUMMARIES[summaryIndex], delayMillis); } -} \ No newline at end of file + + /** Finds index of the summary that should be used for the provided autoclick delay. */ + private int getAutoclickPreferenceSummaryIndex(int delay) { + if (delay <= AutoclickUtils.MIN_AUTOCLICK_DELAY_MS) { + return 0; + } + if (delay >= AutoclickUtils.MAX_AUTOCLICK_DELAY_MS) { + return AUTOCLICK_PREFERENCE_SUMMARIES.length - 1; + } + int delayRange = + AutoclickUtils.MAX_AUTOCLICK_DELAY_MS - AutoclickUtils.MIN_AUTOCLICK_DELAY_MS; + int rangeSize = (delayRange) / (AUTOCLICK_PREFERENCE_SUMMARIES.length - 1); + return (delay - AutoclickUtils.MIN_AUTOCLICK_DELAY_MS) / rangeSize; + } +} diff --git a/src/com/android/settings/accessibility/AutoclickUtils.java b/src/com/android/settings/accessibility/AutoclickUtils.java new file mode 100644 index 00000000000..cd7d662118f --- /dev/null +++ b/src/com/android/settings/accessibility/AutoclickUtils.java @@ -0,0 +1,78 @@ +/* + * 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 java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; +import android.annotation.PluralsRes; +import android.content.res.Resources; + +import java.lang.annotation.Retention; + +/** Provides utility methods related auto click. */ +public final class AutoclickUtils { + + /** Used for autoclick mode in the preferences editor. */ + static final String KEY_DELAY_MODE = "delay_mode"; + + /** Used for autoclick custom delay in the preferences editor. */ + static final String KEY_CUSTOM_DELAY_VALUE = "custom_delay_value"; + + /** Min allowed autoclick delay value. */ + static final int MIN_AUTOCLICK_DELAY_MS = 200; + + /** Max allowed autoclick delay value. */ + static final int MAX_AUTOCLICK_DELAY_MS = 1000; + + /** + * Allowed autoclick delay values are discrete. This is the difference between two allowed + * values. + */ + static final int AUTOCLICK_DELAY_STEP = 100; + + @Retention(SOURCE) + @IntDef({ + Quantity.ONE, + Quantity.FEW + }) + private @interface Quantity { + int ONE = 1; + int FEW = 3; + } + + /** + * Gets string that should be used for provided autoclick delay. + * + * @param resources Resources from which string should be retrieved. + * @param id The desired resource identifier, as generated by the aapt + * tool. This integer encodes the package, type, and resource + * entry. The value 0 is an invalid identifier. + * @param delayMillis Delay for whose value summary should be retrieved. + */ + public static CharSequence getAutoclickDelaySummary(Resources resources, + @PluralsRes int id, int delayMillis) { + final int quantity = (delayMillis == 1000) ? Quantity.ONE : Quantity.FEW; + final float delaySecond = (float) delayMillis / 1000; + // Only show integer when delay time is 1. + final String decimalFormat = (delaySecond == 1) ? "%.0f" : "%.1f"; + + return resources.getQuantityString(id, quantity, String.format(decimalFormat, delaySecond)); + } + + private AutoclickUtils(){} +} diff --git a/src/com/android/settings/accessibility/ToggleAutoclickCustomSeekbarController.java b/src/com/android/settings/accessibility/ToggleAutoclickCustomSeekbarController.java index 1a58b3968d2..372c6f54303 100644 --- a/src/com/android/settings/accessibility/ToggleAutoclickCustomSeekbarController.java +++ b/src/com/android/settings/accessibility/ToggleAutoclickCustomSeekbarController.java @@ -18,8 +18,11 @@ package com.android.settings.accessibility; import static android.content.Context.MODE_PRIVATE; -import static com.android.settings.accessibility.ToggleAutoclickPreferenceController.KEY_DELAY_MODE; -import static com.android.settings.accessibility.ToggleAutoclickPreferenceFragment.Quantity; +import static com.android.settings.accessibility.AutoclickUtils.AUTOCLICK_DELAY_STEP; +import static com.android.settings.accessibility.AutoclickUtils.KEY_CUSTOM_DELAY_VALUE; +import static com.android.settings.accessibility.AutoclickUtils.KEY_DELAY_MODE; +import static com.android.settings.accessibility.AutoclickUtils.MAX_AUTOCLICK_DELAY_MS; +import static com.android.settings.accessibility.AutoclickUtils.MIN_AUTOCLICK_DELAY_MS; import android.content.ContentResolver; import android.content.Context; @@ -35,36 +38,16 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; -import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnPause; -import com.android.settingslib.core.lifecycle.events.OnResume; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.widget.LayoutPreference; -/** - * Controller class that controls accessibility autoclick seekbar settings. - */ +/** Controller class that controls accessibility autoclick seekbar settings. */ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceController - implements LifecycleObserver, OnResume, OnPause, + implements LifecycleObserver, OnStart, OnStop, SharedPreferences.OnSharedPreferenceChangeListener { - private static final String CONTROL_AUTOCLICK_DELAY_SECURE = - Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY; - - @VisibleForTesting - static final String KEY_CUSTOM_DELAY_VALUE = "custom_delay_value"; - - // Min allowed autoclick delay value. - static final int MIN_AUTOCLICK_DELAY_MS = 200; - - // Max allowed autoclick delay value. - static final int MAX_AUTOCLICK_DELAY_MS = 1000; - - // Allowed autoclick delay values are discrete. - // This is the difference between two allowed values. - @VisibleForTesting - static final int AUTOCLICK_DELAY_STEP = 100; - private final SharedPreferences mSharedPreferences; private final ContentResolver mContentResolver; private ImageView mShorter; @@ -98,29 +81,20 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro mContentResolver = context.getContentResolver(); } - public ToggleAutoclickCustomSeekbarController(Context context, Lifecycle lifecycle, - String preferenceKey) { - this(context, preferenceKey); - - if (lifecycle != null) { - lifecycle.addObserver(this); - } - } - @Override public int getAvailabilityStatus() { return AVAILABLE; } @Override - public void onResume() { + public void onStart() { if (mSharedPreferences != null) { mSharedPreferences.registerOnSharedPreferenceChangeListener(this); } } @Override - public void onPause() { + public void onStop() { if (mSharedPreferences != null) { mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this); } @@ -132,7 +106,7 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro final LayoutPreference preference = screen.findPreference(getPreferenceKey()); if (isAvailable()) { - int delayMillis = getSharedPreferenceForDelayValue(); + final int delayMillis = getSharedPreferenceForDelayValue(); // Initialize seek bar preference. Sets seek bar size to the number of possible delay // values. mSeekBar = preference.findViewById(R.id.autoclick_delay); @@ -144,14 +118,10 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro mDelayLabel.setText(delayTimeToString(delayMillis)); mShorter = preference.findViewById(R.id.shorter); - mShorter.setOnClickListener(v -> { - minusDelayByImageView(); - }); + mShorter.setOnClickListener(v -> minusDelayByImageView()); mLonger = preference.findViewById(R.id.longer); - mLonger.setOnClickListener(v -> { - plusDelayByImageView(); - }); + mLonger.setOnClickListener(v -> plusDelayByImageView()); } } @@ -184,12 +154,9 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro return mSharedPreferences.getInt(KEY_CUSTOM_DELAY_VALUE, delayMillis); } - private void putSecureInt(String name, int value) { - Settings.Secure.putInt(mContentResolver, name, value); - } - private void updateCustomDelayValue(int delayMillis) { - putSecureInt(CONTROL_AUTOCLICK_DELAY_SECURE, delayMillis); + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, + delayMillis); mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, delayMillis).apply(); mSeekBar.setProgress(delayToSeekBarProgress(delayMillis)); mDelayLabel.setText(delayTimeToString(delayMillis)); @@ -208,15 +175,8 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro updateCustomDelayValue(delayMillis + AUTOCLICK_DELAY_STEP); } } - private CharSequence delayTimeToString(int delayMillis) { - final int quantity = (delayMillis == 1000) ? Quantity.ONE : Quantity.FEW; - final float delaySecond = (float) delayMillis / 1000; - // Only show integer when delay time is 1. - final String decimalFormat = (delaySecond == 1) ? "%.0f" : "%.1f"; - - return mContext.getResources().getQuantityString( - R.plurals.accessibilty_autoclick_delay_unit_second, - quantity, String.format(decimalFormat, delaySecond)); + return AutoclickUtils.getAutoclickDelaySummary(mContext.getResources(), + R.plurals.accessibilty_autoclick_delay_unit_second, delayMillis); } } diff --git a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceController.java b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceController.java index 2bf17fdba79..f5ce509b425 100644 --- a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceController.java +++ b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceController.java @@ -18,6 +18,10 @@ package com.android.settings.accessibility; import static android.content.Context.MODE_PRIVATE; +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; +import static com.android.settings.accessibility.AutoclickUtils.KEY_DELAY_MODE; + import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; @@ -25,49 +29,28 @@ import android.content.res.Resources; import android.provider.Settings; import android.util.ArrayMap; -import androidx.annotation.VisibleForTesting; -import androidx.lifecycle.LifecycleObserver; +import androidx.annotation.Nullable; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.widget.LayoutPreference; import com.android.settingslib.widget.SelectorWithWidgetPreference; import java.util.Map; -/** - * Controller class that controls accessibility autoclick settings. - */ +/** Controller class that controls accessibility autoclick settings. */ public class ToggleAutoclickPreferenceController extends BasePreferenceController implements - LifecycleObserver, SelectorWithWidgetPreference.OnClickListener, PreferenceControllerMixin { + LifecycleObserver, OnStart, OnStop, SelectorWithWidgetPreference.OnClickListener, + SharedPreferences.OnSharedPreferenceChangeListener { - @VisibleForTesting - static final String CONTROL_AUTOCLICK_DELAY_SECURE = - Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY; - - @VisibleForTesting - static final String KEY_AUTOCLICK_CUSTOM_SEEKBAR = "autoclick_custom_seekbar"; - static final String KEY_DELAY_MODE = "delay_mode"; - - @VisibleForTesting - static final int AUTOCLICK_OFF_MODE = 0; - - @VisibleForTesting - static final int AUTOCLICK_CUSTOM_MODE = 2000; - - // Pair the preference key and autoclick mode value. - @VisibleForTesting - Map mAccessibilityAutoclickKeyToValueMap = new ArrayMap<>(); - - private SharedPreferences mSharedPreferences; - private final ContentResolver mContentResolver; - private final Resources mResources; - private OnChangeListener mOnChangeListener; - private SelectorWithWidgetPreference mDelayModePref; + private static final String KEY_AUTOCLICK_CUSTOM_SEEKBAR = "autoclick_custom_seekbar"; + private static final int AUTOCLICK_OFF_MODE = 0; + private static final int AUTOCLICK_CUSTOM_MODE = 2000; /** * Seek bar preference for autoclick delay value. The seek bar has values between 0 and @@ -75,29 +58,33 @@ public class ToggleAutoclickPreferenceController extends BasePreferenceControlle * delay values before saving them in settings. */ private LayoutPreference mSeekBerPreference; - private int mCurrentUiAutoClickMode; + private SelectorWithWidgetPreference mDelayModePref; + private Map mAccessibilityAutoclickKeyToValueMap = new ArrayMap<>(); + private final SharedPreferences mSharedPreferences; + private final ContentResolver mContentResolver; + private final Resources mResources; public ToggleAutoclickPreferenceController(Context context, String preferenceKey) { - this(context, /* lifecycle= */ null, preferenceKey); - } - - public ToggleAutoclickPreferenceController(Context context, Lifecycle lifecycle, - String preferenceKey) { super(context, preferenceKey); - mSharedPreferences = context.getSharedPreferences(context.getPackageName(), MODE_PRIVATE); mContentResolver = context.getContentResolver(); mResources = context.getResources(); - - setAutoclickModeToKeyMap(); - - if (lifecycle != null) { - lifecycle.addObserver(this); - } } - public void setOnChangeListener(OnChangeListener listener) { - mOnChangeListener = listener; + @Override + public void onStart() { + mSharedPreferences.registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onStop() { + mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + @Nullable String key) { + updateState(mDelayModePref); } @Override @@ -109,86 +96,51 @@ public class ToggleAutoclickPreferenceController extends BasePreferenceControlle public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - mDelayModePref = (SelectorWithWidgetPreference) - screen.findPreference(getPreferenceKey()); + mDelayModePref = screen.findPreference(getPreferenceKey()); mDelayModePref.setOnClickListener(this); - mSeekBerPreference = (LayoutPreference) screen.findPreference(KEY_AUTOCLICK_CUSTOM_SEEKBAR); - updateState((Preference) mDelayModePref); + mSeekBerPreference = screen.findPreference(KEY_AUTOCLICK_CUSTOM_SEEKBAR); + updateState(mDelayModePref); } @Override public void onRadioButtonClicked(SelectorWithWidgetPreference preference) { - final int value = mAccessibilityAutoclickKeyToValueMap.get(mPreferenceKey); - handleRadioButtonPreferenceChange(value); - if (mOnChangeListener != null) { - mOnChangeListener.onCheckedChanged(mDelayModePref); + final int mode = getAutoclickModeToKeyMap().get(mPreferenceKey); + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, + (mode != AUTOCLICK_OFF_MODE) ? ON : OFF); + mSharedPreferences.edit().putInt(KEY_DELAY_MODE, mode).apply(); + if (mode != AUTOCLICK_CUSTOM_MODE) { + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, + mode); } } - private void updatePreferenceCheckedState(int mode) { - if (mCurrentUiAutoClickMode == mode) { - mDelayModePref.setChecked(true); - } - } - - private void updatePreferenceVisibleState(int mode) { - mSeekBerPreference.setVisible(mCurrentUiAutoClickMode == mode); - } - @Override public void updateState(Preference preference) { super.updateState(preference); - final boolean enabled = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 0) == 1; - - mCurrentUiAutoClickMode = - enabled ? getSharedPreferenceForAutoClickMode() : AUTOCLICK_OFF_MODE; - - // Reset RadioButton. - mDelayModePref.setChecked(false); - final int mode = mAccessibilityAutoclickKeyToValueMap.get(mDelayModePref.getKey()); - updatePreferenceCheckedState(mode); - updatePreferenceVisibleState(mode); - } - - /** Listener interface handles checked event. */ - public interface OnChangeListener { - /** - * A hook that is called when preference checked. - */ - void onCheckedChanged(Preference preference); - } - - private void setAutoclickModeToKeyMap() { - final String[] autoclickKeys = mResources.getStringArray( - R.array.accessibility_autoclick_control_selector_keys); - - final int[] autoclickValues = mResources.getIntArray( - R.array.accessibility_autoclick_selector_values); - - final int autoclickValueCount = autoclickValues.length; - for (int i = 0; i < autoclickValueCount; i++) { - mAccessibilityAutoclickKeyToValueMap.put(autoclickKeys[i], autoclickValues[i]); + Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, OFF) == ON; + final int currentUiAutoClickMode = enabled + ? mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_CUSTOM_MODE) + : AUTOCLICK_OFF_MODE; + final int mode = getAutoclickModeToKeyMap().get(mDelayModePref.getKey()); + mDelayModePref.setChecked(currentUiAutoClickMode == mode); + if (mode == AUTOCLICK_CUSTOM_MODE) { + mSeekBerPreference.setVisible(mDelayModePref.isChecked()); } } - private void handleRadioButtonPreferenceChange(int preference) { - putSecureInt(Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, - (preference != AUTOCLICK_OFF_MODE) ? /* enabled */ 1 : /* disabled */ 0); - - mSharedPreferences.edit().putInt(KEY_DELAY_MODE, preference).apply(); - - if (preference != AUTOCLICK_CUSTOM_MODE) { - putSecureInt(CONTROL_AUTOCLICK_DELAY_SECURE, preference); + /** Returns the paring preference key and autoclick mode value listing. */ + private Map getAutoclickModeToKeyMap() { + if (mAccessibilityAutoclickKeyToValueMap.size() == 0) { + final String[] autoclickKeys = mResources.getStringArray( + R.array.accessibility_autoclick_control_selector_keys); + final int[] autoclickValues = mResources.getIntArray( + R.array.accessibility_autoclick_selector_values); + final int autoclickValueCount = autoclickValues.length; + for (int i = 0; i < autoclickValueCount; i++) { + mAccessibilityAutoclickKeyToValueMap.put(autoclickKeys[i], autoclickValues[i]); + } } - } - - private void putSecureInt(String name, int value) { - Settings.Secure.putInt(mContentResolver, name, value); - } - - private int getSharedPreferenceForAutoClickMode() { - return mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_CUSTOM_MODE); + return mAccessibilityAutoclickKeyToValueMap; } } diff --git a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java index 03d4a4cad10..168e99d45c6 100644 --- a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java @@ -16,94 +16,21 @@ package com.android.settings.accessibility; -import static com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController.MAX_AUTOCLICK_DELAY_MS; -import static com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController.MIN_AUTOCLICK_DELAY_MS; - -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.annotation.IntDef; import android.app.settings.SettingsEnums; -import android.content.Context; -import android.content.res.Resources; - -import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.search.SearchIndexable; -import java.lang.annotation.Retention; -import java.util.ArrayList; -import java.util.List; - /** * Fragment for preference screen for settings related to Automatically click after mouse stops * feature. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class ToggleAutoclickPreferenceFragment extends DashboardFragment - implements ToggleAutoclickPreferenceController.OnChangeListener { +public class ToggleAutoclickPreferenceFragment extends DashboardFragment { private static final String TAG = "AutoclickPrefFragment"; - private static final List sControllers = new ArrayList<>(); - - @Retention(SOURCE) - @IntDef({ - Quantity.OTHER, - Quantity.ONE, - Quantity.FEW - }) - @interface Quantity { - int OTHER = 0; - int ONE = 1; - int FEW = 3; - } - - /** - * Resource ids from which autoclick preference summaries should be derived. The strings have - * placeholder for integer delay value. - */ - private static final int[] AUTOCLICK_PREFERENCE_SUMMARIES = { - R.plurals.accessibilty_autoclick_preference_subtitle_short_delay, - R.plurals.accessibilty_autoclick_preference_subtitle_medium_delay, - R.plurals.accessibilty_autoclick_preference_subtitle_long_delay - }; - - /** - * Gets string that should be used as a autoclick preference summary for provided autoclick - * delay. - * - * @param resources Resources from which string should be retrieved. - * @param delayMillis Delay for whose value summary should be retrieved. - */ - static CharSequence getAutoclickPreferenceSummary(Resources resources, int delayMillis) { - final int summaryIndex = getAutoclickPreferenceSummaryIndex(delayMillis); - final int quantity = (delayMillis == 1000) ? Quantity.ONE : Quantity.FEW; - final float delaySecond = (float) delayMillis / 1000; - // Only show integer when delay time is 1. - final String decimalFormat = (delaySecond == 1) ? "%.0f" : "%.1f"; - - return resources.getQuantityString(AUTOCLICK_PREFERENCE_SUMMARIES[summaryIndex], - quantity, String.format(decimalFormat, delaySecond)); - } - - /** - * Finds index of the summary that should be used for the provided autoclick delay. - */ - private static int getAutoclickPreferenceSummaryIndex(int delay) { - if (delay <= MIN_AUTOCLICK_DELAY_MS) { - return 0; - } - if (delay >= MAX_AUTOCLICK_DELAY_MS) { - return AUTOCLICK_PREFERENCE_SUMMARIES.length - 1; - } - int delayRange = MAX_AUTOCLICK_DELAY_MS - MIN_AUTOCLICK_DELAY_MS; - int rangeSize = (delayRange) / (AUTOCLICK_PREFERENCE_SUMMARIES.length - 1); - return (delay - MIN_AUTOCLICK_DELAY_MS) / rangeSize; - } @Override public int getMetricsCategory() { @@ -125,58 +52,6 @@ public class ToggleAutoclickPreferenceFragment extends DashboardFragment return R.xml.accessibility_autoclick_settings; } - @Override - public void onResume() { - super.onResume(); - - for (AbstractPreferenceController controller : sControllers) { - ((ToggleAutoclickPreferenceController) controller).setOnChangeListener(this); - } - } - - @Override - public void onPause() { - super.onPause(); - - for (AbstractPreferenceController controller : sControllers) { - ((ToggleAutoclickPreferenceController) controller).setOnChangeListener(null); - } - } - - @Override - public void onCheckedChanged(Preference preference) { - for (AbstractPreferenceController controller : sControllers) { - controller.updateState(preference); - } - } - - @Override - protected List createPreferenceControllers(Context context) { - return buildPreferenceControllers(context, getSettingsLifecycle()); - } - - private static List buildPreferenceControllers(Context context, - Lifecycle lifecycle) { - Resources resources = context.getResources(); - - String[] autoclickKeys = resources.getStringArray( - R.array.accessibility_autoclick_control_selector_keys); - - final int length = autoclickKeys.length; - for (int i = 0; i < length; i++) { - sControllers.add(new ToggleAutoclickPreferenceController( - context, lifecycle, autoclickKeys[i])); - } - return sControllers; - } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(R.xml.accessibility_autoclick_settings) { - - @Override - public List createPreferenceControllers( - Context context) { - return buildPreferenceControllers(context, null); - } - }; + new BaseSearchIndexProvider(R.xml.accessibility_autoclick_settings); } diff --git a/tests/robotests/src/com/android/settings/accessibility/AutoclickPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AutoclickPreferenceControllerTest.java index d670ee8e785..031c134618b 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AutoclickPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AutoclickPreferenceControllerTest.java @@ -16,11 +16,17 @@ package com.android.settings.accessibility; +import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_DEFAULT; + +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + import static com.google.common.truth.Truth.assertThat; import android.content.Context; import android.provider.Settings; -import android.view.accessibility.AccessibilityManager; + +import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; @@ -29,17 +35,16 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; +/** Tests for {@link AutoclickPreferenceController}. */ @RunWith(RobolectricTestRunner.class) public class AutoclickPreferenceControllerTest { - private Context mContext; + private final Context mContext = ApplicationProvider.getApplicationContext(); private AutoclickPreferenceController mController; @Before public void setUp() { - mContext = RuntimeEnvironment.application; mController = new AutoclickPreferenceController(mContext, "auto_click"); } @@ -52,7 +57,7 @@ public class AutoclickPreferenceControllerTest { @Test public void getSummary_disabledAutoclick_shouldReturnOffSummary() { Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 0); + Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, OFF); assertThat(mController.getSummary()) .isEqualTo(mContext.getText(R.string.accessibility_feature_state_off)); @@ -60,14 +65,15 @@ public class AutoclickPreferenceControllerTest { @Test public void getSummary_enabledAutoclick_shouldReturnOnSummary() { - final int autoclickDelayDefault = AccessibilityManager.AUTOCLICK_DELAY_DEFAULT; Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 1); + Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, ON); Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, autoclickDelayDefault); + Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, AUTOCLICK_DELAY_DEFAULT); - assertThat(mController.getSummary()) - .isEqualTo(ToggleAutoclickPreferenceFragment.getAutoclickPreferenceSummary( - mContext.getResources(), autoclickDelayDefault)); + assertThat(mController.getSummary().toString()) + .isEqualTo(AutoclickUtils.getAutoclickDelaySummary( + mContext.getResources(), + R.plurals.accessibilty_autoclick_preference_subtitle_medium_delay, + AUTOCLICK_DELAY_DEFAULT).toString()); } } diff --git a/tests/robotests/src/com/android/settings/accessibility/AutoclickUtilsTest.java b/tests/robotests/src/com/android/settings/accessibility/AutoclickUtilsTest.java new file mode 100644 index 00000000000..46b1e2b1b7b --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/AutoclickUtilsTest.java @@ -0,0 +1,55 @@ +/* + * 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.android.settings.accessibility.AutoclickUtils.MAX_AUTOCLICK_DELAY_MS; +import static com.android.settings.accessibility.AutoclickUtils.MIN_AUTOCLICK_DELAY_MS; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link AutoclickUtils}. */ +@RunWith(RobolectricTestRunner.class) +public final class AutoclickUtilsTest { + + private final Context mContext = ApplicationProvider.getApplicationContext(); + + @Test + public void getAutoclickDelaySummary_minDelay_shouldReturnOnSummary() { + final CharSequence summary = AutoclickUtils.getAutoclickDelaySummary( + mContext.getResources(), R.plurals.accessibilty_autoclick_delay_unit_second, + MIN_AUTOCLICK_DELAY_MS); + assertThat(summary.toString()).isEqualTo("0.2 seconds"); + } + + @Test + public void getAutoclickDelaySummary_maxDelay_shouldReturnOnSummary() { + final CharSequence summary = AutoclickUtils.getAutoclickDelaySummary( + mContext.getResources(), R.plurals.accessibilty_autoclick_delay_unit_second, + MAX_AUTOCLICK_DELAY_MS); + assertThat(summary.toString()).isEqualTo("1 second"); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCustomSeekbarControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCustomSeekbarControllerTest.java index d6c66ad4254..6f0b157192f 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCustomSeekbarControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCustomSeekbarControllerTest.java @@ -18,13 +18,14 @@ package com.android.settings.accessibility; import static android.content.Context.MODE_PRIVATE; -import static com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController.KEY_CUSTOM_DELAY_VALUE; -import static com.android.settings.accessibility.ToggleAutoclickPreferenceController.KEY_DELAY_MODE; +import static com.android.settings.accessibility.AutoclickUtils.KEY_CUSTOM_DELAY_VALUE; +import static com.android.settings.accessibility.AutoclickUtils.KEY_DELAY_MODE; import static com.android.settings.core.BasePreferenceController.AVAILABLE; 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.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -37,57 +38,52 @@ import android.widget.ImageView; import android.widget.SeekBar; import android.widget.TextView; -import androidx.lifecycle.LifecycleObserver; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; -import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; /** Tests for {@link ToggleAutoclickCustomSeekbarController}. */ @RunWith(RobolectricTestRunner.class) public class ToggleAutoclickCustomSeekbarControllerTest { + private static final String KEY_CUSTOM_SEEKBAR = "autoclick_custom_seekbar"; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock private PreferenceScreen mScreen; - @Mock private LayoutPreference mLayoutPreference; - - @Mock - private Lifecycle mLifecycle; - + @Spy + private Context mContext = ApplicationProvider.getApplicationContext(); private SharedPreferences mSharedPreferences; private TextView mDelayLabel; private ImageView mShorter; private ImageView mLonger; private SeekBar mSeekBar; private ToggleAutoclickCustomSeekbarController mController; - private Context mContext; @Before public void setUp() { - MockitoAnnotations.initMocks(this); - - final String mPrefKey = "prefKey"; - mContext = ApplicationProvider.getApplicationContext(); mSharedPreferences = mContext.getSharedPreferences(mContext.getPackageName(), MODE_PRIVATE); mDelayLabel = new TextView(mContext); mShorter = new ImageView(mContext); mLonger = new ImageView(mContext); mSeekBar = new SeekBar(mContext); - mController = - new ToggleAutoclickCustomSeekbarController(mContext, mLifecycle, mPrefKey); - - doReturn(mLayoutPreference).when(mScreen).findPreference(mPrefKey); + mController = new ToggleAutoclickCustomSeekbarController(mContext, KEY_CUSTOM_SEEKBAR); + doReturn(mLayoutPreference).when(mScreen).findPreference(KEY_CUSTOM_SEEKBAR); doReturn(mSeekBar).when(mLayoutPreference).findViewById(R.id.autoclick_delay); doReturn(mDelayLabel).when(mLayoutPreference).findViewById(R.id.current_label); doReturn(mShorter).when(mLayoutPreference).findViewById(R.id.shorter); @@ -99,18 +95,13 @@ public class ToggleAutoclickCustomSeekbarControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); } - @Test - public void constructor_hasLifecycle_addObserver() { - verify(mLifecycle).addObserver(any(LifecycleObserver.class)); - } - @Test public void displayPreference_initSeekBar() { mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, 700).apply(); - mController.onResume(); + mController.onStart(); mController.displayPreference(mScreen); - mController.onPause(); + mController.onStop(); final SeekBar.OnSeekBarChangeListener mListener = shadowOf(mSeekBar).getOnSeekBarChangeListener(); @@ -123,9 +114,9 @@ public class ToggleAutoclickCustomSeekbarControllerTest { public void displayPreference_initDelayLabel() { mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, 700).apply(); - mController.onResume(); + mController.onStart(); mController.displayPreference(mScreen); - mController.onPause(); + mController.onStop(); assertThat(mDelayLabel.getText()).isEqualTo("0.7 seconds"); } @@ -203,4 +194,28 @@ public class ToggleAutoclickCustomSeekbarControllerTest { assertThat(actualDelayValue).isEqualTo(800); assertThat(actualCustomDelayValue).isEqualTo(800); } + + @Test + public void onStart_registerOnSharedPreferenceChangeListener() { + final SharedPreferences prefs = mock(SharedPreferences.class); + doReturn(prefs).when(mContext).getSharedPreferences(anyString(), anyInt()); + final ToggleAutoclickCustomSeekbarController controller = + new ToggleAutoclickCustomSeekbarController(mContext, KEY_CUSTOM_SEEKBAR); + + controller.onStart(); + + verify(prefs).registerOnSharedPreferenceChangeListener(controller); + } + + @Test + public void onStop_unregisterOnSharedPreferenceChangeListener() { + final SharedPreferences prefs = mock(SharedPreferences.class); + doReturn(prefs).when(mContext).getSharedPreferences(anyString(), anyInt()); + final ToggleAutoclickCustomSeekbarController controller = + new ToggleAutoclickCustomSeekbarController(mContext, KEY_CUSTOM_SEEKBAR); + + controller.onStop(); + + verify(prefs).unregisterOnSharedPreferenceChangeListener(controller); + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickPreferenceControllerTest.java index 1b7f326192b..3053eb24605 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickPreferenceControllerTest.java @@ -16,18 +16,19 @@ package com.android.settings.accessibility; -import static android.content.Context.MODE_PRIVATE; - -import static com.android.settings.accessibility.ToggleAutoclickPreferenceController.AUTOCLICK_CUSTOM_MODE; -import static com.android.settings.accessibility.ToggleAutoclickPreferenceController.AUTOCLICK_OFF_MODE; -import static com.android.settings.accessibility.ToggleAutoclickPreferenceController.KEY_AUTOCLICK_CUSTOM_SEEKBAR; -import static com.android.settings.accessibility.ToggleAutoclickPreferenceController.KEY_DELAY_MODE; +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; +import static com.android.settings.accessibility.AutoclickUtils.KEY_DELAY_MODE; import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -35,127 +36,137 @@ import android.content.Context; import android.content.SharedPreferences; import android.provider.Settings.Secure; -import androidx.lifecycle.LifecycleObserver; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; -import com.android.settings.accessibility.ToggleAutoclickPreferenceController.OnChangeListener; -import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.widget.LayoutPreference; import com.android.settingslib.widget.SelectorWithWidgetPreference; import com.android.settingslib.widget.SelectorWithWidgetPreference.OnClickListener; -import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; -import java.util.Map; - /** Tests for {@link ToggleAutoclickPreferenceController}. */ @RunWith(RobolectricTestRunner.class) public class ToggleAutoclickPreferenceControllerTest { + private static final String KEY_PREF_DEFAULT = "accessibility_control_autoclick_default"; + private static final String KEY_PREF_CUSTOM = "accessibility_control_autoclick_custom"; + private static final String KEY_CUSTOM_SEEKBAR = "autoclick_custom_seekbar"; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock private PreferenceScreen mScreen; - @Mock private SelectorWithWidgetPreference mDelayModePref; - - @Mock - private OnChangeListener mOnChangeListener; - @Mock private LayoutPreference mSeekBarPref; - @Mock - private Map mAccessibilityAutoclickKeyToValueMap; - - private ToggleAutoclickPreferenceController mController; private SharedPreferences mSharedPreferences; - private final String mPrefKey = "prefKey"; - private final Context mContext = ApplicationProvider.getApplicationContext(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mController = new ToggleAutoclickPreferenceController(mContext, mPrefKey); - mController.mAccessibilityAutoclickKeyToValueMap = mAccessibilityAutoclickKeyToValueMap; - mSharedPreferences = - mContext.getSharedPreferences(mContext.getPackageName(), MODE_PRIVATE); - - when(mScreen.findPreference(mPrefKey)).thenReturn(mDelayModePref); - when(mScreen.findPreference(KEY_AUTOCLICK_CUSTOM_SEEKBAR)).thenReturn(mSeekBarPref); - when(mAccessibilityAutoclickKeyToValueMap.get(mDelayModePref.getKey())).thenReturn( - AUTOCLICK_OFF_MODE); - } + @Spy + private Context mContext = ApplicationProvider.getApplicationContext(); + private ToggleAutoclickPreferenceController mController; @Test public void getAvailabilityStatus_available() { + setUpController(KEY_PREF_DEFAULT); + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); } @Test public void setClickListenerOnDelayModePref_whenDisplay_success() { + setUpController(KEY_PREF_DEFAULT); + mController.displayPreference(mScreen); verify(mDelayModePref).setOnClickListener(any(OnClickListener.class)); } @Test - public void constructor_hasLifecycle_addObserver() { - final Lifecycle lifecycle = mock(Lifecycle.class); - mController = new ToggleAutoclickPreferenceController(mContext, lifecycle, mPrefKey); + public void onStart_registerOnSharedPreferenceChangeListener() { + doReturn(mSharedPreferences).when(mContext).getSharedPreferences(anyString(), anyInt()); + setUpController(KEY_PREF_DEFAULT); - verify(lifecycle).addObserver(any(LifecycleObserver.class)); + mController.onStart(); + + verify(mSharedPreferences).registerOnSharedPreferenceChangeListener(mController); + } + + @Test + public void onStop_unregisterOnSharedPreferenceChangeListener() { + doReturn(mSharedPreferences).when(mContext).getSharedPreferences(anyString(), anyInt()); + setUpController(KEY_PREF_DEFAULT); + + mController.onStop(); + + verify(mSharedPreferences).unregisterOnSharedPreferenceChangeListener(mController); } @Test public void onRadioButtonClicked_offMode_disableAutoClick() { - when(mAccessibilityAutoclickKeyToValueMap.get(mPrefKey)).thenReturn(AUTOCLICK_OFF_MODE); - + setUpController(KEY_PREF_DEFAULT); mController.displayPreference(mScreen); - mController.onRadioButtonClicked(any(SelectorWithWidgetPreference.class)); - final boolean isEnabled = Secure.getInt(mContext.getContentResolver(), - Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, /* def= */ 0) == 1; - final int delayMs = Secure.getInt(mContext.getContentResolver(), - Secure.ACCESSIBILITY_AUTOCLICK_DELAY, /* def= */ 0); - final int keyDelayMode = mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_CUSTOM_MODE); - assertThat(keyDelayMode).isEqualTo(AUTOCLICK_OFF_MODE); - assertThat(delayMs).isEqualTo(/* expected= */ 0); + mController.onRadioButtonClicked(mDelayModePref); + + final boolean isEnabled = Secure.getInt(mContext.getContentResolver(), + Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, OFF) == ON; + final int delayMs = Secure.getInt(mContext.getContentResolver(), + Secure.ACCESSIBILITY_AUTOCLICK_DELAY, 0); + assertThat(delayMs).isEqualTo(0); assertThat(isEnabled).isFalse(); } + @Test public void onRadioButtonClicked_customMode_enableAutoClick() { - when(mAccessibilityAutoclickKeyToValueMap.get(mDelayModePref.getKey())).thenReturn( - AUTOCLICK_CUSTOM_MODE); - when(mAccessibilityAutoclickKeyToValueMap.get(mPrefKey)).thenReturn(AUTOCLICK_CUSTOM_MODE); - + setUpController(KEY_PREF_CUSTOM); mController.displayPreference(mScreen); - mController.onRadioButtonClicked(any(SelectorWithWidgetPreference.class)); - final boolean isEnabled = Secure.getInt(mContext.getContentResolver(), - Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, /* def= */ 0) == 1; - final int keyDelayMode = mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_CUSTOM_MODE); - assertThat(keyDelayMode).isEqualTo(AUTOCLICK_CUSTOM_MODE); + mController.onRadioButtonClicked(mDelayModePref); + + final boolean isEnabled = Secure.getInt(mContext.getContentResolver(), + Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, OFF) == ON; assertThat(isEnabled).isTrue(); } @Test - public void onRadioButtonClicked_hasListener_runOnCheckedChanged() { - when(mAccessibilityAutoclickKeyToValueMap.get(mDelayModePref.getKey())).thenReturn( - AUTOCLICK_CUSTOM_MODE); - when(mAccessibilityAutoclickKeyToValueMap.get(mPrefKey)).thenReturn(AUTOCLICK_CUSTOM_MODE); - - mController.setOnChangeListener(mOnChangeListener); + public void onSharedPreferenceChanged_customMode_shouldShowCustomSeekbar() { + setUpController(KEY_PREF_CUSTOM); mController.displayPreference(mScreen); - mController.onRadioButtonClicked(any(SelectorWithWidgetPreference.class)); + mController.onRadioButtonClicked(mDelayModePref); + when(mDelayModePref.isChecked()).thenReturn(true); + reset(mSeekBarPref); - verify(mOnChangeListener).onCheckedChanged(mDelayModePref); + mController.onSharedPreferenceChanged(mSharedPreferences, KEY_DELAY_MODE); + + verify(mSeekBarPref).setVisible(true); + } + + @Test + public void onSharedPreferenceChanged_offMode_shouldNotShowCustomSeekbar() { + setUpController(KEY_PREF_DEFAULT); + mController.displayPreference(mScreen); + mController.onRadioButtonClicked(mDelayModePref); + reset(mSeekBarPref); + + mController.onSharedPreferenceChanged(mSharedPreferences, KEY_DELAY_MODE); + + verify(mSeekBarPref, never()).setVisible(true); + } + + private void setUpController(String preferenceKey) { + mController = new ToggleAutoclickPreferenceController(mContext, preferenceKey); + when(mScreen.findPreference(preferenceKey)).thenReturn(mDelayModePref); + when(mDelayModePref.getKey()).thenReturn(preferenceKey); + when(mScreen.findPreference(KEY_CUSTOM_SEEKBAR)).thenReturn(mSeekBarPref); } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragmentTest.java new file mode 100644 index 00000000000..4e8ce961e55 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragmentTest.java @@ -0,0 +1,80 @@ +/* + * 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 android.app.settings.SettingsEnums; +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; +import com.android.settings.testutils.XmlTestUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import java.util.List; + +/** Tests for {@link ToggleAutoclickPreferenceFragment}. */ +@RunWith(RobolectricTestRunner.class) +public class ToggleAutoclickPreferenceFragmentTest { + + private final Context mContext = ApplicationProvider.getApplicationContext(); + private ToggleAutoclickPreferenceFragment mFragment; + + @Before + public void setUp() { + mFragment = new ToggleAutoclickPreferenceFragment(); + } + + @Test + public void getMetricsCategory_returnsCorrectCategory() { + assertThat(mFragment.getMetricsCategory()).isEqualTo( + SettingsEnums.ACCESSIBILITY_TOGGLE_AUTOCLICK); + } + + @Test + public void getPreferenceScreenResId_returnsCorrectXml() { + assertThat(mFragment.getPreferenceScreenResId()).isEqualTo( + R.xml.accessibility_autoclick_settings); + } + + @Test + public void getHelpResource_returnsCorrectHelpResource() { + assertThat(mFragment.getHelpResource()).isEqualTo(R.string.help_url_autoclick); + } + + @Test + public void getLogTag_returnsCorrectTag() { + assertThat(mFragment.getLogTag()).isEqualTo("AutoclickPrefFragment"); + } + + @Test + public void getNonIndexableKeys_existInXmlLayout() { + final List niks = ToggleAutoclickPreferenceFragment.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(mContext); + final List keys = + XmlTestUtils.getKeysFromPreferenceXml(mContext, + R.xml.accessibility_autoclick_settings); + + assertThat(keys).containsAtLeastElementsIn(niks); + } +}