diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 8ff85e2d9f0..44403583ef1 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -702,6 +702,24 @@
- Accessibility volume
+
+
+ - accessibility_control_autoclick_default
+ - accessibility_control_autoclick_200ms
+ - accessibility_control_autoclick_600ms
+ - accessibility_control_autoclick_1sec
+ - accessibility_control_autoclick_custom
+
+
+
+
+ - 0
+ - 200
+ - 600
+ - 1000
+ - 2000
+
+
- accessibility_control_timeout_default
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b16ab2cfdc6..cc18c5694b5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4919,11 +4919,25 @@
Turn light screens dark so people who are sensitive to bright light can have a better viewing experience.\n\nNote: dark colors will turn light. Images will also be inverted.
- Dwell timing
+ Auto click (dwell timing)
If you are using a mouse, you can set the cursor to take action automatically when it stops moving for a certain amount of time.
-
- Delay before click
+
+ None
+
+ Short
+
+ 0.2 seconds
+
+ Medium
+
+ 0.6 seconds
+
+ Long
+
+ 1 second
+
+ Custom
Vibration & haptic strength
diff --git a/res/xml/accessibility_autoclick_settings.xml b/res/xml/accessibility_autoclick_settings.xml
index 0351faf3066..70cb9c844ad 100644
--- a/res/xml/accessibility_autoclick_settings.xml
+++ b/res/xml/accessibility_autoclick_settings.xml
@@ -20,14 +20,37 @@
android:key="autoclick_preference_screen"
android:title="@string/accessibility_autoclick_preference_title">
+
+
+
+
+
+
+
+
+
+ android:key="autoclick_delay" />
+
diff --git a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceController.java b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceController.java
new file mode 100644
index 00000000000..33ebfc582d1
--- /dev/null
+++ b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceController.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2020 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 android.content.Context.MODE_PRIVATE;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.util.ArrayMap;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.lifecycle.LifecycleObserver;
+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.settings.widget.SeekBarPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import java.util.Map;
+
+/**
+ * Controller class that controls accessibility autoclick settings.
+ */
+public class ToggleAutoclickPreferenceController extends BasePreferenceController implements
+ LifecycleObserver, RadioButtonPreference.OnClickListener, PreferenceControllerMixin,
+ Preference.OnPreferenceChangeListener {
+ // 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;
+
+ private static final String CONTROL_AUTOCLICK_DELAY_SECURE =
+ Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY;
+ private static final String KEY_AUTOCLICK_DELA = "autoclick_delay";
+ private static final String KEY_CUSTOM_DELAY_VALUE = "custom_delay_value";
+ private static final String KEY_DELAY_MODE = "delay_mode";
+
+ // Allowed autoclick delay values are discrete.
+ // This is the difference between two allowed values.
+ private static final int AUTOCLICK_DELAY_STEP = 100;
+ private static final int AUTOCLICK_OFF_MODE = 0;
+ private static final int AUTOCLICK_CUSTOM_MODE = 2000;
+
+ // Pair the preference key and autoclick mode value.
+ private final Map mAccessibilityAutoclickKeyToValueMap = new ArrayMap<>();
+
+ private SharedPreferences mSharedPreferences;
+ private final ContentResolver mContentResolver;
+ private final Resources mResources;
+ private OnChangeListener mOnChangeListener;
+ private RadioButtonPreference mDelayModePref;
+
+ /**
+ * Seek bar preference for autoclick delay value. The seek bar has values between 0 and
+ * number of possible discrete autoclick delay values. These will have to be converted to actual
+ * delay values before saving them in settings.
+ */
+ private SeekBarPreference mCustomDelayPref;
+ private int mCurrentUiAutoClickMode;
+
+ public ToggleAutoclickPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+
+ mSharedPreferences = context.getSharedPreferences(context.getPackageName(), MODE_PRIVATE);
+ mContentResolver = context.getContentResolver();
+ mResources = context.getResources();
+
+ setAutoclickModeToKeyMap();
+ }
+
+ 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 int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+
+ mDelayModePref = (RadioButtonPreference)
+ screen.findPreference(getPreferenceKey());
+ mDelayModePref.setOnClickListener(this);
+
+ int delay = getSharedPreferenceForDelayValue();
+
+ // Initialize seek bar preference. Sets seek bar size to the number of possible delay
+ // values.
+ mCustomDelayPref = (SeekBarPreference) screen.findPreference(KEY_AUTOCLICK_DELA);
+ mCustomDelayPref.setMax(delayToSeekBarProgress(MAX_AUTOCLICK_DELAY_MS));
+ mCustomDelayPref.setProgress(delayToSeekBarProgress(delay));
+ mCustomDelayPref.setOnPreferenceChangeListener(this);
+
+ updateState((Preference) mDelayModePref);
+ }
+
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference preference) {
+ int value = mAccessibilityAutoclickKeyToValueMap.get(mPreferenceKey);
+ handleRadioButtonPreferenceChange(value);
+ if (mOnChangeListener != null) {
+ mOnChangeListener.onCheckedChanged(mDelayModePref);
+ }
+ }
+
+ private void updatePreferenceCheckedState(int mode) {
+ if (mCurrentUiAutoClickMode == mode) {
+ mDelayModePref.setChecked(true);
+ }
+ }
+
+ private void updatePreferenceVisibleState(int mode) {
+ mCustomDelayPref.setVisible(mCurrentUiAutoClickMode == mode);
+ }
+
+ private void updateSeekBarProgressState() {
+ if (mCurrentUiAutoClickMode == AUTOCLICK_CUSTOM_MODE) {
+ int delay = getSharedPreferenceForDelayValue();
+ mCustomDelayPref.setProgress(delayToSeekBarProgress(delay));
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ mCurrentUiAutoClickMode = getSharedPreferenceForAutoClickMode();
+
+ // Reset RadioButton.
+ mDelayModePref.setChecked(false);
+ int mode = mAccessibilityAutoclickKeyToValueMap.get(mDelayModePref.getKey());
+ updateSeekBarProgressState();
+ updatePreferenceCheckedState(mode);
+ updatePreferenceVisibleState(mode);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mCustomDelayPref && newValue instanceof Integer) {
+ putSecureInt(CONTROL_AUTOCLICK_DELAY_SECURE, seekBarProgressToDelay((int) newValue));
+ mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE,
+ seekBarProgressToDelay((int) newValue)).apply();
+ return true;
+ }
+ return false;
+ }
+
+ /** Listener interface handles checked event. */
+ public interface OnChangeListener {
+ /**
+ * A hook that is called when preference checked.
+ */
+ void onCheckedChanged(Preference preference);
+ }
+
+ private void setAutoclickModeToKeyMap() {
+ String[] autoclickKeys = mResources.getStringArray(
+ R.array.accessibility_autoclick_control_selector_keys);
+
+ 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 handleRadioButtonPreferenceChange(int preference) {
+ if (preference == AUTOCLICK_OFF_MODE) {
+ putSecureInt(Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, /*value= */ 0);
+ } else {
+ putSecureInt(Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, /*value= */ 1);
+ }
+
+ mSharedPreferences.edit().putInt(KEY_DELAY_MODE, preference).apply();
+
+ if (preference == AUTOCLICK_CUSTOM_MODE) {
+ putSecureInt(CONTROL_AUTOCLICK_DELAY_SECURE, getSharedPreferenceForDelayValue());
+ } else {
+ putSecureInt(CONTROL_AUTOCLICK_DELAY_SECURE, preference);
+ }
+ }
+
+ /** Converts seek bar preference progress value to autoclick delay associated with it. */
+ private int seekBarProgressToDelay(int progress) {
+ return progress * AUTOCLICK_DELAY_STEP + MIN_AUTOCLICK_DELAY_MS;
+ }
+
+ /**
+ * Converts autoclick delay value to seek bar preference progress values that represents said
+ * delay.
+ */
+ private int delayToSeekBarProgress(int delay) {
+ return (delay - MIN_AUTOCLICK_DELAY_MS) / AUTOCLICK_DELAY_STEP;
+ }
+
+ private void putSecureInt(String name, int value) {
+ Settings.Secure.putInt(mContentResolver, name, value);
+ }
+
+ private int getSharedPreferenceForDelayValue() {
+ int mode = mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_OFF_MODE);
+ int delay = mSharedPreferences.getInt(KEY_CUSTOM_DELAY_VALUE,
+ AccessibilityManager.AUTOCLICK_DELAY_DEFAULT);
+
+ return mode == AUTOCLICK_CUSTOM_MODE ? delay : mode;
+ }
+
+ private int getSharedPreferenceForAutoClickMode() {
+ return mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_OFF_MODE);
+ }
+}
diff --git a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java
index 45dd39ee3fe..0ba54eb3a9f 100644
--- a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java
@@ -16,22 +16,20 @@
package com.android.settings.accessibility;
+import static com.android.settings.accessibility.ToggleAutoclickPreferenceController.MAX_AUTOCLICK_DELAY_MS;
+import static com.android.settings.accessibility.ToggleAutoclickPreferenceController.MIN_AUTOCLICK_DELAY_MS;
+
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Resources;
-import android.os.Bundle;
-import android.provider.SearchIndexableResource;
-import android.provider.Settings;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.Switch;
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.search.Indexable;
-import com.android.settings.widget.SeekBarPreference;
-import com.android.settings.widget.SwitchBar;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
@@ -42,18 +40,11 @@ import java.util.List;
* feature.
*/
@SearchIndexable
-public class ToggleAutoclickPreferenceFragment extends ToggleFeaturePreferenceFragment
- implements SwitchBar.OnSwitchChangeListener, Preference.OnPreferenceChangeListener {
+public class ToggleAutoclickPreferenceFragment extends DashboardFragment
+ implements ToggleAutoclickPreferenceController.OnChangeListener {
- /** Min allowed autoclick delay value. */
- private static final int MIN_AUTOCLICK_DELAY = 200;
- /** Max allowed autoclick delay value. */
- private static final int MAX_AUTOCLICK_DELAY = 1000;
- /**
- * Allowed autoclick delay values are discrete. This is the difference between two allowed
- * values.
- */
- private static final int AUTOCLICK_DELAY_STEP = 100;
+ private static final String TAG = "AutoclickPrefFragment";
+ private static final List sControllers = new ArrayList<>();
/**
* Resource ids from which autoclick preference summaries should be derived. The strings have
@@ -67,13 +58,6 @@ public class ToggleAutoclickPreferenceFragment extends ToggleFeaturePreferenceFr
R.plurals.accessibilty_autoclick_preference_subtitle_very_long_delay
};
- /**
- * Seek bar preference for autoclick delay value. The seek bar has values between 0 and
- * number of possible discrete autoclick delay values. These will have to be converted to actual
- * delay values before saving them in settings.
- */
- private SeekBarPreference mDelay;
-
/**
* Gets string that should be used as a autoclick preference summary for provided autoclick
* delay.
@@ -91,21 +75,15 @@ public class ToggleAutoclickPreferenceFragment extends ToggleFeaturePreferenceFr
* 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) {
+ if (delay <= MIN_AUTOCLICK_DELAY_MS) {
return 0;
}
- if (delay >= MAX_AUTOCLICK_DELAY) {
+ if (delay >= MAX_AUTOCLICK_DELAY_MS) {
return mAutoclickPreferenceSummaries.length - 1;
}
- int rangeSize = (MAX_AUTOCLICK_DELAY - MIN_AUTOCLICK_DELAY) /
- (mAutoclickPreferenceSummaries.length - 1);
- return (delay - MIN_AUTOCLICK_DELAY) / rangeSize;
- }
-
- @Override
- protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
- Settings.Secure.putInt(getContentResolver(), preferenceKey, enabled ? 1 : 0);
- mDelay.setEnabled(enabled);
+ int delayRange = MAX_AUTOCLICK_DELAY_MS - MIN_AUTOCLICK_DELAY_MS;
+ int rangeSize = (delayRange) / (mAutoclickPreferenceSummaries.length - 1);
+ return (delay - MIN_AUTOCLICK_DELAY_MS) / rangeSize;
}
@Override
@@ -118,82 +96,68 @@ public class ToggleAutoclickPreferenceFragment extends ToggleFeaturePreferenceFr
return R.string.help_url_autoclick;
}
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
@Override
protected int getPreferenceScreenResId() {
return R.xml.accessibility_autoclick_settings;
}
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public void onResume() {
+ super.onResume();
- int delay = Settings.Secure.getInt(
- getContentResolver(), Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
- AccessibilityManager.AUTOCLICK_DELAY_DEFAULT);
-
- // Initialize seek bar preference. Sets seek bar size to the number of possible delay
- // values.
- mDelay = (SeekBarPreference) findPreference("autoclick_delay");
- mDelay.setMax(delayToSeekBarProgress(MAX_AUTOCLICK_DELAY));
- mDelay.setProgress(delayToSeekBarProgress(delay));
- mDelay.setOnPreferenceChangeListener(this);
- }
-
- @Override
- protected void onInstallSwitchBarToggleSwitch() {
- super.onInstallSwitchBarToggleSwitch();
-
- int value = Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 0);
- mSwitchBar.setCheckedInternal(value == 1);
- mSwitchBar.addOnSwitchChangeListener(this);
- mDelay.setEnabled(value == 1);
- }
-
- @Override
- protected void onRemoveSwitchBarToggleSwitch() {
- super.onRemoveSwitchBarToggleSwitch();
- mSwitchBar.removeOnSwitchChangeListener(this);
- }
-
- @Override
- public void onSwitchChanged(Switch switchView, boolean isChecked) {
- onPreferenceToggled(Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, isChecked);
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (preference == mDelay && newValue instanceof Integer) {
- Settings.Secure.putInt(getContentResolver(),
- Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
- seekBarProgressToDelay((int) newValue));
- return true;
+ for (AbstractPreferenceController controller : sControllers) {
+ ((ToggleAutoclickPreferenceController) controller).setOnChangeListener(this);
}
- return false;
}
@Override
- protected void updateSwitchBarText(SwitchBar switchBar) {
- final String switchBarText = getString(R.string.accessibility_service_master_switch_title,
- getString(R.string.accessibility_autoclick_preference_title));
- switchBar.setSwitchBarText(switchBarText, switchBarText);
+ public void onPause() {
+ super.onPause();
+
+ for (AbstractPreferenceController controller : sControllers) {
+ ((ToggleAutoclickPreferenceController) controller).setOnChangeListener(null);
+ }
}
- /**
- * Converts seek bar preference progress value to autoclick delay associated with it.
- */
- private int seekBarProgressToDelay(int progress) {
- return progress * AUTOCLICK_DELAY_STEP + MIN_AUTOCLICK_DELAY;
+ @Override
+ public void onCheckedChanged(Preference preference) {
+ for (AbstractPreferenceController controller : sControllers) {
+ controller.updateState(preference);
+ }
}
- /**
- * Converts autoclick delay value to seek bar preference progress values that represents said
- * delay.
- */
- private int delayToSeekBarProgress(int delay) {
- return (delay - MIN_AUTOCLICK_DELAY) / AUTOCLICK_DELAY_STEP;
+ @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);
+ new BaseSearchIndexProvider(R.xml.accessibility_autoclick_settings) {
+
+ @Override
+ public List createPreferenceControllers(
+ Context context) {
+ return buildPreferenceControllers(context, null);
+ }
+ };
}