• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.hardware.input;
18 
19 import static com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_MOUSE_KEYS;
20 import static com.android.hardware.input.Flags.enableCustomizableInputGestures;
21 import static com.android.hardware.input.Flags.keyboardA11yMouseKeys;
22 import static com.android.hardware.input.Flags.mouseScrollingAcceleration;
23 import static com.android.hardware.input.Flags.mouseReverseVerticalScrolling;
24 import static com.android.hardware.input.Flags.mouseSwapPrimaryButton;
25 import static com.android.hardware.input.Flags.pointerAcceleration;
26 import static com.android.hardware.input.Flags.touchpadSystemGestureDisable;
27 import static com.android.hardware.input.Flags.touchpadThreeFingerTapShortcut;
28 import static com.android.hardware.input.Flags.touchpadVisualizer;
29 import static com.android.hardware.input.Flags.useKeyGestureEventHandler;
30 import static com.android.hardware.input.Flags.useKeyGestureEventHandlerMultiKeyGestures;
31 import static com.android.input.flags.Flags.FLAG_KEYBOARD_REPEAT_KEYS;
32 import static com.android.input.flags.Flags.keyboardRepeatKeys;
33 
34 import android.Manifest;
35 import android.annotation.FlaggedApi;
36 import android.annotation.FloatRange;
37 import android.annotation.NonNull;
38 import android.annotation.RequiresPermission;
39 import android.annotation.SuppressLint;
40 import android.annotation.TestApi;
41 import android.app.AppGlobals;
42 import android.content.Context;
43 import android.os.UserHandle;
44 import android.provider.Settings;
45 import android.sysprop.InputProperties;
46 import android.view.ViewConfiguration;
47 
48 /**
49  * InputSettings encapsulates reading and writing settings related to input
50  *
51  * @hide
52  */
53 @TestApi
54 public class InputSettings {
55     /**
56      * Pointer Speed: The minimum (slowest) pointer speed (-7).
57      * @hide
58      */
59     public static final int MIN_POINTER_SPEED = -7;
60 
61     /**
62      * Pointer Speed: The maximum (fastest) pointer speed (7).
63      * @hide
64      */
65     public static final int MAX_POINTER_SPEED = 7;
66 
67     /**
68      * Pointer Speed: The default pointer speed (0).
69      */
70     @SuppressLint("UnflaggedApi") // TestApi without associated feature.
71     public static final int DEFAULT_POINTER_SPEED = 0;
72 
73     /**
74      * Pointer Speed: The minimum (slowest) mouse scrolling speed (-7).
75      * @hide
76      */
77     public static final int MIN_MOUSE_SCROLLING_SPEED = -7;
78 
79     /**
80      * Pointer Speed: The maximum (fastest) mouse scrolling speed (7).
81      * @hide
82      */
83     public static final int MAX_MOUSE_SCROLLING_SPEED = 7;
84 
85     /**
86      * Pointer Speed: The default mouse scrolling speed (0).
87      * @hide
88      */
89     public static final int DEFAULT_MOUSE_SCROLLING_SPEED = 0;
90 
91     /**
92      * Bounce Keys Threshold: The default value of the threshold (500 ms).
93      *
94      * @hide
95      */
96     public static final int DEFAULT_BOUNCE_KEYS_THRESHOLD_MILLIS = 500;
97 
98     /**
99      * Slow Keys Threshold: The default value of the threshold (500 ms).
100      *
101      * @hide
102      */
103     public static final int DEFAULT_SLOW_KEYS_THRESHOLD_MILLIS = 500;
104 
105     /**
106      * The maximum allowed obscuring opacity by UID to propagate touches (0 <= x <= 1).
107      * @hide
108      */
109     public static final float DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH = .8f;
110 
111     /**
112      * The maximum allowed Accessibility bounce keys threshold.
113      * @hide
114      */
115     public static final int MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS = 5000;
116 
117     /**
118      * The maximum allowed Accessibility slow keys threshold.
119      * @hide
120      */
121     public static final int MAX_ACCESSIBILITY_SLOW_KEYS_THRESHOLD_MILLIS = 5000;
122 
123     /**
124      * Default value for {@link Settings.Secure#STYLUS_POINTER_ICON_ENABLED}.
125      * @hide
126      */
127     public static final int DEFAULT_STYLUS_POINTER_ICON_ENABLED = 1;
128 
129     /**
130      * The minimum allowed repeat keys timeout before starting key repeats.
131      * @hide
132      */
133     public static final int MIN_KEY_REPEAT_TIMEOUT_MILLIS = 150;
134 
135     /**
136      * The maximum allowed repeat keys timeout before starting key repeats.
137      * @hide
138      */
139     public static final int MAX_KEY_REPEAT_TIMEOUT_MILLIS = 2000;
140 
141     /**
142      * The minimum allowed repeat keys delay between successive key repeats.
143      * @hide
144      */
145     public static final int MIN_KEY_REPEAT_DELAY_MILLIS = 20;
146 
147     /**
148      * The maximum allowed repeat keys delay between successive key repeats.
149      * @hide
150      */
151     public static final int MAX_KEY_REPEAT_DELAY_MILLIS = 2000;
152 
InputSettings()153     private InputSettings() {
154     }
155 
156     /**
157      * Gets the mouse pointer speed.
158      * <p>
159      * Only returns the permanent mouse pointer speed.  Ignores any temporary pointer
160      * speed set by {@link InputManager#tryPointerSpeed}.
161      * </p>
162      *
163      * @param context The application context.
164      * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
165      * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
166      *
167      * @hide
168      */
169     @SuppressLint("NonUserGetterCalled")
getPointerSpeed(Context context)170     public static int getPointerSpeed(Context context) {
171         return Settings.System.getInt(context.getContentResolver(),
172                 Settings.System.POINTER_SPEED, DEFAULT_POINTER_SPEED);
173     }
174 
175     /**
176      * Sets the mouse pointer speed.
177      * <p>
178      * Requires {@link android.Manifest.permission#WRITE_SETTINGS}.
179      * </p>
180      *
181      * @param context The application context.
182      * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
183      * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
184      *
185      * @hide
186      */
187     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setPointerSpeed(Context context, int speed)188     public static void setPointerSpeed(Context context, int speed) {
189         if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
190             throw new IllegalArgumentException("speed out of range");
191         }
192 
193         Settings.System.putInt(context.getContentResolver(),
194                 Settings.System.POINTER_SPEED, speed);
195     }
196 
197     /**
198      * Returns the maximum allowed obscuring opacity per UID to propagate touches.
199      *
200      * <p>For certain window types (e.g. {@link LayoutParams#TYPE_APPLICATION_OVERLAY}),
201      * the decision of honoring {@link LayoutParams#FLAG_NOT_TOUCHABLE} or not depends on
202      * the combined obscuring opacity of the windows above the touch-consuming window, per
203      * UID. Check documentation of {@link LayoutParams#FLAG_NOT_TOUCHABLE} for more details.
204      *
205      * <p>The value returned is between 0 (inclusive) and 1 (inclusive).
206      *
207      * @see LayoutParams#FLAG_NOT_TOUCHABLE
208      *
209      * @hide
210      */
211     @FloatRange(from = 0, to = 1)
getMaximumObscuringOpacityForTouch(Context context)212     public static float getMaximumObscuringOpacityForTouch(Context context) {
213         return Settings.Global.getFloat(context.getContentResolver(),
214                 Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH,
215                 DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
216     }
217 
218     /**
219      * Sets the maximum allowed obscuring opacity by UID to propagate touches.
220      *
221      * <p>For certain window types (e.g. SAWs), the decision of honoring {@link LayoutParams
222      * #FLAG_NOT_TOUCHABLE} or not depends on the combined obscuring opacity of the windows
223      * above the touch-consuming window.
224      *
225      * <p>For a certain UID:
226      * <ul>
227      *     <li>If it's the same as the UID of the touch-consuming window, allow it to propagate
228      *     the touch.
229      *     <li>Otherwise take all its windows of eligible window types above the touch-consuming
230      *     window, compute their combined obscuring opacity considering that {@code
231      *     opacity(A, B) = 1 - (1 - opacity(A))*(1 - opacity(B))}. If the computed value is
232      *     less than or equal to this setting and there are no other windows preventing the
233      *     touch, allow the UID to propagate the touch.
234      * </ul>
235      *
236      * <p>This value should be between 0 (inclusive) and 1 (inclusive).
237      *
238      * @see #getMaximumObscuringOpacityForTouch(Context)
239      *
240      * @hide
241      */
242     @TestApi
243     @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
setMaximumObscuringOpacityForTouch( @onNull Context context, @FloatRange(from = 0, to = 1) float opacity)244     public static void setMaximumObscuringOpacityForTouch(
245             @NonNull Context context,
246             @FloatRange(from = 0, to = 1) float opacity) {
247         if (opacity < 0 || opacity > 1) {
248             throw new IllegalArgumentException(
249                     "Maximum obscuring opacity for touch should be >= 0 and <= 1");
250         }
251         Settings.Global.putFloat(context.getContentResolver(),
252                 Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, opacity);
253     }
254 
255     /**
256      * Whether stylus has ever been used on device (false by default).
257      * @hide
258      */
isStylusEverUsed(@onNull Context context)259     public static boolean isStylusEverUsed(@NonNull Context context) {
260         return Settings.Global.getInt(context.getContentResolver(),
261                         Settings.Global.STYLUS_EVER_USED, 0) == 1;
262     }
263 
264     /**
265      * Set whether stylus has ever been used on device.
266      * Should only ever be set to true once after stylus first usage.
267      * @hide
268      */
269     @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
setStylusEverUsed(@onNull Context context, boolean stylusEverUsed)270     public static void setStylusEverUsed(@NonNull Context context, boolean stylusEverUsed) {
271         Settings.Global.putInt(context.getContentResolver(),
272                 Settings.Global.STYLUS_EVER_USED, stylusEverUsed ? 1 : 0);
273     }
274 
275 
276     /**
277      * Gets the touchpad pointer speed.
278      *
279      * The returned value only applies to gesture-compatible touchpads.
280      *
281      * @param context The application context.
282      * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
283      * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
284      *
285      * @hide
286      */
getTouchpadPointerSpeed(@onNull Context context)287     public static int getTouchpadPointerSpeed(@NonNull Context context) {
288         return Settings.System.getIntForUser(context.getContentResolver(),
289                 Settings.System.TOUCHPAD_POINTER_SPEED, DEFAULT_POINTER_SPEED,
290                 UserHandle.USER_CURRENT);
291     }
292 
293     /**
294      * Sets the touchpad pointer speed, and saves it in the settings.
295      *
296      * The new speed will only apply to gesture-compatible touchpads.
297      *
298      * @param context The application context.
299      * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
300      * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
301      *
302      * @hide
303      */
304     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadPointerSpeed(@onNull Context context, int speed)305     public static void setTouchpadPointerSpeed(@NonNull Context context, int speed) {
306         if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
307             throw new IllegalArgumentException("speed out of range");
308         }
309 
310         Settings.System.putIntForUser(context.getContentResolver(),
311                 Settings.System.TOUCHPAD_POINTER_SPEED, speed, UserHandle.USER_CURRENT);
312     }
313 
314     /**
315      * Returns true if moving two fingers upwards on the touchpad should
316      * scroll down, which is known as natural scrolling.
317      *
318      * The returned value only applies to gesture-compatible touchpads.
319      *
320      * @param context The application context.
321      * @return Whether the touchpad should use natural scrolling.
322      *
323      * @hide
324      */
useTouchpadNaturalScrolling(@onNull Context context)325     public static boolean useTouchpadNaturalScrolling(@NonNull Context context) {
326         return Settings.System.getIntForUser(context.getContentResolver(),
327                 Settings.System.TOUCHPAD_NATURAL_SCROLLING, 1, UserHandle.USER_CURRENT) == 1;
328     }
329 
330     /**
331      * Sets the natural scroll behavior for the touchpad.
332      *
333      * If natural scrolling is enabled, moving two fingers upwards on the
334      * touchpad will scroll down.
335      *
336      * @param context The application context.
337      * @param enabled Will enable natural scroll if true, disable it if false
338      *
339      * @hide
340      */
341     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadNaturalScrolling(@onNull Context context, boolean enabled)342     public static void setTouchpadNaturalScrolling(@NonNull Context context, boolean enabled) {
343         Settings.System.putIntForUser(context.getContentResolver(),
344                 Settings.System.TOUCHPAD_NATURAL_SCROLLING, enabled ? 1 : 0,
345                 UserHandle.USER_CURRENT);
346     }
347 
348     /**
349      * Returns true if the touchpad should use tap to click.
350      *
351      * The returned value only applies to gesture-compatible touchpads.
352      *
353      * @param context The application context.
354      * @return Whether the touchpad should use tap to click.
355      *
356      * @hide
357      */
useTouchpadTapToClick(@onNull Context context)358     public static boolean useTouchpadTapToClick(@NonNull Context context) {
359         return Settings.System.getIntForUser(context.getContentResolver(),
360                 Settings.System.TOUCHPAD_TAP_TO_CLICK, 1, UserHandle.USER_CURRENT) == 1;
361     }
362 
363     /**
364      * Sets the tap to click behavior for the touchpad.
365      *
366      * The new behavior is only applied to gesture-compatible touchpads.
367      *
368      * @param context The application context.
369      * @param enabled Will enable tap to click if true, disable it if false
370      *
371      * @hide
372      */
373     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadTapToClick(@onNull Context context, boolean enabled)374     public static void setTouchpadTapToClick(@NonNull Context context, boolean enabled) {
375         Settings.System.putIntForUser(context.getContentResolver(),
376                 Settings.System.TOUCHPAD_TAP_TO_CLICK, enabled ? 1 : 0,
377                 UserHandle.USER_CURRENT);
378     }
379 
380     /**
381      * Whether touchpad acceleration is enabled or not.
382      *
383      * @param context The application context.
384      *
385      * @hide
386      */
isTouchpadAccelerationEnabled(@onNull Context context)387     public static boolean isTouchpadAccelerationEnabled(@NonNull Context context) {
388         if (!isPointerAccelerationFeatureFlagEnabled()) {
389             return true;
390         }
391 
392         return Settings.System.getIntForUser(context.getContentResolver(),
393                 Settings.System.TOUCHPAD_ACCELERATION_ENABLED, 1, UserHandle.USER_CURRENT)
394                 == 1;
395     }
396 
397    /**
398     * Enables or disables touchpad acceleration.
399     *
400     * @param context The application context.
401     * @param enabled Will enable touchpad acceleration if true, disable it if
402     *                false.
403     * @hide
404     */
405     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadAccelerationEnabled(@onNull Context context, boolean enabled)406     public static void setTouchpadAccelerationEnabled(@NonNull Context context,
407             boolean enabled) {
408         if (!isPointerAccelerationFeatureFlagEnabled()) {
409             return;
410         }
411         Settings.System.putIntForUser(context.getContentResolver(),
412                 Settings.System.TOUCHPAD_ACCELERATION_ENABLED, enabled ? 1 : 0,
413                 UserHandle.USER_CURRENT);
414     }
415 
416     /**
417      * Returns true if the feature flag for disabling system gestures on touchpads is enabled.
418      *
419      * @hide
420      */
isTouchpadSystemGestureDisableFeatureFlagEnabled()421     public static boolean isTouchpadSystemGestureDisableFeatureFlagEnabled() {
422         return touchpadSystemGestureDisable();
423     }
424 
425     /**
426      * Returns true if the feature flag for touchpad visualizer is enabled.
427      *
428      * @hide
429      */
isTouchpadVisualizerFeatureFlagEnabled()430     public static boolean isTouchpadVisualizerFeatureFlagEnabled() {
431         return touchpadVisualizer();
432     }
433 
434     /**
435      * Returns true if the feature flag for the touchpad three-finger tap shortcut is enabled.
436      *
437      * @hide
438      */
isTouchpadThreeFingerTapShortcutFeatureFlagEnabled()439     public static boolean isTouchpadThreeFingerTapShortcutFeatureFlagEnabled() {
440         return isCustomizableInputGesturesFeatureFlagEnabled() && touchpadThreeFingerTapShortcut();
441     }
442 
443     /**
444      * Returns true if the feature flag for toggling the mouse scrolling acceleration is enabled.
445      *
446      * @hide
447      */
isMouseScrollingAccelerationFeatureFlagEnabled()448     public static boolean isMouseScrollingAccelerationFeatureFlagEnabled() {
449         return mouseScrollingAcceleration();
450     }
451 
452     /**
453      * Returns true if the feature flag for mouse reverse vertical scrolling is enabled.
454      * @hide
455      */
isMouseReverseVerticalScrollingFeatureFlagEnabled()456     public static boolean isMouseReverseVerticalScrollingFeatureFlagEnabled() {
457         return mouseReverseVerticalScrolling();
458     }
459 
460     /**
461      * Returns true if the feature flag for mouse swap primary button is enabled.
462      * @hide
463      */
isMouseSwapPrimaryButtonFeatureFlagEnabled()464     public static boolean isMouseSwapPrimaryButtonFeatureFlagEnabled() {
465         return mouseSwapPrimaryButton();
466     }
467 
468     /**
469      * Returns true if the feature flag for the pointer acceleration toggle is
470      * enabled.
471      * @hide
472      */
isPointerAccelerationFeatureFlagEnabled()473     public static boolean isPointerAccelerationFeatureFlagEnabled() {
474         return pointerAcceleration();
475     }
476 
477     /**
478      * Returns true if the touchpad visualizer is allowed to appear.
479      *
480      * @param context The application context.
481      * @return Whether it is allowed to show touchpad visualizer or not.
482      *
483      * @hide
484      */
useTouchpadVisualizer(@onNull Context context)485     public static boolean useTouchpadVisualizer(@NonNull Context context) {
486         if (!isTouchpadVisualizerFeatureFlagEnabled()) {
487             return false;
488         }
489         return Settings.System.getIntForUser(context.getContentResolver(),
490                 Settings.System.TOUCHPAD_VISUALIZER, 0, UserHandle.USER_CURRENT) == 1;
491     }
492 
493     /**
494      * Sets the touchpad visualizer behaviour.
495      *
496      * @param context The application context.
497      * @param enabled Will enable touchpad visualizer if true, disable it if false
498      *
499      * @hide
500      */
501     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadVisualizer(@onNull Context context, boolean enabled)502     public static void setTouchpadVisualizer(@NonNull Context context, boolean enabled) {
503         if (!isTouchpadVisualizerFeatureFlagEnabled()) {
504             return;
505         }
506         Settings.System.putIntForUser(context.getContentResolver(),
507                 Settings.System.TOUCHPAD_VISUALIZER, enabled ? 1 : 0, UserHandle.USER_CURRENT);
508     }
509 
510     /**
511      * Returns true if the touchpad should allow tap dragging.
512      *
513      * The returned value only applies to gesture-compatible touchpads.
514      *
515      * @param context The application context.
516      * @return Whether the touchpad should allow tap dragging.
517      *
518      * @hide
519      */
useTouchpadTapDragging(@onNull Context context)520     public static boolean useTouchpadTapDragging(@NonNull Context context) {
521         return Settings.System.getIntForUser(context.getContentResolver(),
522                 Settings.System.TOUCHPAD_TAP_DRAGGING, 0, UserHandle.USER_CURRENT) == 1;
523     }
524 
525     /**
526      * Sets the tap dragging behavior for the touchpad.
527      *
528      * The new behavior is only applied to gesture-compatible touchpads.
529      *
530      * @param context The application context.
531      * @param enabled Will enable tap dragging if true, disable it if false
532      *
533      * @hide
534      */
535     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadTapDragging(@onNull Context context, boolean enabled)536     public static void setTouchpadTapDragging(@NonNull Context context, boolean enabled) {
537         Settings.System.putIntForUser(context.getContentResolver(),
538                 Settings.System.TOUCHPAD_TAP_DRAGGING, enabled ? 1 : 0,
539                 UserHandle.USER_CURRENT);
540     }
541 
542     /**
543      * Returns true if the touchpad should use the right click zone.
544      *
545      * The returned value only applies to gesture-compatible touchpads.
546      *
547      * @param context The application context.
548      * @return Whether the touchpad should use the right click zone.
549      *
550      * @hide
551      */
useTouchpadRightClickZone(@onNull Context context)552     public static boolean useTouchpadRightClickZone(@NonNull Context context) {
553         return Settings.System.getIntForUser(context.getContentResolver(),
554                 Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, 0, UserHandle.USER_CURRENT) == 1;
555     }
556 
557     /**
558      * Sets the right click zone behavior for the touchpad.
559      *
560      * The new behavior is only applied to gesture-compatible touchpads.
561      *
562      * @param context The application context.
563      * @param enabled Will enable the right click zone if true, disable it if false
564      *
565      * @hide
566      */
567     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadRightClickZone(@onNull Context context, boolean enabled)568     public static void setTouchpadRightClickZone(@NonNull Context context, boolean enabled) {
569         Settings.System.putIntForUser(context.getContentResolver(),
570                 Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, enabled ? 1 : 0,
571                 UserHandle.USER_CURRENT);
572     }
573 
574     /**
575      * Returns true if three-finger taps on the touchpad should trigger a customizable shortcut
576      * rather than a middle click.
577      *
578      * The returned value only applies to gesture-compatible touchpads.
579      *
580      * @param context The application context.
581      * @return Whether three-finger taps should trigger the shortcut.
582      *
583      * @hide
584      */
useTouchpadThreeFingerTapShortcut(@onNull Context context)585     public static boolean useTouchpadThreeFingerTapShortcut(@NonNull Context context) {
586         int customizedShortcut = Settings.System.getIntForUser(context.getContentResolver(),
587                 Settings.System.TOUCHPAD_THREE_FINGER_TAP_CUSTOMIZATION,
588                 KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED, UserHandle.USER_CURRENT);
589         return customizedShortcut != KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED
590                 && isTouchpadThreeFingerTapShortcutFeatureFlagEnabled();
591     }
592 
593     /**
594      * Returns true if system gestures (three- and four-finger swipes) should be enabled for
595      * touchpads.
596      *
597      * @param context The application context.
598      * @return Whether system gestures on touchpads are enabled
599      *
600      * @hide
601      */
useTouchpadSystemGestures(@onNull Context context)602     public static boolean useTouchpadSystemGestures(@NonNull Context context) {
603         if (!isTouchpadSystemGestureDisableFeatureFlagEnabled()) {
604             return true;
605         }
606         return Settings.System.getIntForUser(context.getContentResolver(),
607                 Settings.System.TOUCHPAD_SYSTEM_GESTURES, 1, UserHandle.USER_CURRENT) == 1;
608     }
609 
610     /**
611      * Sets whether system gestures are enabled for touchpads.
612      *
613      * @param context The application context.
614      * @param enabled True to enable system gestures.
615      *
616      * @hide
617      */
618     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadSystemGesturesEnabled(@onNull Context context, boolean enabled)619     public static void setTouchpadSystemGesturesEnabled(@NonNull Context context, boolean enabled) {
620         if (!isTouchpadSystemGestureDisableFeatureFlagEnabled()) {
621             return;
622         }
623         Settings.System.putIntForUser(context.getContentResolver(),
624                 Settings.System.TOUCHPAD_SYSTEM_GESTURES, enabled ? 1 : 0, UserHandle.USER_CURRENT);
625     }
626 
627     /**
628      * Whether a pointer icon will be shown over the location of a stylus pointer.
629      *
630      * @hide
631      */
isStylusPointerIconEnabled(@onNull Context context, boolean forceReloadSetting)632     public static boolean isStylusPointerIconEnabled(@NonNull Context context,
633             boolean forceReloadSetting) {
634         if (InputProperties.force_enable_stylus_pointer_icon().orElse(false)) {
635             // Sysprop override is set
636             return true;
637         }
638         if (!context.getResources().getBoolean(
639                 com.android.internal.R.bool.config_enableStylusPointerIcon)) {
640             // Stylus pointer icons are disabled for the build
641             return false;
642         }
643         if (forceReloadSetting) {
644             return Settings.Secure.getIntForUser(context.getContentResolver(),
645                     Settings.Secure.STYLUS_POINTER_ICON_ENABLED,
646                     DEFAULT_STYLUS_POINTER_ICON_ENABLED, UserHandle.USER_CURRENT_OR_SELF) != 0;
647         }
648         return AppGlobals.getIntCoreSetting(Settings.Secure.STYLUS_POINTER_ICON_ENABLED,
649                 DEFAULT_STYLUS_POINTER_ICON_ENABLED) != 0;
650     }
651 
652     /**
653      * Whether a pointer icon will be shown over the location of a stylus pointer.
654      *
655      * @hide
656      * @see #isStylusPointerIconEnabled(Context, boolean)
657      */
isStylusPointerIconEnabled(@onNull Context context)658     public static boolean isStylusPointerIconEnabled(@NonNull Context context) {
659         return isStylusPointerIconEnabled(context, false /* forceReloadSetting */);
660     }
661 
662     /**
663      * Whether mouse scrolling acceleration is enabled. This applies only to connected mice.
664      *
665      * @param context The application context.
666      * @return Whether the mouse scrolling is accelerated based on the user's scrolling speed.
667      *
668      * @hide
669      */
isMouseScrollingAccelerationEnabled(@onNull Context context)670     public static boolean isMouseScrollingAccelerationEnabled(@NonNull Context context) {
671         if (!isMouseScrollingAccelerationFeatureFlagEnabled()) {
672             return true;
673         }
674 
675         return Settings.System.getIntForUser(context.getContentResolver(),
676             Settings.System.MOUSE_SCROLLING_ACCELERATION, 0, UserHandle.USER_CURRENT) != 0;
677     }
678 
679     /**
680      * Sets whether the connected mouse scrolling acceleration is enabled.
681      *
682      * @param context The application context.
683      * @param scrollingAcceleration Whether mouse scrolling acceleration is enabled.
684      *
685      * @hide
686      */
687     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setMouseScrollingAcceleration(@onNull Context context, boolean scrollingAcceleration)688     public static void setMouseScrollingAcceleration(@NonNull Context context,
689             boolean scrollingAcceleration) {
690         if (!isMouseScrollingAccelerationFeatureFlagEnabled()) {
691             return;
692         }
693 
694         Settings.System.putIntForUser(context.getContentResolver(),
695                 Settings.System.MOUSE_SCROLLING_ACCELERATION, scrollingAcceleration ? 1 : 0,
696                 UserHandle.USER_CURRENT);
697     }
698 
699     /**
700      * Gets the mouse scrolling speed.
701      *
702      * The returned value only applies when mouse scrolling acceleration is not enabled.
703      *
704      * @param context The application context.
705      * @return The mouse scrolling speed as a value between {@link #MIN_MOUSE_SCROLLING_SPEED} and
706      *         {@link #MAX_MOUSE_SCROLLING_SPEED}, or the default value
707      *         {@link #DEFAULT_MOUSE_SCROLLING_SPEED}.
708      *
709      * @hide
710      */
getMouseScrollingSpeed(@onNull Context context)711     public static int getMouseScrollingSpeed(@NonNull Context context) {
712         if (!isMouseScrollingAccelerationFeatureFlagEnabled()) {
713             return 0;
714         }
715 
716         return Settings.System.getIntForUser(context.getContentResolver(),
717                 Settings.System.MOUSE_SCROLLING_SPEED, DEFAULT_MOUSE_SCROLLING_SPEED,
718                 UserHandle.USER_CURRENT);
719     }
720 
721     /**
722      * Sets the mouse scrolling speed, and saves it in the settings.
723      *
724      * The new speed will only apply when mouse scrolling acceleration is not enabled.
725      *
726      * @param context The application context.
727      * @param speed The mouse scrolling speed as a value between {@link #MIN_MOUSE_SCROLLING_SPEED}
728      *              and {@link #MAX_MOUSE_SCROLLING_SPEED}, or the default value
729      *              {@link #DEFAULT_MOUSE_SCROLLING_SPEED}.
730      *
731      * @hide
732      */
733     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setMouseScrollingSpeed(@onNull Context context, int speed)734     public static void setMouseScrollingSpeed(@NonNull Context context, int speed) {
735         if (isMouseScrollingAccelerationEnabled(context)) {
736             return;
737         }
738 
739         if (speed < MIN_MOUSE_SCROLLING_SPEED || speed > MAX_MOUSE_SCROLLING_SPEED) {
740             throw new IllegalArgumentException("speed out of range");
741         }
742 
743         Settings.System.putIntForUser(context.getContentResolver(),
744                 Settings.System.MOUSE_SCROLLING_SPEED, speed, UserHandle.USER_CURRENT);
745     }
746 
747     /**
748      * Whether mouse vertical scrolling is reversed. This applies only to connected mice.
749      *
750      * @param context The application context.
751      * @return Whether the mouse will have its vertical scrolling reversed
752      * (scroll down to move up).
753      *
754      * @hide
755      */
isMouseReverseVerticalScrollingEnabled(@onNull Context context)756     public static boolean isMouseReverseVerticalScrollingEnabled(@NonNull Context context) {
757         if (!isMouseReverseVerticalScrollingFeatureFlagEnabled()) {
758             return false;
759         }
760 
761         return Settings.System.getIntForUser(context.getContentResolver(),
762                 Settings.System.MOUSE_REVERSE_VERTICAL_SCROLLING, 0, UserHandle.USER_CURRENT)
763                 != 0;
764     }
765 
766     /**
767      * Sets whether the connected mouse will have its vertical scrolling reversed.
768      *
769      * @param context The application context.
770      * @param reverseScrolling Whether reverse scrolling is enabled.
771      *
772      * @hide
773      */
774     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setMouseReverseVerticalScrolling(@onNull Context context, boolean reverseScrolling)775     public static void setMouseReverseVerticalScrolling(@NonNull Context context,
776             boolean reverseScrolling) {
777         if (!isMouseReverseVerticalScrollingFeatureFlagEnabled()) {
778             return;
779         }
780 
781         Settings.System.putIntForUser(context.getContentResolver(),
782                 Settings.System.MOUSE_REVERSE_VERTICAL_SCROLLING, reverseScrolling ? 1 : 0,
783                 UserHandle.USER_CURRENT);
784     }
785 
786     /**
787      * Whether the primary mouse button is swapped on connected mice.
788      *
789      * @param context The application context.
790      * @return Whether mice will have their primary buttons swapped, so that left clicking will
791      * perform the secondary action (e.g. show menu) and right clicking will perform the primary
792      * action.
793      *
794      * @hide
795      */
isMouseSwapPrimaryButtonEnabled(@onNull Context context)796     public static boolean isMouseSwapPrimaryButtonEnabled(@NonNull Context context) {
797         if (!isMouseSwapPrimaryButtonFeatureFlagEnabled()) {
798             return false;
799         }
800 
801         return Settings.System.getIntForUser(context.getContentResolver(),
802                 Settings.System.MOUSE_SWAP_PRIMARY_BUTTON, 0, UserHandle.USER_CURRENT)
803                 != 0;
804     }
805 
806     /**
807      * Sets whether mice will have their primary buttons swapped between left and right
808      * clicks.
809      *
810      * @param context The application context.
811      * @param swapPrimaryButton Whether swapping the primary button is enabled.
812      *
813      * @hide
814      */
815     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setMouseSwapPrimaryButton(@onNull Context context, boolean swapPrimaryButton)816     public static void setMouseSwapPrimaryButton(@NonNull Context context,
817             boolean swapPrimaryButton) {
818         if (!isMouseSwapPrimaryButtonFeatureFlagEnabled()) {
819             return;
820         }
821 
822         Settings.System.putIntForUser(context.getContentResolver(),
823                 Settings.System.MOUSE_SWAP_PRIMARY_BUTTON, swapPrimaryButton ? 1 : 0,
824                 UserHandle.USER_CURRENT);
825     }
826 
827     /**
828      * Whether cursor acceleration is enabled or not for connected mice.
829      *
830      * @param context The application context.
831      *
832      * @hide
833      */
isMousePointerAccelerationEnabled(@onNull Context context)834     public static boolean isMousePointerAccelerationEnabled(@NonNull Context context) {
835         if (!isPointerAccelerationFeatureFlagEnabled()) {
836             return true;
837         }
838 
839         return Settings.System.getIntForUser(context.getContentResolver(),
840                 Settings.System.MOUSE_POINTER_ACCELERATION_ENABLED, 1, UserHandle.USER_CURRENT)
841                 == 1;
842     }
843 
844    /**
845     * Sets whether mouse acceleration is enabled.
846     *
847     * When enabled, the mouse cursor moves farther when it is moved faster.
848     * When disabled, the mouse cursor speed becomes directly proportional to
849     * the speed at which the mouse is moved.
850     *
851     * @param context The application context.
852     * @param enabled Will enable mouse acceleration if true, disable it if
853     *                false.
854     * @hide
855     */
856     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setMouseAccelerationEnabled(@onNull Context context, boolean enabled)857     public static void setMouseAccelerationEnabled(@NonNull Context context,
858             boolean enabled) {
859         if (!isPointerAccelerationFeatureFlagEnabled()) {
860             return;
861         }
862         Settings.System.putIntForUser(context.getContentResolver(),
863                 Settings.System.MOUSE_POINTER_ACCELERATION_ENABLED, enabled ? 1 : 0,
864                 UserHandle.USER_CURRENT);
865     }
866 
867     /**
868      * Whether Accessibility bounce keys is enabled.
869      *
870      * <p>
871      * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
872      * that allows the user to configure the device to ignore rapid, repeated keypresses of the
873      * same key.
874      * </p>
875      *
876      * @hide
877      */
isAccessibilityBounceKeysEnabled(@onNull Context context)878     public static boolean isAccessibilityBounceKeysEnabled(@NonNull Context context) {
879         return getAccessibilityBounceKeysThreshold(context) != 0;
880     }
881 
882     /**
883      * Get Accessibility bounce keys threshold duration in milliseconds.
884      *
885      * <p>
886      * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
887      * that allows the user to configure the device to ignore rapid, repeated keypresses of the
888      * same key.
889      * </p>
890      *
891      * @hide
892      */
893     @TestApi
getAccessibilityBounceKeysThreshold(@onNull Context context)894     public static int getAccessibilityBounceKeysThreshold(@NonNull Context context) {
895         return Settings.Secure.getIntForUser(context.getContentResolver(),
896                 Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS, 0, UserHandle.USER_CURRENT);
897     }
898 
899     /**
900      * Set Accessibility bounce keys threshold duration in milliseconds.
901      * @param thresholdTimeMillis time duration for which a key down will be ignored after a
902      *                            previous key up for the same key on the same device between 0 and
903      *                            {@link MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS}
904      *
905      * <p>
906      * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
907      * that allows the user to configure the device to ignore rapid, repeated keypresses of the
908      * same key.
909      * </p>
910      *
911      * @hide
912      */
913     @TestApi
914     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setAccessibilityBounceKeysThreshold(@onNull Context context, int thresholdTimeMillis)915     public static void setAccessibilityBounceKeysThreshold(@NonNull Context context,
916             int thresholdTimeMillis) {
917         if (thresholdTimeMillis < 0
918                 || thresholdTimeMillis > MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS) {
919             throw new IllegalArgumentException(
920                     "Provided Bounce keys threshold should be in range [0, "
921                             + MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS + "]");
922         }
923         Settings.Secure.putIntForUser(context.getContentResolver(),
924                 Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS, thresholdTimeMillis,
925                 UserHandle.USER_CURRENT);
926     }
927 
928     /**
929      * Whether Accessibility slow keys is enabled.
930      *
931      * <p>
932      * 'Slow keys' is an accessibility feature to aid users who have physical disabilities, that
933      * allows the user to specify the duration for which one must press-and-hold a key before the
934      * system accepts the keypress.
935      * </p>
936      *
937      * @hide
938      */
isAccessibilitySlowKeysEnabled(@onNull Context context)939     public static boolean isAccessibilitySlowKeysEnabled(@NonNull Context context) {
940         return getAccessibilitySlowKeysThreshold(context) != 0;
941     }
942 
943     /**
944      * Get Accessibility slow keys threshold duration in milliseconds.
945      *
946      * <p>
947      * 'Slow keys' is an accessibility feature to aid users who have physical disabilities, that
948      * allows the user to specify the duration for which one must press-and-hold a key before the
949      * system accepts the keypress.
950      * </p>
951      *
952      * @hide
953      */
954     @TestApi
getAccessibilitySlowKeysThreshold(@onNull Context context)955     public static int getAccessibilitySlowKeysThreshold(@NonNull Context context) {
956         return Settings.Secure.getIntForUser(context.getContentResolver(),
957                 Settings.Secure.ACCESSIBILITY_SLOW_KEYS, 0, UserHandle.USER_CURRENT);
958     }
959 
960     /**
961      * Set Accessibility slow keys threshold duration in milliseconds.
962      * @param thresholdTimeMillis time duration for which a key should be pressed to be registered
963      *                            in the system. The threshold must be between 0 and
964      *                            {@link MAX_ACCESSIBILITY_SLOW_KEYS_THRESHOLD_MILLIS}
965      *
966      * <p>
967      * 'Slow keys' is an accessibility feature to aid users who have physical disabilities, that
968      * allows the user to specify the duration for which one must press-and-hold a key before the
969      * system accepts the keypress.
970      * </p>
971      *
972      * @hide
973      */
974     @TestApi
975     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setAccessibilitySlowKeysThreshold(@onNull Context context, int thresholdTimeMillis)976     public static void setAccessibilitySlowKeysThreshold(@NonNull Context context,
977             int thresholdTimeMillis) {
978         if (thresholdTimeMillis < 0
979                 || thresholdTimeMillis > MAX_ACCESSIBILITY_SLOW_KEYS_THRESHOLD_MILLIS) {
980             throw new IllegalArgumentException(
981                     "Provided Slow keys threshold should be in range [0, "
982                             + MAX_ACCESSIBILITY_SLOW_KEYS_THRESHOLD_MILLIS + "]");
983         }
984         Settings.Secure.putIntForUser(context.getContentResolver(),
985                 Settings.Secure.ACCESSIBILITY_SLOW_KEYS, thresholdTimeMillis,
986                 UserHandle.USER_CURRENT);
987     }
988 
989     /**
990      * Whether Accessibility sticky keys is enabled.
991      *
992      * <p>
993      * 'Sticky keys' is an accessibility feature that assists users who have physical
994      * disabilities or help users reduce repetitive strain injury. It serializes keystrokes
995      * instead of pressing multiple keys at a time, allowing the user to press and release a
996      * modifier key, such as Shift, Ctrl, Alt, or any other modifier key, and have it remain
997      * active until any other key is pressed.
998      * </p>
999      *
1000      * @hide
1001      */
1002     @TestApi
isAccessibilityStickyKeysEnabled(@onNull Context context)1003     public static boolean isAccessibilityStickyKeysEnabled(@NonNull Context context) {
1004         return Settings.Secure.getIntForUser(context.getContentResolver(),
1005                 Settings.Secure.ACCESSIBILITY_STICKY_KEYS, 0, UserHandle.USER_CURRENT) != 0;
1006     }
1007 
1008     /**
1009      * Set Accessibility sticky keys feature enabled/disabled.
1010      *
1011      *  <p>
1012      * 'Sticky keys' is an accessibility feature that assists users who have physical
1013      * disabilities or help users reduce repetitive strain injury. It serializes keystrokes
1014      * instead of pressing multiple keys at a time, allowing the user to press and release a
1015      * modifier key, such as Shift, Ctrl, Alt, or any other modifier key, and have it remain
1016      * active until any other key is pressed.
1017      * </p>
1018      *
1019      * @hide
1020      */
1021     @TestApi
1022     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setAccessibilityStickyKeysEnabled(@onNull Context context, boolean enabled)1023     public static void setAccessibilityStickyKeysEnabled(@NonNull Context context,
1024             boolean enabled) {
1025         Settings.Secure.putIntForUser(context.getContentResolver(),
1026                 Settings.Secure.ACCESSIBILITY_STICKY_KEYS, enabled ? 1 : 0,
1027                 UserHandle.USER_CURRENT);
1028     }
1029 
1030     /**
1031      * Whether Accessibility mouse keys feature flag is enabled.
1032      *
1033      * <p>
1034      * ‘Mouse keys’ is an accessibility feature to aid users who have physical disabilities,
1035      * that allows the user to use the keys on the keyboard to control the mouse pointer and
1036      * other perform other mouse functionality.
1037      * </p>
1038      *
1039      * @hide
1040      */
isAccessibilityMouseKeysFeatureFlagEnabled()1041     public static boolean isAccessibilityMouseKeysFeatureFlagEnabled() {
1042         return keyboardA11yMouseKeys();
1043     }
1044 
1045     /**
1046      * Whether Accessibility mouse keys is enabled.
1047      *
1048      * <p>
1049      * ‘Mouse keys’ is an accessibility feature to aid users who have physical disabilities,
1050      * that allows the user to use the keys on the keyboard to control the mouse pointer and
1051      * other perform other mouse functionality.
1052      * </p>
1053      *
1054      * @hide
1055      */
1056     @TestApi
1057     @FlaggedApi(FLAG_KEYBOARD_A11Y_MOUSE_KEYS)
isAccessibilityMouseKeysEnabled(@onNull Context context)1058     public static boolean isAccessibilityMouseKeysEnabled(@NonNull Context context) {
1059         if (!isAccessibilityMouseKeysFeatureFlagEnabled()) {
1060             return false;
1061         }
1062         return Settings.Secure.getIntForUser(context.getContentResolver(),
1063                 Settings.Secure.ACCESSIBILITY_MOUSE_KEYS_ENABLED, 0, UserHandle.USER_CURRENT)
1064                 != 0;
1065     }
1066 
1067     /**
1068      * Set Accessibility mouse keys feature enabled/disabled.
1069      *
1070      *  <p>
1071      * ‘Mouse keys’ is an accessibility feature to aid users who have physical disabilities,
1072      * that allows the user to use the keys on the keyboard to control the mouse pointer and
1073      * other perform other mouse functionality.
1074      * </p>
1075      *
1076      * @hide
1077      */
1078     @TestApi
1079     @FlaggedApi(FLAG_KEYBOARD_A11Y_MOUSE_KEYS)
1080     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setAccessibilityMouseKeysEnabled(@onNull Context context, boolean enabled)1081     public static void setAccessibilityMouseKeysEnabled(@NonNull Context context,
1082             boolean enabled) {
1083         if (!isAccessibilityMouseKeysFeatureFlagEnabled()) {
1084             return;
1085         }
1086         Settings.Secure.putIntForUser(context.getContentResolver(),
1087                 Settings.Secure.ACCESSIBILITY_MOUSE_KEYS_ENABLED, enabled ? 1 : 0,
1088                 UserHandle.USER_CURRENT);
1089     }
1090 
1091     /**
1092      * Whether "Repeat keys" feature flag is enabled.
1093      *
1094      * <p>
1095      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
1096      * key on the physical keyboard is held down. This feature allows the user
1097      * to configure the timeout before the key repeats begin as well as the delay
1098      * between successive key repeats.
1099      * </p>
1100      *
1101      * @hide
1102      */
isRepeatKeysFeatureFlagEnabled()1103     public static boolean isRepeatKeysFeatureFlagEnabled() {
1104         return keyboardRepeatKeys();
1105     }
1106 
1107     /**
1108      * Whether "Repeat keys" feature is enabled.
1109      * Repeat keys is ON by default.
1110      * The repeat keys timeout and delay would have the default values in the default ON case.
1111      *
1112      * <p>
1113      * 'Repeat keys’ is a feature which allows users to generate key repeats when a particular
1114      * key on the physical keyboard is held down. This feature allows the user
1115      * to configure the timeout before the key repeats begin as well as the delay
1116      * between successive key repeats.
1117      * </p>
1118      *
1119      * @hide
1120      */
1121     @TestApi
1122     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
isRepeatKeysEnabled(@onNull Context context)1123     public static boolean isRepeatKeysEnabled(@NonNull Context context) {
1124         if (!isRepeatKeysFeatureFlagEnabled()) {
1125             return true;
1126         }
1127         return Settings.Secure.getIntForUser(context.getContentResolver(),
1128                 Settings.Secure.KEY_REPEAT_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
1129     }
1130 
1131     /**
1132      * Get repeat keys timeout duration in milliseconds.
1133      * The default key repeat timeout is {@link ViewConfiguration#DEFAULT_KEY_REPEAT_TIMEOUT_MS}.
1134      *
1135      * @param context The application context
1136      * @return The time duration for which a key should be pressed after
1137      *         which the pressed key will be repeated. The timeout must be between
1138      *         {@link #MIN_KEY_REPEAT_TIMEOUT_MILLIS} and
1139      *         {@link #MAX_KEY_REPEAT_TIMEOUT_MILLIS}
1140      *
1141      * <p>
1142      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
1143      * key on the physical keyboard is held down. This feature allows the user
1144      * to configure the timeout before the key repeats begin as well as the delay
1145      * between successive key repeats.
1146      * </p>
1147      *
1148      * @hide
1149      */
1150     @TestApi
1151     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
getRepeatKeysTimeout(@onNull Context context)1152     public static int getRepeatKeysTimeout(@NonNull Context context) {
1153         if (!isRepeatKeysFeatureFlagEnabled()) {
1154             return ViewConfiguration.getKeyRepeatTimeout();
1155         }
1156         return Settings.Secure.getIntForUser(context.getContentResolver(),
1157                 Settings.Secure.KEY_REPEAT_TIMEOUT_MS, ViewConfiguration.getKeyRepeatTimeout(),
1158                 UserHandle.USER_CURRENT);
1159     }
1160 
1161     /**
1162      * Get repeat keys delay rate in milliseconds.
1163      * The default key repeat delay is {@link ViewConfiguration#DEFAULT_KEY_REPEAT_DELAY_MS}.
1164      *
1165      * @param context The application context
1166      * @return Time duration between successive key repeats when a key is
1167      *         pressed down. The delay duration must be between
1168      *         {@link #MIN_KEY_REPEAT_DELAY_MILLIS} and
1169      *         {@link #MAX_KEY_REPEAT_DELAY_MILLIS}
1170      *
1171      * <p>
1172      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
1173      * key on the physical keyboard is held down. This feature allows the user
1174      * to configure the timeout before the key repeats begin as well as the delay
1175      * between successive key repeats.
1176      * </p>
1177      *
1178      * @hide
1179      */
1180     @TestApi
1181     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
getRepeatKeysDelay(@onNull Context context)1182     public static int getRepeatKeysDelay(@NonNull Context context) {
1183         if (!isRepeatKeysFeatureFlagEnabled()) {
1184             return ViewConfiguration.getKeyRepeatDelay();
1185         }
1186         return Settings.Secure.getIntForUser(context.getContentResolver(),
1187                 Settings.Secure.KEY_REPEAT_DELAY_MS, ViewConfiguration.getKeyRepeatDelay(),
1188                 UserHandle.USER_CURRENT);
1189     }
1190 
1191     /**
1192      * Set repeat keys feature enabled/disabled.
1193      *
1194      * <p>
1195      * 'Repeat keys’ is a feature which allows users to generate key repeats when a particular
1196      * key on the physical keyboard is held down. This feature allows the user
1197      * to configure the timeout before the key repeats begin as well as the delay
1198      * between successive key repeats.
1199      * </p>
1200      *
1201      * @hide
1202      */
1203     @TestApi
1204     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
1205     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setRepeatKeysEnabled(@onNull Context context, boolean enabled)1206     public static void setRepeatKeysEnabled(@NonNull Context context,
1207             boolean enabled) {
1208         if (!isRepeatKeysFeatureFlagEnabled()) {
1209             return;
1210         }
1211         Settings.Secure.putIntForUser(context.getContentResolver(),
1212                 Settings.Secure.KEY_REPEAT_ENABLED, enabled ? 1 : 0, UserHandle.USER_CURRENT);
1213     }
1214 
1215     /**
1216      * Set repeat keys timeout duration in milliseconds.
1217      *
1218      * @param timeoutTimeMillis time duration for which a key should be pressed after which the
1219      *                          pressed key will be repeated. The timeout must be between
1220      *                          {@link #MIN_KEY_REPEAT_TIMEOUT_MILLIS} and
1221      *                          {@link #MAX_KEY_REPEAT_TIMEOUT_MILLIS}
1222      *
1223      *  <p>
1224      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
1225      * key on the physical keyboard is held down. This feature allows the user
1226      * to configure the timeout before the key repeats begin as well as the delay
1227      *  between successive key repeats.
1228      * </p>
1229      *
1230      * @hide
1231      */
1232     @TestApi
1233     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
1234     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setRepeatKeysTimeout(@onNull Context context, int timeoutTimeMillis)1235     public static void setRepeatKeysTimeout(@NonNull Context context,
1236             int timeoutTimeMillis) {
1237         if (!isRepeatKeysFeatureFlagEnabled()
1238                 && !isRepeatKeysEnabled(context)) {
1239             return;
1240         }
1241         if (timeoutTimeMillis < MIN_KEY_REPEAT_TIMEOUT_MILLIS
1242                 || timeoutTimeMillis > MAX_KEY_REPEAT_TIMEOUT_MILLIS) {
1243             throw new IllegalArgumentException(
1244                     "Provided repeat keys timeout should be in range ("
1245                             + MIN_KEY_REPEAT_TIMEOUT_MILLIS + ","
1246                             + MAX_KEY_REPEAT_TIMEOUT_MILLIS + ")");
1247         }
1248         Settings.Secure.putIntForUser(context.getContentResolver(),
1249                 Settings.Secure.KEY_REPEAT_TIMEOUT_MS, timeoutTimeMillis,
1250                 UserHandle.USER_CURRENT);
1251     }
1252 
1253     /**
1254      * Set repeat key delay duration in milliseconds.
1255      *
1256      * @param delayTimeMillis Time duration between successive key repeats when a key is
1257      *                        pressed down. The delay duration must be between
1258      *                        {@link #MIN_KEY_REPEAT_DELAY_MILLIS} and
1259      *                        {@link #MAX_KEY_REPEAT_DELAY_MILLIS}
1260      * <p>
1261      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
1262      * key on the physical keyboard is held down. This feature allows the user
1263      * to configure the timeout before the key repeats begin as well as the delay
1264      * between successive key repeats.
1265      * </p>
1266      *
1267      * @hide
1268      */
1269     @TestApi
1270     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
1271     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setRepeatKeysDelay(@onNull Context context, int delayTimeMillis)1272     public static void setRepeatKeysDelay(@NonNull Context context,
1273             int delayTimeMillis) {
1274         if (!isRepeatKeysFeatureFlagEnabled()
1275                 && !isRepeatKeysEnabled(context)) {
1276             return;
1277         }
1278         if (delayTimeMillis < MIN_KEY_REPEAT_DELAY_MILLIS
1279                 || delayTimeMillis > MAX_KEY_REPEAT_DELAY_MILLIS) {
1280             throw new IllegalArgumentException(
1281                     "Provided repeat keys delay should be in range ("
1282                             + MIN_KEY_REPEAT_DELAY_MILLIS + ","
1283                             + MAX_KEY_REPEAT_DELAY_MILLIS + ")");
1284         }
1285         Settings.Secure.putIntForUser(context.getContentResolver(),
1286                 Settings.Secure.KEY_REPEAT_DELAY_MS, delayTimeMillis,
1287                 UserHandle.USER_CURRENT);
1288     }
1289 
1290     /**
1291      * Whether "Customizable key gestures" feature flag is enabled.
1292      *
1293      * <p>
1294      * ‘Customizable key gestures’ is a feature which allows users to customize key based
1295      * shortcuts on the physical keyboard.
1296      * </p>
1297      *
1298      * @hide
1299      */
isCustomizableInputGesturesFeatureFlagEnabled()1300     public static boolean isCustomizableInputGesturesFeatureFlagEnabled() {
1301         return enableCustomizableInputGestures() && useKeyGestureEventHandler();
1302     }
1303 
1304     /**
1305      * Whether multi-key gestures are supported using {@code KeyGestureEventHandler}
1306      *
1307      * @hide
1308      */
doesKeyGestureEventHandlerSupportMultiKeyGestures()1309     public static boolean doesKeyGestureEventHandlerSupportMultiKeyGestures() {
1310         return useKeyGestureEventHandler() && useKeyGestureEventHandlerMultiKeyGestures();
1311     }
1312 }
1313