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