summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/input/InputSettings.java73
-rw-r--r--core/java/android/hardware/input/input_framework.aconfig6
-rw-r--r--core/java/android/provider/Settings.java11
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java1
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java1
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java7
-rw-r--r--services/core/java/com/android/server/input/InputSettingsObserver.java9
-rw-r--r--services/core/java/com/android/server/input/NativeInputManagerService.java8
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp12
9 files changed, 127 insertions, 1 deletions
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 33960c058baa..145dbf21699e 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -16,6 +16,8 @@
package android.hardware.input;
+import static com.android.hardware.input.Flags.keyboardA11yBounceKeysFlag;
+
import android.Manifest;
import android.annotation.FloatRange;
import android.annotation.NonNull;
@@ -58,6 +60,11 @@ public class InputSettings {
*/
public static final float DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH = .8f;
+ /**
+ * The maximum allowed Accessibility bounce keys threshold.
+ * @hide
+ */
+ public static final int MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS = 5000;
private InputSettings() {
}
@@ -328,4 +335,70 @@ public class InputSettings {
.getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon)
|| InputProperties.force_enable_stylus_pointer_icon().orElse(false);
}
+
+ /**
+ * Whether Accessibility bounce keys is enabled.
+ *
+ * <p>
+ * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
+ * that allows the user to configure the device to ignore rapid, repeated keypresses of the
+ * same key.
+ * </p>
+ *
+ * @hide
+ */
+ public static boolean isAccessibilityBounceKeysEnabled(@NonNull Context context) {
+ return getAccessibilityBounceKeysThreshold(context) != 0;
+ }
+
+ /**
+ * Get Accessibility bounce keys threshold duration in milliseconds.
+ *
+ * <p>
+ * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
+ * that allows the user to configure the device to ignore rapid, repeated keypresses of the
+ * same key.
+ * </p>
+ *
+ * @hide
+ */
+ public static int getAccessibilityBounceKeysThreshold(@NonNull Context context) {
+ if (!keyboardA11yBounceKeysFlag()) {
+ return 0;
+ }
+ return Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS, 0, UserHandle.USER_CURRENT);
+ }
+
+ /**
+ * Set Accessibility bounce keys threshold duration in milliseconds.
+ * @param thresholdTimeMillis time duration for which a key down will be ignored after a
+ * previous key up for the same key on the same device between 0 and
+ * {@link MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS}
+ *
+ * <p>
+ * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
+ * that allows the user to configure the device to ignore rapid, repeated keypresses of the
+ * same key.
+ * </p>
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
+ public static void setAccessibilityBounceKeysThreshold(@NonNull Context context,
+ int thresholdTimeMillis) {
+ if (!keyboardA11yBounceKeysFlag()) {
+ return;
+ }
+ if (thresholdTimeMillis < 0
+ || thresholdTimeMillis > MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS) {
+ throw new IllegalArgumentException(
+ "Provided Bounce keys threshold should be in range [0, "
+ + MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS + "]");
+ }
+ Settings.System.putIntForUser(context.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS, thresholdTimeMillis,
+ UserHandle.USER_CURRENT);
+ }
+
}
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index 97c45a76ade9..362fe78b14b8 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -17,6 +17,12 @@ flag {
bug: "294546335"
}
+flag {
+ namespace: "input_native"
+ name: "keyboard_a11y_bounce_keys_flag"
+ description: "Controls if the bounce keys accessibility feature for physical keyboard is available to the user"
+ bug: "294546335"
+}
flag {
namespace: "input_native"
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9c27f19b349a..2ed994b503c9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7791,6 +7791,16 @@ public final class Settings {
public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
/**
+ * Whether to enable bounce keys for Physical Keyboard accessibility.
+ *
+ * If set to non-zero value, any key press on physical keyboard within the provided
+ * threshold duration (in milliseconds) of the same key, will be ignored.
+ *
+ * @hide
+ */
+ public static final String ACCESSIBILITY_BOUNCE_KEYS = "accessibility_bounce_keys";
+
+ /**
* Whether stylus button presses are disabled. This is a boolean that
* determines if stylus buttons are ignored.
*
@@ -12126,6 +12136,7 @@ public final class Settings {
CLONE_TO_MANAGED_PROFILE.add(LOCATION_CHANGER);
CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
CLONE_TO_MANAGED_PROFILE.add(SHOW_IME_WITH_HARD_KEYBOARD);
+ CLONE_TO_MANAGED_PROFILE.add(ACCESSIBILITY_BOUNCE_KEYS);
CLONE_TO_MANAGED_PROFILE.add(NOTIFICATION_BUBBLES);
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 5c09b1692453..460d9f040e68 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -73,6 +73,7 @@ public class SecureSettings {
Settings.Secure.TTS_ENABLED_PLUGINS,
Settings.Secure.TTS_DEFAULT_LOCALE,
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+ Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS,
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, // moved to global
Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, // moved to global
Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT, // moved to global
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index b0169a115ec5..6c48110ef10b 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -119,6 +119,7 @@ public class SecureSettingsValidators {
VALIDATORS.put(Secure.TTS_ENABLED_PLUGINS, new PackageNameListValidator(" "));
VALIDATORS.put(Secure.TTS_DEFAULT_LOCALE, TTS_LIST_VALIDATOR);
VALIDATORS.put(Secure.SHOW_IME_WITH_HARD_KEYBOARD, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.ACCESSIBILITY_BOUNCE_KEYS, ANY_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.WIFI_NUM_OPEN_NETWORKS_KEPT, NON_NEGATIVE_INTEGER_VALIDATOR);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 3fc9594965a2..972f85793556 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -3504,6 +3504,13 @@ public class InputManagerService extends IInputManager.Stub
wm.addView(view, lp);
}
+ /**
+ * Sets Accessibility bounce keys threshold in milliseconds.
+ */
+ public void setAccessibilityBounceKeysThreshold(int thresholdTimeMs) {
+ mNative.setAccessibilityBounceKeysThreshold(thresholdTimeMs);
+ }
+
interface KeyboardBacklightControllerInterface {
default void incrementKeyboardBacklight(int deviceId) {}
default void decrementKeyboardBacklight(int deviceId) {}
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index 8e0289ef1b43..0012eab11277 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -85,7 +85,9 @@ class InputSettingsObserver extends ContentObserver {
Map.entry(Settings.Secure.getUriFor(Settings.Secure.KEY_REPEAT_DELAY_MS),
(reason) -> updateKeyRepeatInfo()),
Map.entry(Settings.System.getUriFor(Settings.System.SHOW_ROTARY_INPUT),
- (reason) -> updateShowRotaryInput()));
+ (reason) -> updateShowRotaryInput()),
+ Map.entry(Settings.System.getUriFor(Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS),
+ (reason) -> updateAccessibilityBounceKeys()));
}
/**
@@ -216,4 +218,9 @@ class InputSettingsObserver extends ContentObserver {
}
mNative.setMaximumObscuringOpacityForTouch(opacity);
}
+
+ private void updateAccessibilityBounceKeys() {
+ mService.setAccessibilityBounceKeysThreshold(
+ InputSettings.getAccessibilityBounceKeysThreshold(mContext));
+ }
}
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index 620cde59fb52..49bbe9a7655c 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -246,6 +246,11 @@ interface NativeInputManagerService {
*/
void sysfsNodeChanged(String sysfsNodePath);
+ /**
+ * Notify if Accessibility bounce keys threshold is changed from InputSettings.
+ */
+ void setAccessibilityBounceKeysThreshold(int thresholdTimeMs);
+
/** The native implementation of InputManagerService methods. */
class NativeImpl implements NativeInputManagerService {
/** Pointer to native input manager service object, used by native code. */
@@ -500,5 +505,8 @@ interface NativeInputManagerService {
@Override
public native void sysfsNodeChanged(String sysfsNodePath);
+
+ @Override
+ public native void setAccessibilityBounceKeysThreshold(int thresholdTimeMs);
}
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 6f65965b8aa8..bc05e77171bd 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -88,6 +88,7 @@ namespace input_flags = com::android::input::flags;
namespace android {
static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
+static const bool ENABLE_INPUT_FILTER_RUST = input_flags::enable_input_filter_rust_impl();
// The exponent used to calculate the pointer speed scaling factor.
// The scaling factor is calculated as 2 ^ (speed * exponent),
@@ -2737,6 +2738,15 @@ static void nativeSetStylusPointerIconEnabled(JNIEnv* env, jobject nativeImplObj
im->setStylusPointerIconEnabled(enabled);
}
+static void nativeSetAccessibilityBounceKeysThreshold(JNIEnv* env, jobject nativeImplObj,
+ jint thresholdTimeMs) {
+ NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+ if (ENABLE_INPUT_FILTER_RUST) {
+ im->getInputManager()->getInputFilter().setAccessibilityBounceKeysThreshold(
+ static_cast<nsecs_t>(thresholdTimeMs) * 1000000);
+ }
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputManagerMethods[] = {
@@ -2836,6 +2846,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
(void*)nativeSetStylusButtonMotionEventsEnabled},
{"getMouseCursorPosition", "()[F", (void*)nativeGetMouseCursorPosition},
{"setStylusPointerIconEnabled", "(Z)V", (void*)nativeSetStylusPointerIconEnabled},
+ {"setAccessibilityBounceKeysThreshold", "(I)V",
+ (void*)nativeSetAccessibilityBounceKeysThreshold},
};
#define FIND_CLASS(var, className) \