1 /* 2 * Copyright (C) 2006 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.view; 18 19 import android.annotation.FloatRange; 20 import android.annotation.NonNull; 21 import android.annotation.TestApi; 22 import android.annotation.UiContext; 23 import android.app.Activity; 24 import android.app.AppGlobals; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.content.Context; 27 import android.content.res.Configuration; 28 import android.content.res.Resources; 29 import android.graphics.Rect; 30 import android.hardware.input.InputManager; 31 import android.hardware.input.InputManagerGlobal; 32 import android.os.Build; 33 import android.os.Bundle; 34 import android.os.RemoteException; 35 import android.os.StrictMode; 36 import android.provider.Settings; 37 import android.util.DisplayMetrics; 38 import android.util.SparseArray; 39 import android.util.TypedValue; 40 import android.view.flags.Flags; 41 42 import com.android.internal.annotations.VisibleForTesting; 43 44 /** 45 * Contains methods to standard constants used in the UI for timeouts, sizes, and distances. 46 */ 47 public class ViewConfiguration { 48 private static final String TAG = "ViewConfiguration"; 49 50 /** 51 * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in 52 * dips 53 */ 54 private static final int SCROLL_BAR_SIZE = 4; 55 56 /** 57 * Duration of the fade when scrollbars fade away in milliseconds 58 */ 59 private static final int SCROLL_BAR_FADE_DURATION = 250; 60 61 /** 62 * Default delay before the scrollbars fade in milliseconds 63 */ 64 private static final int SCROLL_BAR_DEFAULT_DELAY = 300; 65 66 /** 67 * Defines the length of the fading edges in dips 68 */ 69 private static final int FADING_EDGE_LENGTH = 12; 70 71 /** 72 * Defines the duration in milliseconds of the pressed state in child 73 * components. 74 */ 75 private static final int PRESSED_STATE_DURATION = 64; 76 77 /** 78 * Defines the default duration in milliseconds before a press turns into 79 * a long press 80 * @hide 81 */ 82 public static final int DEFAULT_LONG_PRESS_TIMEOUT = 400; 83 84 /** 85 * Defines the default duration in milliseconds between the first tap's up event and the second 86 * tap's down event for an interaction to be considered part of the same multi-press. 87 */ 88 private static final int DEFAULT_MULTI_PRESS_TIMEOUT = 300; 89 90 /** 91 * Defines the default duration in milliseconds between a key being pressed and its first key 92 * repeat event being generated. Historically, Android used the long press timeout as the 93 * key repeat timeout, so its default value is set to long press timeout's default. 94 */ 95 private static final int DEFAULT_KEY_REPEAT_TIMEOUT_MS = DEFAULT_LONG_PRESS_TIMEOUT; 96 97 /** 98 * Defines the default duration between successive key repeats in milliseconds. 99 */ 100 private static final int DEFAULT_KEY_REPEAT_DELAY_MS = 50; 101 102 /** 103 * Defines the duration in milliseconds a user needs to hold down the 104 * appropriate button to bring up the global actions dialog (power off, 105 * lock screen, etc). 106 */ 107 private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500; 108 109 /** 110 * Defines the duration in milliseconds a user needs to hold down the 111 * appropriate buttons (power + volume down) to trigger the screenshot chord. 112 */ 113 private static final int SCREENSHOT_CHORD_KEY_TIMEOUT = 0; 114 115 /** 116 * Defines the duration in milliseconds a user needs to hold down the 117 * appropriate button to bring up the accessibility shortcut for the first time 118 */ 119 private static final int A11Y_SHORTCUT_KEY_TIMEOUT = 3000; 120 121 /** 122 * Defines the duration in milliseconds a user needs to hold down the 123 * appropriate button to enable the accessibility shortcut once it's configured. 124 */ 125 private static final int A11Y_SHORTCUT_KEY_TIMEOUT_AFTER_CONFIRMATION = 1000; 126 127 /** 128 * Defines the duration in milliseconds we will wait to see if a touch event 129 * is a tap or a scroll. If the user does not move within this interval, it is 130 * considered to be a tap. 131 */ 132 private static final int TAP_TIMEOUT = 100; 133 134 /** 135 * Defines the duration in milliseconds we will wait to see if a touch event 136 * is a jump tap. If the user does not complete the jump tap within this interval, it is 137 * considered to be a tap. 138 */ 139 private static final int JUMP_TAP_TIMEOUT = 500; 140 141 /** 142 * Defines the duration in milliseconds between the first tap's up event and 143 * the second tap's down event for an interaction to be considered a 144 * double-tap. 145 */ 146 private static final int DOUBLE_TAP_TIMEOUT = 300; 147 148 /** 149 * Defines the minimum duration in milliseconds between the first tap's up event and 150 * the second tap's down event for an interaction to be considered a 151 * double-tap. 152 */ 153 private static final int DOUBLE_TAP_MIN_TIME = 40; 154 155 /** 156 * Defines the maximum duration in milliseconds between a touch pad 157 * touch and release for a given touch to be considered a tap (click) as 158 * opposed to a hover movement gesture. 159 */ 160 private static final int HOVER_TAP_TIMEOUT = 150; 161 162 /** 163 * Defines the maximum distance in pixels that a touch pad touch can move 164 * before being released for it to be considered a tap (click) as opposed 165 * to a hover movement gesture. 166 */ 167 private static final int HOVER_TAP_SLOP = 20; 168 169 /** 170 * Defines the duration in milliseconds we want to display zoom controls in response 171 * to a user panning within an application. 172 */ 173 private static final int ZOOM_CONTROLS_TIMEOUT = 3000; 174 175 /** 176 * Inset in dips to look for touchable content when the user touches the edge of the screen 177 */ 178 private static final int EDGE_SLOP = 12; 179 180 /** 181 * Distance a touch can wander before we think the user is scrolling in dips. 182 * Note that this value defined here is only used as a fallback by legacy/misbehaving 183 * applications that do not provide a Context for determining density/configuration-dependent 184 * values. 185 * 186 * To alter this value, see the configuration resource config_viewConfigurationTouchSlop 187 * in frameworks/base/core/res/res/values/config.xml or the appropriate device resource overlay. 188 * It may be appropriate to tweak this on a device-specific basis in an overlay based on 189 * the characteristics of the touch panel and firmware. 190 */ 191 private static final int TOUCH_SLOP = 8; 192 193 /** Distance a stylus touch can wander before we think the user is handwriting in dips. */ 194 private static final int HANDWRITING_SLOP = 2; 195 196 /** 197 * Defines the minimum size of the touch target for a scrollbar in dips 198 */ 199 private static final int MIN_SCROLLBAR_TOUCH_TARGET = 48; 200 201 /** 202 * Distance the first touch can wander before we stop considering this event a double tap 203 * (in dips) 204 */ 205 private static final int DOUBLE_TAP_TOUCH_SLOP = TOUCH_SLOP; 206 207 /** 208 * Distance a touch can wander before we think the user is attempting a paged scroll 209 * (in dips) 210 * 211 * Note that this value defined here is only used as a fallback by legacy/misbehaving 212 * applications that do not provide a Context for determining density/configuration-dependent 213 * values. 214 * 215 * See the note above on {@link #TOUCH_SLOP} regarding the dimen resource 216 * config_viewConfigurationTouchSlop. ViewConfiguration will report a paging touch slop of 217 * config_viewConfigurationTouchSlop * 2 when provided with a Context. 218 */ 219 private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2; 220 221 /** 222 * Distance in dips between the first touch and second touch to still be considered a double tap 223 */ 224 private static final int DOUBLE_TAP_SLOP = 100; 225 226 /** 227 * Distance in dips a touch needs to be outside of a window's bounds for it to 228 * count as outside for purposes of dismissing the window. 229 */ 230 private static final int WINDOW_TOUCH_SLOP = 16; 231 232 /** 233 * Margin in dips around text line bounds where stylus handwriting gestures should be supported. 234 */ 235 private static final int HANDWRITING_GESTURE_LINE_MARGIN = 16; 236 237 /** 238 * Minimum velocity to initiate a fling, as measured in dips per second 239 */ 240 private static final int MINIMUM_FLING_VELOCITY = 50; 241 242 /** 243 * Maximum velocity to initiate a fling, as measured in dips per second 244 */ 245 private static final int MAXIMUM_FLING_VELOCITY = 8000; 246 247 /** Value used as a minimum fling velocity, when fling is not supported. */ 248 private static final int NO_FLING_MIN_VELOCITY = Integer.MAX_VALUE; 249 250 /** Value used as a maximum fling velocity, when fling is not supported. */ 251 private static final int NO_FLING_MAX_VELOCITY = Integer.MIN_VALUE; 252 253 /** @hide */ 254 public static final int NO_HAPTIC_SCROLL_TICK_INTERVAL = Integer.MAX_VALUE; 255 256 /** 257 * Delay before dispatching a recurring accessibility event in milliseconds. 258 * This delay guarantees that a recurring event will be send at most once 259 * during the {@link #SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS} time 260 * frame. 261 */ 262 private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 100; 263 264 /** 265 * The maximum size of View's drawing cache, expressed in bytes. This size 266 * should be at least equal to the size of the screen in ARGB888 format. 267 */ 268 @Deprecated 269 private static final int MAXIMUM_DRAWING_CACHE_SIZE = 480 * 800 * 4; // ARGB8888 270 271 /** 272 * The coefficient of friction applied to flings/scrolls. 273 */ 274 @UnsupportedAppUsage 275 private static final float SCROLL_FRICTION = 0.015f; 276 277 /** 278 * Max distance in dips to overscroll for edge effects 279 */ 280 private static final int OVERSCROLL_DISTANCE = 0; 281 282 /** 283 * Max distance in dips to overfling for edge effects 284 */ 285 private static final int OVERFLING_DISTANCE = 6; 286 287 /** 288 * Amount to scroll in response to a horizontal {@link MotionEvent#ACTION_SCROLL} event, 289 * in dips per axis value. 290 */ 291 private static final float HORIZONTAL_SCROLL_FACTOR = 64; 292 293 /** 294 * Amount to scroll in response to a vertical {@link MotionEvent#ACTION_SCROLL} event, 295 * in dips per axis value. 296 */ 297 private static final float VERTICAL_SCROLL_FACTOR = 64; 298 299 /** 300 * Default duration to hide an action mode for. 301 */ 302 private static final long ACTION_MODE_HIDE_DURATION_DEFAULT = 2000; 303 304 /** 305 * Defines the duration in milliseconds before an end of a long press causes a tooltip to be 306 * hidden. 307 */ 308 private static final int LONG_PRESS_TOOLTIP_HIDE_TIMEOUT = 1500; 309 310 /** 311 * Defines the duration in milliseconds before a hover event causes a tooltip to be shown. 312 */ 313 private static final int HOVER_TOOLTIP_SHOW_TIMEOUT = 500; 314 315 /** 316 * Defines the duration in milliseconds before mouse inactivity causes a tooltip to be hidden. 317 * (default variant to be used when {@link View#SYSTEM_UI_FLAG_LOW_PROFILE} is not set). 318 */ 319 private static final int HOVER_TOOLTIP_HIDE_TIMEOUT = 15000; 320 321 /** 322 * Defines the duration in milliseconds before mouse inactivity causes a tooltip to be hidden 323 * (short version to be used when {@link View#SYSTEM_UI_FLAG_LOW_PROFILE} is set). 324 */ 325 private static final int HOVER_TOOLTIP_HIDE_SHORT_TIMEOUT = 3000; 326 327 /** 328 * Configuration values for overriding {@link #hasPermanentMenuKey()} behavior. 329 * These constants must match the definition in res/values/config.xml. 330 */ 331 private static final int HAS_PERMANENT_MENU_KEY_AUTODETECT = 0; 332 private static final int HAS_PERMANENT_MENU_KEY_TRUE = 1; 333 private static final int HAS_PERMANENT_MENU_KEY_FALSE = 2; 334 335 /** 336 * The multiplication factor for inhibiting default gestures. 337 */ 338 private static final float AMBIGUOUS_GESTURE_MULTIPLIER = 2f; 339 340 /** 341 * The timeout value in milliseconds to adjust the selection span and actions for the selected 342 * text when TextClassifier has been initialized. 343 */ 344 private static final int SMART_SELECTION_INITIALIZED_TIMEOUT_IN_MILLISECOND = 200; 345 346 /** 347 * The timeout value in milliseconds to adjust the selection span and actions for the selected 348 * text when TextClassifier has not been initialized. 349 */ 350 private static final int SMART_SELECTION_INITIALIZING_TIMEOUT_IN_MILLISECOND = 500; 351 352 private final boolean mConstructedWithContext; 353 private final int mEdgeSlop; 354 private final int mFadingEdgeLength; 355 private final int mMinimumFlingVelocity; 356 private final int mMaximumFlingVelocity; 357 private final int mMinimumRotaryEncoderFlingVelocity; 358 private final int mMaximumRotaryEncoderFlingVelocity; 359 private final int mRotaryEncoderHapticScrollFeedbackTickIntervalPixels; 360 private final boolean mRotaryEncoderHapticScrollFeedbackEnabled; 361 private final int mScrollbarSize; 362 private final int mTouchSlop; 363 private final int mHandwritingSlop; 364 private final int mMinScalingSpan; 365 private final int mHoverSlop; 366 private final int mMinScrollbarTouchTarget; 367 private final int mDoubleTapTouchSlop; 368 private final int mPagingTouchSlop; 369 private final int mDoubleTapSlop; 370 private final int mWindowTouchSlop; 371 private final int mHandwritingGestureLineMargin; 372 private final float mAmbiguousGestureMultiplier; 373 private final int mMaximumDrawingCacheSize; 374 private final int mOverscrollDistance; 375 private final int mOverflingDistance; 376 @UnsupportedAppUsage 377 private final boolean mFadingMarqueeEnabled; 378 private final long mGlobalActionsKeyTimeout; 379 private final float mVerticalScrollFactor; 380 private final float mHorizontalScrollFactor; 381 private final boolean mShowMenuShortcutsWhenKeyboardPresent; 382 private final long mScreenshotChordKeyTimeout; 383 private final int mSmartSelectionInitializedTimeout; 384 private final int mSmartSelectionInitializingTimeout; 385 private final boolean mPreferKeepClearForFocusEnabled; 386 private final boolean mViewBasedRotaryEncoderScrollHapticsEnabledConfig; 387 388 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768915) 389 private boolean sHasPermanentMenuKey; 390 @UnsupportedAppUsage 391 private boolean sHasPermanentMenuKeySet; 392 393 @UnsupportedAppUsage 394 static final SparseArray<ViewConfiguration> sConfigurations = 395 new SparseArray<ViewConfiguration>(2); 396 397 /** 398 * @deprecated Use {@link android.view.ViewConfiguration#get(android.content.Context)} instead. 399 */ 400 @Deprecated ViewConfiguration()401 public ViewConfiguration() { 402 mConstructedWithContext = false; 403 mEdgeSlop = EDGE_SLOP; 404 mFadingEdgeLength = FADING_EDGE_LENGTH; 405 mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY; 406 mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY; 407 mMinimumRotaryEncoderFlingVelocity = MINIMUM_FLING_VELOCITY; 408 mMaximumRotaryEncoderFlingVelocity = MAXIMUM_FLING_VELOCITY; 409 mRotaryEncoderHapticScrollFeedbackEnabled = false; 410 mRotaryEncoderHapticScrollFeedbackTickIntervalPixels = NO_HAPTIC_SCROLL_TICK_INTERVAL; 411 mViewBasedRotaryEncoderScrollHapticsEnabledConfig = false; 412 mScrollbarSize = SCROLL_BAR_SIZE; 413 mTouchSlop = TOUCH_SLOP; 414 mHandwritingSlop = HANDWRITING_SLOP; 415 mHoverSlop = TOUCH_SLOP / 2; 416 mMinScrollbarTouchTarget = MIN_SCROLLBAR_TOUCH_TARGET; 417 mDoubleTapTouchSlop = DOUBLE_TAP_TOUCH_SLOP; 418 mPagingTouchSlop = PAGING_TOUCH_SLOP; 419 mDoubleTapSlop = DOUBLE_TAP_SLOP; 420 mWindowTouchSlop = WINDOW_TOUCH_SLOP; 421 mHandwritingGestureLineMargin = HANDWRITING_GESTURE_LINE_MARGIN; 422 mAmbiguousGestureMultiplier = AMBIGUOUS_GESTURE_MULTIPLIER; 423 //noinspection deprecation 424 mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE; 425 mOverscrollDistance = OVERSCROLL_DISTANCE; 426 mOverflingDistance = OVERFLING_DISTANCE; 427 mFadingMarqueeEnabled = true; 428 mGlobalActionsKeyTimeout = GLOBAL_ACTIONS_KEY_TIMEOUT; 429 mHorizontalScrollFactor = HORIZONTAL_SCROLL_FACTOR; 430 mVerticalScrollFactor = VERTICAL_SCROLL_FACTOR; 431 mShowMenuShortcutsWhenKeyboardPresent = false; 432 mScreenshotChordKeyTimeout = SCREENSHOT_CHORD_KEY_TIMEOUT; 433 434 // Getter throws if mConstructedWithContext is false so doesn't matter what 435 // this value is. 436 mMinScalingSpan = 0; 437 mSmartSelectionInitializedTimeout = SMART_SELECTION_INITIALIZED_TIMEOUT_IN_MILLISECOND; 438 mSmartSelectionInitializingTimeout = SMART_SELECTION_INITIALIZING_TIMEOUT_IN_MILLISECOND; 439 mPreferKeepClearForFocusEnabled = false; 440 } 441 442 /** 443 * Creates a new configuration for the specified visual {@link Context}. The configuration 444 * depends on various parameters of the {@link Context}, like the dimension of the display or 445 * the density of the display. 446 * 447 * @param context A visual {@link Context} used to initialize the view configuration. It must 448 * be {@link Activity} or other {@link Context} created with 449 * {@link Context#createWindowContext(int, Bundle)}. 450 * 451 * @see #get(android.content.Context) 452 * @see android.util.DisplayMetrics 453 */ ViewConfiguration(@onNull @iContext Context context)454 private ViewConfiguration(@NonNull @UiContext Context context) { 455 mConstructedWithContext = true; 456 final Resources res = context.getResources(); 457 final DisplayMetrics metrics = res.getDisplayMetrics(); 458 final Configuration config = res.getConfiguration(); 459 final float density = metrics.density; 460 final float sizeAndDensity; 461 if (config.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE)) { 462 sizeAndDensity = density * 1.5f; 463 } else { 464 sizeAndDensity = density; 465 } 466 467 mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f); 468 mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f); 469 mScrollbarSize = res.getDimensionPixelSize( 470 com.android.internal.R.dimen.config_scrollbarSize); 471 mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f); 472 mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f); 473 474 final TypedValue multiplierValue = new TypedValue(); 475 res.getValue( 476 com.android.internal.R.dimen.config_ambiguousGestureMultiplier, 477 multiplierValue, 478 true /*resolveRefs*/); 479 mAmbiguousGestureMultiplier = Math.max(1.0f, multiplierValue.getFloat()); 480 481 // Size of the screen in bytes, in ARGB_8888 format 482 final Rect maxBounds = config.windowConfiguration.getMaxBounds(); 483 mMaximumDrawingCacheSize = 4 * maxBounds.width() * maxBounds.height(); 484 485 mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f); 486 mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f); 487 488 if (!sHasPermanentMenuKeySet) { 489 final int configVal = res.getInteger( 490 com.android.internal.R.integer.config_overrideHasPermanentMenuKey); 491 492 switch (configVal) { 493 default: 494 case HAS_PERMANENT_MENU_KEY_AUTODETECT: { 495 IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); 496 try { 497 sHasPermanentMenuKey = !wm.hasNavigationBar(context.getDisplayId()); 498 sHasPermanentMenuKeySet = true; 499 } catch (RemoteException ex) { 500 sHasPermanentMenuKey = false; 501 } 502 } 503 break; 504 505 case HAS_PERMANENT_MENU_KEY_TRUE: 506 sHasPermanentMenuKey = true; 507 sHasPermanentMenuKeySet = true; 508 break; 509 510 case HAS_PERMANENT_MENU_KEY_FALSE: 511 sHasPermanentMenuKey = false; 512 sHasPermanentMenuKeySet = true; 513 break; 514 } 515 } 516 517 mFadingMarqueeEnabled = res.getBoolean( 518 com.android.internal.R.bool.config_ui_enableFadingMarquee); 519 mTouchSlop = res.getDimensionPixelSize( 520 com.android.internal.R.dimen.config_viewConfigurationTouchSlop); 521 mHandwritingSlop = res.getDimensionPixelSize( 522 com.android.internal.R.dimen.config_viewConfigurationHandwritingSlop); 523 mHoverSlop = res.getDimensionPixelSize( 524 com.android.internal.R.dimen.config_viewConfigurationHoverSlop); 525 mMinScrollbarTouchTarget = res.getDimensionPixelSize( 526 com.android.internal.R.dimen.config_minScrollbarTouchTarget); 527 mPagingTouchSlop = mTouchSlop * 2; 528 529 mDoubleTapTouchSlop = mTouchSlop; 530 531 mHandwritingGestureLineMargin = res.getDimensionPixelSize( 532 com.android.internal.R.dimen.config_viewConfigurationHandwritingGestureLineMargin); 533 534 mMinimumFlingVelocity = res.getDimensionPixelSize( 535 com.android.internal.R.dimen.config_viewMinFlingVelocity); 536 mMaximumFlingVelocity = res.getDimensionPixelSize( 537 com.android.internal.R.dimen.config_viewMaxFlingVelocity); 538 539 int configMinRotaryEncoderFlingVelocity = res.getDimensionPixelSize( 540 com.android.internal.R.dimen.config_viewMinRotaryEncoderFlingVelocity); 541 int configMaxRotaryEncoderFlingVelocity = res.getDimensionPixelSize( 542 com.android.internal.R.dimen.config_viewMaxRotaryEncoderFlingVelocity); 543 if (configMinRotaryEncoderFlingVelocity < 0 || configMaxRotaryEncoderFlingVelocity < 0) { 544 mMinimumRotaryEncoderFlingVelocity = NO_FLING_MIN_VELOCITY; 545 mMaximumRotaryEncoderFlingVelocity = NO_FLING_MAX_VELOCITY; 546 } else { 547 mMinimumRotaryEncoderFlingVelocity = configMinRotaryEncoderFlingVelocity; 548 mMaximumRotaryEncoderFlingVelocity = configMaxRotaryEncoderFlingVelocity; 549 } 550 551 int configRotaryEncoderHapticScrollFeedbackTickIntervalPixels = 552 res.getDimensionPixelSize( 553 com.android.internal.R.dimen 554 .config_rotaryEncoderAxisScrollTickInterval); 555 mRotaryEncoderHapticScrollFeedbackTickIntervalPixels = 556 configRotaryEncoderHapticScrollFeedbackTickIntervalPixels > 0 557 ? configRotaryEncoderHapticScrollFeedbackTickIntervalPixels 558 : NO_HAPTIC_SCROLL_TICK_INTERVAL; 559 560 mRotaryEncoderHapticScrollFeedbackEnabled = 561 res.getBoolean( 562 com.android.internal.R.bool 563 .config_viewRotaryEncoderHapticScrollFedbackEnabled); 564 565 mGlobalActionsKeyTimeout = res.getInteger( 566 com.android.internal.R.integer.config_globalActionsKeyTimeout); 567 568 mHorizontalScrollFactor = res.getDimensionPixelSize( 569 com.android.internal.R.dimen.config_horizontalScrollFactor); 570 mVerticalScrollFactor = res.getDimensionPixelSize( 571 com.android.internal.R.dimen.config_verticalScrollFactor); 572 573 mShowMenuShortcutsWhenKeyboardPresent = res.getBoolean( 574 com.android.internal.R.bool.config_showMenuShortcutsWhenKeyboardPresent); 575 576 mMinScalingSpan = res.getDimensionPixelSize( 577 com.android.internal.R.dimen.config_minScalingSpan); 578 579 mScreenshotChordKeyTimeout = res.getInteger( 580 com.android.internal.R.integer.config_screenshotChordKeyTimeout); 581 582 mSmartSelectionInitializedTimeout = res.getInteger( 583 com.android.internal.R.integer.config_smartSelectionInitializedTimeoutMillis); 584 mSmartSelectionInitializingTimeout = res.getInteger( 585 com.android.internal.R.integer.config_smartSelectionInitializingTimeoutMillis); 586 mPreferKeepClearForFocusEnabled = res.getBoolean( 587 com.android.internal.R.bool.config_preferKeepClearForFocus); 588 mViewBasedRotaryEncoderScrollHapticsEnabledConfig = 589 res.getBoolean( 590 com.android.internal.R.bool.config_viewBasedRotaryEncoderHapticsEnabled); 591 } 592 593 /** 594 * Returns a configuration for the specified visual {@link Context}. The configuration depends 595 * on various parameters of the {@link Context}, like the dimension of the display or the 596 * density of the display. 597 * 598 * @param context A visual {@link Context} used to initialize the view configuration. It must 599 * be {@link Activity} or other {@link Context} created with 600 * {@link Context#createWindowContext(int, Bundle)}. 601 */ 602 // TODO(b/182007470): Use @ConfigurationContext instead get(@onNull @iContext Context context)603 public static ViewConfiguration get(@NonNull @UiContext Context context) { 604 StrictMode.assertConfigurationContext(context, "ViewConfiguration"); 605 606 final int density = getDisplayDensity(context); 607 608 ViewConfiguration configuration = sConfigurations.get(density); 609 if (configuration == null) { 610 configuration = new ViewConfiguration(context); 611 sConfigurations.put(density, configuration); 612 } 613 614 return configuration; 615 } 616 617 /** 618 * Removes cached ViewConfiguration instances, so that we can ensure `get` constructs a new 619 * ViewConfiguration instance. This is useful for testing the behavior and performance of 620 * creating ViewConfiguration the first time. 621 * 622 * @hide 623 */ 624 @VisibleForTesting resetCacheForTesting()625 public static void resetCacheForTesting() { 626 sConfigurations.clear(); 627 } 628 629 /** 630 * Sets the ViewConfiguration cached instanc for a given Context for testing. 631 * 632 * @hide 633 */ 634 @VisibleForTesting setInstanceForTesting(Context context, ViewConfiguration instance)635 public static void setInstanceForTesting(Context context, ViewConfiguration instance) { 636 sConfigurations.put(getDisplayDensity(context), instance); 637 } 638 639 /** 640 * @return The width of the horizontal scrollbar and the height of the vertical 641 * scrollbar in dips 642 * 643 * @deprecated Use {@link #getScaledScrollBarSize()} instead. 644 */ 645 @Deprecated getScrollBarSize()646 public static int getScrollBarSize() { 647 return SCROLL_BAR_SIZE; 648 } 649 650 /** 651 * @return The width of the horizontal scrollbar and the height of the vertical 652 * scrollbar in pixels 653 */ getScaledScrollBarSize()654 public int getScaledScrollBarSize() { 655 return mScrollbarSize; 656 } 657 658 /** 659 * @return the minimum size of the scrollbar thumb's touch target in pixels 660 * @hide 661 */ getScaledMinScrollbarTouchTarget()662 public int getScaledMinScrollbarTouchTarget() { 663 return mMinScrollbarTouchTarget; 664 } 665 666 /** 667 * @return Duration of the fade when scrollbars fade away in milliseconds 668 */ getScrollBarFadeDuration()669 public static int getScrollBarFadeDuration() { 670 return SCROLL_BAR_FADE_DURATION; 671 } 672 673 /** 674 * @return Default delay before the scrollbars fade in milliseconds 675 */ getScrollDefaultDelay()676 public static int getScrollDefaultDelay() { 677 return SCROLL_BAR_DEFAULT_DELAY; 678 } 679 680 /** 681 * @return the length of the fading edges in dips 682 * 683 * @deprecated Use {@link #getScaledFadingEdgeLength()} instead. 684 */ 685 @Deprecated getFadingEdgeLength()686 public static int getFadingEdgeLength() { 687 return FADING_EDGE_LENGTH; 688 } 689 690 /** 691 * @return the length of the fading edges in pixels 692 */ getScaledFadingEdgeLength()693 public int getScaledFadingEdgeLength() { 694 return mFadingEdgeLength; 695 } 696 697 /** 698 * @return the duration in milliseconds of the pressed state in child 699 * components. 700 */ getPressedStateDuration()701 public static int getPressedStateDuration() { 702 return PRESSED_STATE_DURATION; 703 } 704 705 /** 706 * Used for both key and motion events. 707 * 708 * @return the duration in milliseconds before a press turns into 709 * a long press 710 */ getLongPressTimeout()711 public static int getLongPressTimeout() { 712 return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT, 713 DEFAULT_LONG_PRESS_TIMEOUT); 714 } 715 716 /** 717 * @return the duration in milliseconds between the first tap's up event and the second tap's 718 * down event for an interaction to be considered part of the same multi-press. 719 */ getMultiPressTimeout()720 public static int getMultiPressTimeout() { 721 return AppGlobals.getIntCoreSetting(Settings.Secure.MULTI_PRESS_TIMEOUT, 722 DEFAULT_MULTI_PRESS_TIMEOUT); 723 } 724 725 /** 726 * @return the time before the first key repeat in milliseconds. 727 */ getKeyRepeatTimeout()728 public static int getKeyRepeatTimeout() { 729 return AppGlobals.getIntCoreSetting(Settings.Secure.KEY_REPEAT_TIMEOUT_MS, 730 DEFAULT_KEY_REPEAT_TIMEOUT_MS); 731 } 732 733 /** 734 * @return the time between successive key repeats in milliseconds. 735 */ getKeyRepeatDelay()736 public static int getKeyRepeatDelay() { 737 return AppGlobals.getIntCoreSetting(Settings.Secure.KEY_REPEAT_DELAY_MS, 738 DEFAULT_KEY_REPEAT_DELAY_MS); 739 } 740 741 /** 742 * @return the duration in milliseconds we will wait to see if a touch event 743 * is a tap or a scroll. If the user does not move within this interval, it is 744 * considered to be a tap. 745 */ getTapTimeout()746 public static int getTapTimeout() { 747 return TAP_TIMEOUT; 748 } 749 750 /** 751 * @return the duration in milliseconds we will wait to see if a touch event 752 * is a jump tap. If the user does not move within this interval, it is 753 * considered to be a tap. 754 */ getJumpTapTimeout()755 public static int getJumpTapTimeout() { 756 return JUMP_TAP_TIMEOUT; 757 } 758 759 /** 760 * @return the duration in milliseconds between the first tap's up event and 761 * the second tap's down event for an interaction to be considered a 762 * double-tap. 763 */ getDoubleTapTimeout()764 public static int getDoubleTapTimeout() { 765 return DOUBLE_TAP_TIMEOUT; 766 } 767 768 /** 769 * @return the minimum duration in milliseconds between the first tap's 770 * up event and the second tap's down event for an interaction to be considered a 771 * double-tap. 772 * 773 * @hide 774 */ 775 @UnsupportedAppUsage getDoubleTapMinTime()776 public static int getDoubleTapMinTime() { 777 return DOUBLE_TAP_MIN_TIME; 778 } 779 780 /** 781 * @return the maximum duration in milliseconds between a touch pad 782 * touch and release for a given touch to be considered a tap (click) as 783 * opposed to a hover movement gesture. 784 * @hide 785 */ getHoverTapTimeout()786 public static int getHoverTapTimeout() { 787 return HOVER_TAP_TIMEOUT; 788 } 789 790 /** 791 * @return the maximum distance in pixels that a touch pad touch can move 792 * before being released for it to be considered a tap (click) as opposed 793 * to a hover movement gesture. 794 * @hide 795 */ 796 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getHoverTapSlop()797 public static int getHoverTapSlop() { 798 return HOVER_TAP_SLOP; 799 } 800 801 /** 802 * @return Inset in dips to look for touchable content when the user touches the edge of the 803 * screen 804 * 805 * @deprecated Use {@link #getScaledEdgeSlop()} instead. 806 */ 807 @Deprecated getEdgeSlop()808 public static int getEdgeSlop() { 809 return EDGE_SLOP; 810 } 811 812 /** 813 * @return Inset in pixels to look for touchable content when the user touches the edge of the 814 * screen 815 */ getScaledEdgeSlop()816 public int getScaledEdgeSlop() { 817 return mEdgeSlop; 818 } 819 820 /** 821 * @return Distance in dips a touch can wander before we think the user is scrolling 822 * 823 * @deprecated Use {@link #getScaledTouchSlop()} instead. 824 */ 825 @Deprecated getTouchSlop()826 public static int getTouchSlop() { 827 return TOUCH_SLOP; 828 } 829 830 /** 831 * @return Distance in pixels a touch can wander before we think the user is scrolling 832 */ getScaledTouchSlop()833 public int getScaledTouchSlop() { 834 return mTouchSlop; 835 } 836 837 /** 838 * @return Distance in pixels a stylus touch can wander before we think the user is 839 * handwriting. 840 */ getScaledHandwritingSlop()841 public int getScaledHandwritingSlop() { 842 return mHandwritingSlop; 843 } 844 845 /** 846 * @return Distance in pixels a hover can wander while it is still considered "stationary". 847 * 848 */ getScaledHoverSlop()849 public int getScaledHoverSlop() { 850 return mHoverSlop; 851 } 852 853 /** 854 * @return Distance in pixels the first touch can wander before we do not consider this a 855 * potential double tap event 856 * @hide 857 */ 858 @UnsupportedAppUsage getScaledDoubleTapTouchSlop()859 public int getScaledDoubleTapTouchSlop() { 860 return mDoubleTapTouchSlop; 861 } 862 863 /** 864 * @return Distance in pixels a touch can wander before we think the user is scrolling a full 865 * page 866 */ getScaledPagingTouchSlop()867 public int getScaledPagingTouchSlop() { 868 return mPagingTouchSlop; 869 } 870 871 /** 872 * @return Distance in dips between the first touch and second touch to still be 873 * considered a double tap 874 * @deprecated Use {@link #getScaledDoubleTapSlop()} instead. 875 * @hide The only client of this should be GestureDetector, which needs this 876 * for clients that still use its deprecated constructor. 877 */ 878 @Deprecated 879 @UnsupportedAppUsage getDoubleTapSlop()880 public static int getDoubleTapSlop() { 881 return DOUBLE_TAP_SLOP; 882 } 883 884 /** 885 * @return Distance in pixels between the first touch and second touch to still be 886 * considered a double tap 887 */ getScaledDoubleTapSlop()888 public int getScaledDoubleTapSlop() { 889 return mDoubleTapSlop; 890 } 891 892 /** 893 * @return margin in pixels around text line bounds where stylus handwriting gestures should be 894 * supported. 895 */ getScaledHandwritingGestureLineMargin()896 public int getScaledHandwritingGestureLineMargin() { 897 return mHandwritingGestureLineMargin; 898 } 899 900 /** 901 * Interval for dispatching a recurring accessibility event in milliseconds. 902 * This interval guarantees that a recurring event will be send at most once 903 * during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame. 904 * 905 * @return The delay in milliseconds. 906 * 907 * @hide 908 */ getSendRecurringAccessibilityEventsInterval()909 public static long getSendRecurringAccessibilityEventsInterval() { 910 return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS; 911 } 912 913 /** 914 * @return Distance in dips a touch must be outside the bounds of a window for it 915 * to be counted as outside the window for purposes of dismissing that 916 * window. 917 * 918 * @deprecated Use {@link #getScaledWindowTouchSlop()} instead. 919 */ 920 @Deprecated getWindowTouchSlop()921 public static int getWindowTouchSlop() { 922 return WINDOW_TOUCH_SLOP; 923 } 924 925 /** 926 * @return Distance in pixels a touch must be outside the bounds of a window for it 927 * to be counted as outside the window for purposes of dismissing that window. 928 */ getScaledWindowTouchSlop()929 public int getScaledWindowTouchSlop() { 930 return mWindowTouchSlop; 931 } 932 933 /** 934 * @return Minimum velocity to initiate a fling, as measured in dips per second. 935 * 936 * @deprecated Use {@link #getScaledMinimumFlingVelocity()} instead. 937 */ 938 @Deprecated getMinimumFlingVelocity()939 public static int getMinimumFlingVelocity() { 940 return MINIMUM_FLING_VELOCITY; 941 } 942 943 /** 944 * @return Minimum velocity to initiate a fling, as measured in pixels per second. 945 */ getScaledMinimumFlingVelocity()946 public int getScaledMinimumFlingVelocity() { 947 return mMinimumFlingVelocity; 948 } 949 950 /** 951 * @return Maximum velocity to initiate a fling, as measured in dips per second. 952 * 953 * @deprecated Use {@link #getScaledMaximumFlingVelocity()} instead. 954 */ 955 @Deprecated getMaximumFlingVelocity()956 public static int getMaximumFlingVelocity() { 957 return MAXIMUM_FLING_VELOCITY; 958 } 959 960 /** 961 * @return Maximum velocity to initiate a fling, as measured in pixels per second. 962 */ getScaledMaximumFlingVelocity()963 public int getScaledMaximumFlingVelocity() { 964 return mMaximumFlingVelocity; 965 } 966 967 /** 968 * @return Amount to scroll in response to a {@link MotionEvent#ACTION_SCROLL} event. Multiply 969 * this by the event's axis value to obtain the number of pixels to be scrolled. 970 * 971 * @removed 972 */ getScaledScrollFactor()973 public int getScaledScrollFactor() { 974 return (int) mVerticalScrollFactor; 975 } 976 977 /** 978 * @return Amount to scroll in response to a horizontal {@link MotionEvent#ACTION_SCROLL} event. 979 * Multiply this by the event's axis value to obtain the number of pixels to be scrolled. 980 */ getScaledHorizontalScrollFactor()981 public float getScaledHorizontalScrollFactor() { 982 return mHorizontalScrollFactor; 983 } 984 985 /** 986 * @return Amount to scroll in response to a vertical {@link MotionEvent#ACTION_SCROLL} event. 987 * Multiply this by the event's axis value to obtain the number of pixels to be scrolled. 988 */ getScaledVerticalScrollFactor()989 public float getScaledVerticalScrollFactor() { 990 return mVerticalScrollFactor; 991 } 992 993 /** 994 * The maximum drawing cache size expressed in bytes. 995 * 996 * @return the maximum size of View's drawing cache expressed in bytes 997 * 998 * @deprecated Use {@link #getScaledMaximumDrawingCacheSize()} instead. 999 */ 1000 @Deprecated getMaximumDrawingCacheSize()1001 public static int getMaximumDrawingCacheSize() { 1002 //noinspection deprecation 1003 return MAXIMUM_DRAWING_CACHE_SIZE; 1004 } 1005 1006 /** 1007 * The maximum drawing cache size expressed in bytes. 1008 * 1009 * @return the maximum size of View's drawing cache expressed in bytes 1010 */ getScaledMaximumDrawingCacheSize()1011 public int getScaledMaximumDrawingCacheSize() { 1012 return mMaximumDrawingCacheSize; 1013 } 1014 1015 /** 1016 * @return The maximum distance a View should overscroll by when showing edge effects (in 1017 * pixels). 1018 */ getScaledOverscrollDistance()1019 public int getScaledOverscrollDistance() { 1020 return mOverscrollDistance; 1021 } 1022 1023 /** 1024 * @return The maximum distance a View should overfling by when showing edge effects (in 1025 * pixels). 1026 */ getScaledOverflingDistance()1027 public int getScaledOverflingDistance() { 1028 return mOverflingDistance; 1029 } 1030 1031 /** 1032 * The amount of time that the zoom controls should be 1033 * displayed on the screen expressed in milliseconds. 1034 * 1035 * @return the time the zoom controls should be visible expressed 1036 * in milliseconds. 1037 */ getZoomControlsTimeout()1038 public static long getZoomControlsTimeout() { 1039 return ZOOM_CONTROLS_TIMEOUT; 1040 } 1041 1042 /** 1043 * The amount of time a user needs to press the relevant key to bring up 1044 * the global actions dialog. 1045 * 1046 * @return how long a user needs to press the relevant key to bring up 1047 * the global actions dialog. 1048 * @deprecated This timeout should not be used by applications 1049 */ 1050 @Deprecated getGlobalActionKeyTimeout()1051 public static long getGlobalActionKeyTimeout() { 1052 return GLOBAL_ACTIONS_KEY_TIMEOUT; 1053 } 1054 1055 /** 1056 * The amount of time a user needs to press the relevant key to bring up 1057 * the global actions dialog. 1058 * 1059 * @return how long a user needs to press the relevant key to bring up 1060 * the global actions dialog. 1061 * @hide 1062 */ 1063 @TestApi getDeviceGlobalActionKeyTimeout()1064 public long getDeviceGlobalActionKeyTimeout() { 1065 return mGlobalActionsKeyTimeout; 1066 } 1067 1068 /** 1069 * The amount of time a user needs to press the relevant keys to trigger 1070 * the screenshot chord. 1071 * 1072 * @return how long a user needs to press the relevant keys to trigger 1073 * the screenshot chord. 1074 * @hide 1075 */ getScreenshotChordKeyTimeout()1076 public long getScreenshotChordKeyTimeout() { 1077 return mScreenshotChordKeyTimeout; 1078 } 1079 1080 /** 1081 * The amount of time a user needs to press the relevant keys to activate the accessibility 1082 * shortcut. 1083 * 1084 * @return how long a user needs to press the relevant keys to activate the accessibility 1085 * shortcut. 1086 * @hide 1087 */ getAccessibilityShortcutKeyTimeout()1088 public long getAccessibilityShortcutKeyTimeout() { 1089 return A11Y_SHORTCUT_KEY_TIMEOUT; 1090 } 1091 1092 /** 1093 * @return The amount of time a user needs to press the relevant keys to activate the 1094 * accessibility shortcut after it's confirmed that accessibility shortcut is used. 1095 * @hide 1096 */ getAccessibilityShortcutKeyTimeoutAfterConfirmation()1097 public long getAccessibilityShortcutKeyTimeoutAfterConfirmation() { 1098 return A11Y_SHORTCUT_KEY_TIMEOUT_AFTER_CONFIRMATION; 1099 } 1100 1101 /** 1102 * The amount of friction applied to scrolls and flings. 1103 * 1104 * @return A scalar dimensionless value representing the coefficient of 1105 * friction. 1106 */ getScrollFriction()1107 public static float getScrollFriction() { 1108 return SCROLL_FRICTION; 1109 } 1110 1111 /** 1112 * @return the default duration in milliseconds for {@link ActionMode#hide(long)}. 1113 */ getDefaultActionModeHideDuration()1114 public static long getDefaultActionModeHideDuration() { 1115 return ACTION_MODE_HIDE_DURATION_DEFAULT; 1116 } 1117 1118 /** 1119 * The multiplication factor for inhibiting default gestures. 1120 * 1121 * If a MotionEvent has {@link android.view.MotionEvent#CLASSIFICATION_AMBIGUOUS_GESTURE} set, 1122 * then certain actions, such as scrolling, will be inhibited. However, to account for the 1123 * possibility of an incorrect classification, existing gesture thresholds (e.g. scrolling 1124 * touch slop and the long-press timeout) should be scaled by this factor and remain in effect. 1125 * 1126 * @deprecated Use {@link #getScaledAmbiguousGestureMultiplier()}. 1127 */ 1128 @Deprecated 1129 @FloatRange(from = 1.0) getAmbiguousGestureMultiplier()1130 public static float getAmbiguousGestureMultiplier() { 1131 return AMBIGUOUS_GESTURE_MULTIPLIER; 1132 } 1133 1134 /** 1135 * The multiplication factor for inhibiting default gestures. 1136 * 1137 * If a MotionEvent has {@link android.view.MotionEvent#CLASSIFICATION_AMBIGUOUS_GESTURE} set, 1138 * then certain actions, such as scrolling, will be inhibited. However, to account for the 1139 * possibility of an incorrect classification, existing gesture thresholds (e.g. scrolling 1140 * touch slop and the long-press timeout) should be scaled by this factor and remain in effect. 1141 */ 1142 @FloatRange(from = 1.0) getScaledAmbiguousGestureMultiplier()1143 public float getScaledAmbiguousGestureMultiplier() { 1144 return mAmbiguousGestureMultiplier; 1145 } 1146 1147 /** 1148 * Report if the device has a permanent menu key available to the user. 1149 * 1150 * <p>As of Android 3.0, devices may not have a permanent menu key available. 1151 * Apps should use the action bar to present menu options to users. 1152 * However, there are some apps where the action bar is inappropriate 1153 * or undesirable. This method may be used to detect if a menu key is present. 1154 * If not, applications should provide another on-screen affordance to access 1155 * functionality. 1156 * 1157 * @return true if a permanent menu key is present, false otherwise. 1158 */ hasPermanentMenuKey()1159 public boolean hasPermanentMenuKey() { 1160 return sHasPermanentMenuKey; 1161 } 1162 1163 /** 1164 * Minimum absolute value of velocity to initiate a fling for a motion generated by an 1165 * {@link InputDevice} with an id of {@code inputDeviceId}, from an input {@code source} and on 1166 * a given motion event {@code axis}. 1167 * 1168 * <p>Before utilizing this method to get a minimum fling velocity for a motion generated by the 1169 * input device, scale the velocity of the motion events generated by the input device to pixels 1170 * per second. 1171 * 1172 * <p>For instance, if you tracked {@link MotionEvent#AXIS_SCROLL} vertical velocities generated 1173 * from a {@link InputDevice#SOURCE_ROTARY_ENCODER}, the velocity returned from 1174 * {@link VelocityTracker} will be in the units with which the axis values were reported in the 1175 * motion event. Before comparing that velocity against the minimum fling velocity specified 1176 * here, make sure that the {@link MotionEvent#AXIS_SCROLL} velocity from the tracker is 1177 * calculated in "units per second" (see {@link VelocityTracker#computeCurrentVelocity(int)}, 1178 * {@link VelocityTracker#computeCurrentVelocity(int, float)} to adjust your velocity 1179 * computations to "per second"), and use {@link #getScaledVerticalScrollFactor} to change this 1180 * velocity value to "pixels/second". 1181 * 1182 * <p>If the provided {@code inputDeviceId} is not valid, or if the input device whose ID is 1183 * provided does not support the given motion event source and/or axis, this method will return 1184 * {@code Integer.MAX_VALUE}. 1185 * 1186 * <h3>Obtaining the correct arguments for this method call</h3> 1187 * <p><b>inputDeviceId</b>: if calling this method in response to a {@link MotionEvent}, use 1188 * the device ID that is reported by the event, which can be obtained using 1189 * {@link MotionEvent#getDeviceId()}. Otherwise, use a valid ID that is obtained from 1190 * {@link InputDevice#getId()}, or from an {@link InputManager} instance 1191 * ({@link InputManager#getInputDeviceIds()} gives all the valid input device IDs). 1192 * 1193 * <p><b>axis</b>: a {@link MotionEvent} may report data for multiple axes, and each axis may 1194 * have multiple data points for different pointers. Use the axis for which you obtained the 1195 * velocity for ({@link VelocityTracker} lets you calculate velocities for a specific axis. Use 1196 * the axis for which you calculated velocity). You can use 1197 * {@link InputDevice#getMotionRanges()} to get all the {@link InputDevice.MotionRange}s for the 1198 * {@link InputDevice}, from which you can derive all the valid axes for the device. 1199 * 1200 * <p><b>source</b>: use {@link MotionEvent#getSource()} if calling this method in response to a 1201 * {@link MotionEvent}. Otherwise, use a valid source for the {@link InputDevice}. You can use 1202 * {@link InputDevice#getMotionRanges()} to get all the {@link InputDevice.MotionRange}s for the 1203 * {@link InputDevice}, from which you can derive all the valid sources for the device. 1204 * 1205 * 1206 * <p>This method optimizes calls over multiple input device IDs, so caching the return value of 1207 * the method is not necessary if you are handling multiple input devices. 1208 * 1209 * @param inputDeviceId the ID of the {@link InputDevice} that generated the motion triggering 1210 * fling. 1211 * @param axis the axis on which the motion triggering the fling happened. This axis should be 1212 * a valid axis that can be reported by the provided input device from the provided 1213 * input device source. 1214 * @param source the input source of the motion causing fling. This source should be a valid 1215 * source for the {@link InputDevice} whose ID is {@code inputDeviceId}. 1216 * 1217 * @return the minimum velocity, in pixels/second, to trigger fling. 1218 * 1219 * @see InputDevice#getMotionRange(int, int) 1220 * @see InputDevice#getMotionRanges() 1221 * @see VelocityTracker#getAxisVelocity(int, int) 1222 * @see VelocityTracker#getAxisVelocity(int) 1223 */ getScaledMinimumFlingVelocity(int inputDeviceId, int axis, int source)1224 public int getScaledMinimumFlingVelocity(int inputDeviceId, int axis, int source) { 1225 if (!isInputDeviceInfoValid(inputDeviceId, axis, source)) return NO_FLING_MIN_VELOCITY; 1226 1227 if (source == InputDevice.SOURCE_ROTARY_ENCODER) return mMinimumRotaryEncoderFlingVelocity; 1228 1229 return mMinimumFlingVelocity; 1230 } 1231 1232 /** 1233 * Maximum absolute value of velocity to initiate a fling for a motion generated by an 1234 * {@link InputDevice} with an id of {@code inputDeviceId}, from an input {@code source} and on 1235 * a given motion event {@code axis}. 1236 * 1237 * <p>Similar to {@link #getScaledMinimumFlingVelocity(int, int, int)}, but for maximum fling 1238 * velocity, instead of minimum. Also, unlike that method which returns 1239 * {@code Integer.MAX_VALUE} for bad input device ID, source and/or motion event axis inputs, 1240 * this method returns {@code Integer.MIN_VALUE} for such bad inputs. 1241 */ getScaledMaximumFlingVelocity(int inputDeviceId, int axis, int source)1242 public int getScaledMaximumFlingVelocity(int inputDeviceId, int axis, int source) { 1243 if (!isInputDeviceInfoValid(inputDeviceId, axis, source)) return NO_FLING_MAX_VELOCITY; 1244 1245 if (source == InputDevice.SOURCE_ROTARY_ENCODER) return mMaximumRotaryEncoderFlingVelocity; 1246 1247 return mMaximumFlingVelocity; 1248 } 1249 1250 /** 1251 * Checks if any kind of scroll haptic feedback is enabled for a motion generated by a specific 1252 * input device configuration and motion axis. 1253 * 1254 * <p>See {@link ScrollFeedbackProvider} for details on the arguments that should be passed to 1255 * the methods in this class. 1256 * 1257 * <p>If the provided input device ID, source, and motion axis are not supported by this Android 1258 * device, this method returns {@code false}. In other words, if the {@link InputDevice} 1259 * represented by the provided {code inputDeviceId} does not have a 1260 * {@link InputDevice.MotionRange} with the provided {@code axis} and {@code source}, the method 1261 * returns {@code false}. 1262 * 1263 * <p>If the provided input device ID, source, and motion axis are supported by this Android 1264 * device, this method returns {@code true} only if the provided arguments are supported for 1265 * scroll haptics. Otherwise, this method returns {@code false}. 1266 * 1267 * @param inputDeviceId the ID of the {@link InputDevice} that generated the motion that may 1268 * produce scroll haptics. 1269 * @param source the input source of the motion that may produce scroll haptics. 1270 * @param axis the axis of the motion that may produce scroll haptics. 1271 * @return {@code true} if motions generated by the provided input and motion configuration 1272 * can produce scroll haptics. {@code false} otherwise. 1273 * 1274 * @see #getHapticScrollFeedbackTickInterval(int, int, int) 1275 * @see InputDevice#getMotionRanges() 1276 * @see InputDevice#getMotionRange(int) 1277 * @see InputDevice#getMotionRange(int, int) 1278 * 1279 * @hide 1280 */ isHapticScrollFeedbackEnabled(int inputDeviceId, int axis, int source)1281 public boolean isHapticScrollFeedbackEnabled(int inputDeviceId, int axis, int source) { 1282 if (!isInputDeviceInfoValid(inputDeviceId, axis, source)) return false; 1283 1284 if (source == InputDevice.SOURCE_ROTARY_ENCODER && axis == MotionEvent.AXIS_SCROLL) { 1285 return mRotaryEncoderHapticScrollFeedbackEnabled; 1286 } 1287 1288 return false; 1289 } 1290 1291 /** 1292 * Provides the minimum scroll interval (in pixels) between consecutive scroll tick haptics for 1293 * motions generated by a specific input device configuration and motion axis. 1294 * 1295 * <p><b>Scroll tick</b> here refers to an interval-based, consistent scroll feedback provided 1296 * to the user as the user scrolls through a scrollable view. 1297 * 1298 * <p>If you are supporting scroll tick haptics, use this interval as the minimum pixel scroll 1299 * distance between consecutive scroll ticks. That is, once your view has scrolled for at least 1300 * this interval, play a haptic, and wait again until the view has further scrolled with this 1301 * interval in the same direction before playing the next scroll haptic. 1302 * 1303 * <p>Some devices may support other types of scroll haptics but not interval based tick 1304 * haptics. In those cases, this method will return {@code Integer.MAX_VALUE}. The same value 1305 * will be returned if the device does not support scroll haptics at all (which can be checked 1306 * via {@link #isHapticScrollFeedbackEnabled(int, int, int)}). 1307 * 1308 * <p>See {@link #isHapticScrollFeedbackEnabled(int, int, int)} for more details about obtaining 1309 * the correct arguments for this method. 1310 * 1311 * @param inputDeviceId the ID of the {@link InputDevice} that generated the motion that may 1312 * produce scroll haptics. 1313 * @param source the input source of the motion that may produce scroll haptics. 1314 * @param axis the axis of the motion that may produce scroll haptics. 1315 * @return the absolute value of the minimum scroll interval, in pixels, between consecutive 1316 * scroll feedback haptics for motions generated by the provided input and motion 1317 * configuration. If scroll haptics is disabled for the given configuration, or if the 1318 * device does not support scroll tick haptics for the given configuration, this method 1319 * returns {@code Integer.MAX_VALUE}. 1320 * 1321 * @see #isHapticScrollFeedbackEnabled(int, int, int) 1322 * 1323 * @hide 1324 */ getHapticScrollFeedbackTickInterval(int inputDeviceId, int axis, int source)1325 public int getHapticScrollFeedbackTickInterval(int inputDeviceId, int axis, int source) { 1326 if (!mRotaryEncoderHapticScrollFeedbackEnabled) { 1327 return NO_HAPTIC_SCROLL_TICK_INTERVAL; 1328 } 1329 1330 if (!isInputDeviceInfoValid(inputDeviceId, axis, source)) { 1331 return NO_HAPTIC_SCROLL_TICK_INTERVAL; 1332 } 1333 1334 if (source == InputDevice.SOURCE_ROTARY_ENCODER && axis == MotionEvent.AXIS_SCROLL) { 1335 return mRotaryEncoderHapticScrollFeedbackTickIntervalPixels; 1336 } 1337 1338 return NO_HAPTIC_SCROLL_TICK_INTERVAL; 1339 } 1340 1341 /** 1342 * Checks if the View-based haptic scroll feedback implementation is enabled for 1343 * {@link InputDevice#SOURCE_ROTARY_ENCODER}s. 1344 * 1345 * @hide 1346 */ isViewBasedRotaryEncoderHapticScrollFeedbackEnabled()1347 public boolean isViewBasedRotaryEncoderHapticScrollFeedbackEnabled() { 1348 return mViewBasedRotaryEncoderScrollHapticsEnabledConfig 1349 && Flags.useViewBasedRotaryEncoderScrollHaptics(); 1350 } 1351 isInputDeviceInfoValid(int id, int axis, int source)1352 private static boolean isInputDeviceInfoValid(int id, int axis, int source) { 1353 InputDevice device = InputManagerGlobal.getInstance().getInputDevice(id); 1354 return device != null && device.getMotionRange(axis, source) != null; 1355 } 1356 1357 /** 1358 * Check if shortcuts should be displayed in menus. 1359 * 1360 * @return {@code True} if shortcuts should be displayed in menus. 1361 */ shouldShowMenuShortcutsWhenKeyboardPresent()1362 public boolean shouldShowMenuShortcutsWhenKeyboardPresent() { 1363 return mShowMenuShortcutsWhenKeyboardPresent; 1364 } 1365 1366 /** 1367 * Retrieves the distance in pixels between touches that must be reached for a gesture to be 1368 * interpreted as scaling. 1369 * 1370 * In general, scaling shouldn't start until this distance has been met or surpassed, and 1371 * scaling should end when the distance in pixels between touches drops below this distance. 1372 * 1373 * @return The distance in pixels 1374 * @throws IllegalStateException if this method is called on a ViewConfiguration that was 1375 * instantiated using a constructor with no Context parameter. 1376 */ getScaledMinimumScalingSpan()1377 public int getScaledMinimumScalingSpan() { 1378 if (!mConstructedWithContext) { 1379 throw new IllegalStateException("Min scaling span cannot be determined when this " 1380 + "method is called on a ViewConfiguration that was instantiated using a " 1381 + "constructor with no Context parameter"); 1382 } 1383 return mMinScalingSpan; 1384 } 1385 1386 /** 1387 * @hide 1388 * @return Whether or not marquee should use fading edges. 1389 */ 1390 @UnsupportedAppUsage isFadingMarqueeEnabled()1391 public boolean isFadingMarqueeEnabled() { 1392 return mFadingMarqueeEnabled; 1393 } 1394 1395 /** 1396 * @return the timeout value in milliseconds to adjust the selection span and actions for the 1397 * selected text when TextClassifier has been initialized. 1398 * @hide 1399 */ getSmartSelectionInitializedTimeout()1400 public int getSmartSelectionInitializedTimeout() { 1401 return mSmartSelectionInitializedTimeout; 1402 } 1403 1404 /** 1405 * @return the timeout value in milliseconds to adjust the selection span and actions for the 1406 * selected text when TextClassifier has not been initialized. 1407 * @hide 1408 */ getSmartSelectionInitializingTimeout()1409 public int getSmartSelectionInitializingTimeout() { 1410 return mSmartSelectionInitializingTimeout; 1411 } 1412 1413 /** 1414 * @return {@code true} if Views should set themselves as preferred to keep clear when focused, 1415 * {@code false} otherwise. 1416 * @hide 1417 */ 1418 @TestApi isPreferKeepClearForFocusEnabled()1419 public boolean isPreferKeepClearForFocusEnabled() { 1420 return mPreferKeepClearForFocusEnabled; 1421 } 1422 1423 /** 1424 * @return the duration in milliseconds before an end of a long press causes a tooltip to be 1425 * hidden 1426 * @hide 1427 */ 1428 @TestApi getLongPressTooltipHideTimeout()1429 public static int getLongPressTooltipHideTimeout() { 1430 return LONG_PRESS_TOOLTIP_HIDE_TIMEOUT; 1431 } 1432 1433 /** 1434 * @return the duration in milliseconds before a hover event causes a tooltip to be shown 1435 * @hide 1436 */ 1437 @TestApi getHoverTooltipShowTimeout()1438 public static int getHoverTooltipShowTimeout() { 1439 return HOVER_TOOLTIP_SHOW_TIMEOUT; 1440 } 1441 1442 /** 1443 * @return the duration in milliseconds before mouse inactivity causes a tooltip to be hidden 1444 * (default variant to be used when {@link View#SYSTEM_UI_FLAG_LOW_PROFILE} is not set). 1445 * @hide 1446 */ 1447 @TestApi getHoverTooltipHideTimeout()1448 public static int getHoverTooltipHideTimeout() { 1449 return HOVER_TOOLTIP_HIDE_TIMEOUT; 1450 } 1451 1452 /** 1453 * @return the duration in milliseconds before mouse inactivity causes a tooltip to be hidden 1454 * (shorter variant to be used when {@link View#SYSTEM_UI_FLAG_LOW_PROFILE} is set). 1455 * @hide 1456 */ 1457 @TestApi getHoverTooltipHideShortTimeout()1458 public static int getHoverTooltipHideShortTimeout() { 1459 return HOVER_TOOLTIP_HIDE_SHORT_TIMEOUT; 1460 } 1461 getDisplayDensity(Context context)1462 private static final int getDisplayDensity(Context context) { 1463 final DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 1464 return (int) (100.0f * metrics.density); 1465 } 1466 } 1467