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
17package android.view;
18
19import android.app.AppGlobals;
20import android.content.Context;
21import android.content.res.Configuration;
22import android.content.res.Resources;
23import android.graphics.Point;
24import android.os.RemoteException;
25import android.provider.Settings;
26import android.util.DisplayMetrics;
27import android.util.SparseArray;
28
29/**
30 * Contains methods to standard constants used in the UI for timeouts, sizes, and distances.
31 */
32public class ViewConfiguration {
33    /**
34     * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
35     * dips
36     */
37    private static final int SCROLL_BAR_SIZE = 10;
38
39    /**
40     * Duration of the fade when scrollbars fade away in milliseconds
41     */
42    private static final int SCROLL_BAR_FADE_DURATION = 250;
43
44    /**
45     * Default delay before the scrollbars fade in milliseconds
46     */
47    private static final int SCROLL_BAR_DEFAULT_DELAY = 300;
48
49    /**
50     * Defines the length of the fading edges in dips
51     */
52    private static final int FADING_EDGE_LENGTH = 12;
53
54    /**
55     * Defines the duration in milliseconds of the pressed state in child
56     * components.
57     */
58    private static final int PRESSED_STATE_DURATION = 64;
59
60    /**
61     * Defines the default duration in milliseconds before a press turns into
62     * a long press
63     */
64    private static final int DEFAULT_LONG_PRESS_TIMEOUT = 500;
65
66    /**
67     * Defines the time between successive key repeats in milliseconds.
68     */
69    private static final int KEY_REPEAT_DELAY = 50;
70
71    /**
72     * Defines the duration in milliseconds a user needs to hold down the
73     * appropriate button to bring up the global actions dialog (power off,
74     * lock screen, etc).
75     */
76    private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500;
77
78    /**
79     * Defines the duration in milliseconds we will wait to see if a touch event
80     * is a tap or a scroll. If the user does not move within this interval, it is
81     * considered to be a tap.
82     */
83    private static final int TAP_TIMEOUT = 100;
84
85    /**
86     * Defines the duration in milliseconds we will wait to see if a touch event
87     * is a jump tap. If the user does not complete the jump tap within this interval, it is
88     * considered to be a tap.
89     */
90    private static final int JUMP_TAP_TIMEOUT = 500;
91
92    /**
93     * Defines the duration in milliseconds between the first tap's up event and
94     * the second tap's down event for an interaction to be considered a
95     * double-tap.
96     */
97    private static final int DOUBLE_TAP_TIMEOUT = 300;
98
99    /**
100     * Defines the minimum duration in milliseconds between the first tap's up event and
101     * the second tap's down event for an interaction to be considered a
102     * double-tap.
103     */
104    private static final int DOUBLE_TAP_MIN_TIME = 40;
105
106    /**
107     * Defines the maximum duration in milliseconds between a touch pad
108     * touch and release for a given touch to be considered a tap (click) as
109     * opposed to a hover movement gesture.
110     */
111    private static final int HOVER_TAP_TIMEOUT = 150;
112
113    /**
114     * Defines the maximum distance in pixels that a touch pad touch can move
115     * before being released for it to be considered a tap (click) as opposed
116     * to a hover movement gesture.
117     */
118    private static final int HOVER_TAP_SLOP = 20;
119
120    /**
121     * Defines the duration in milliseconds we want to display zoom controls in response
122     * to a user panning within an application.
123     */
124    private static final int ZOOM_CONTROLS_TIMEOUT = 3000;
125
126    /**
127     * Inset in dips to look for touchable content when the user touches the edge of the screen
128     */
129    private static final int EDGE_SLOP = 12;
130
131    /**
132     * Distance a touch can wander before we think the user is scrolling in dips.
133     * Note that this value defined here is only used as a fallback by legacy/misbehaving
134     * applications that do not provide a Context for determining density/configuration-dependent
135     * values.
136     *
137     * To alter this value, see the configuration resource config_viewConfigurationTouchSlop
138     * in frameworks/base/core/res/res/values/config.xml or the appropriate device resource overlay.
139     * It may be appropriate to tweak this on a device-specific basis in an overlay based on
140     * the characteristics of the touch panel and firmware.
141     */
142    private static final int TOUCH_SLOP = 8;
143
144    /**
145     * Distance the first touch can wander before we stop considering this event a double tap
146     * (in dips)
147     */
148    private static final int DOUBLE_TAP_TOUCH_SLOP = TOUCH_SLOP;
149
150    /**
151     * Distance a touch can wander before we think the user is attempting a paged scroll
152     * (in dips)
153     *
154     * Note that this value defined here is only used as a fallback by legacy/misbehaving
155     * applications that do not provide a Context for determining density/configuration-dependent
156     * values.
157     *
158     * See the note above on {@link #TOUCH_SLOP} regarding the dimen resource
159     * config_viewConfigurationTouchSlop. ViewConfiguration will report a paging touch slop of
160     * config_viewConfigurationTouchSlop * 2 when provided with a Context.
161     */
162    private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2;
163
164    /**
165     * Distance in dips between the first touch and second touch to still be considered a double tap
166     */
167    private static final int DOUBLE_TAP_SLOP = 100;
168
169    /**
170     * Distance in dips a touch needs to be outside of a window's bounds for it to
171     * count as outside for purposes of dismissing the window.
172     */
173    private static final int WINDOW_TOUCH_SLOP = 16;
174
175    /**
176     * Minimum velocity to initiate a fling, as measured in dips per second
177     */
178    private static final int MINIMUM_FLING_VELOCITY = 50;
179
180    /**
181     * Maximum velocity to initiate a fling, as measured in dips per second
182     */
183    private static final int MAXIMUM_FLING_VELOCITY = 8000;
184
185    /**
186     * Delay before dispatching a recurring accessibility event in milliseconds.
187     * This delay guarantees that a recurring event will be send at most once
188     * during the {@link #SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS} time
189     * frame.
190     */
191    private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 100;
192
193    /**
194     * The maximum size of View's drawing cache, expressed in bytes. This size
195     * should be at least equal to the size of the screen in ARGB888 format.
196     */
197    @Deprecated
198    private static final int MAXIMUM_DRAWING_CACHE_SIZE = 480 * 800 * 4; // ARGB8888
199
200    /**
201     * The coefficient of friction applied to flings/scrolls.
202     */
203    private static final float SCROLL_FRICTION = 0.015f;
204
205    /**
206     * Max distance in dips to overscroll for edge effects
207     */
208    private static final int OVERSCROLL_DISTANCE = 0;
209
210    /**
211     * Max distance in dips to overfling for edge effects
212     */
213    private static final int OVERFLING_DISTANCE = 6;
214
215    /**
216     * Configuration values for overriding {@link #hasPermanentMenuKey()} behavior.
217     * These constants must match the definition in res/values/config.xml.
218     */
219    private static final int HAS_PERMANENT_MENU_KEY_AUTODETECT = 0;
220    private static final int HAS_PERMANENT_MENU_KEY_TRUE = 1;
221    private static final int HAS_PERMANENT_MENU_KEY_FALSE = 2;
222
223    private final int mEdgeSlop;
224    private final int mFadingEdgeLength;
225    private final int mMinimumFlingVelocity;
226    private final int mMaximumFlingVelocity;
227    private final int mScrollbarSize;
228    private final int mTouchSlop;
229    private final int mDoubleTapTouchSlop;
230    private final int mPagingTouchSlop;
231    private final int mDoubleTapSlop;
232    private final int mWindowTouchSlop;
233    private final int mMaximumDrawingCacheSize;
234    private final int mOverscrollDistance;
235    private final int mOverflingDistance;
236    private final boolean mFadingMarqueeEnabled;
237    private final long mGlobalActionsKeyTimeout;
238
239    private boolean sHasPermanentMenuKey;
240    private boolean sHasPermanentMenuKeySet;
241
242    static final SparseArray<ViewConfiguration> sConfigurations =
243            new SparseArray<ViewConfiguration>(2);
244
245    /**
246     * @deprecated Use {@link android.view.ViewConfiguration#get(android.content.Context)} instead.
247     */
248    @Deprecated
249    public ViewConfiguration() {
250        mEdgeSlop = EDGE_SLOP;
251        mFadingEdgeLength = FADING_EDGE_LENGTH;
252        mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY;
253        mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY;
254        mScrollbarSize = SCROLL_BAR_SIZE;
255        mTouchSlop = TOUCH_SLOP;
256        mDoubleTapTouchSlop = DOUBLE_TAP_TOUCH_SLOP;
257        mPagingTouchSlop = PAGING_TOUCH_SLOP;
258        mDoubleTapSlop = DOUBLE_TAP_SLOP;
259        mWindowTouchSlop = WINDOW_TOUCH_SLOP;
260        //noinspection deprecation
261        mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE;
262        mOverscrollDistance = OVERSCROLL_DISTANCE;
263        mOverflingDistance = OVERFLING_DISTANCE;
264        mFadingMarqueeEnabled = true;
265        mGlobalActionsKeyTimeout = GLOBAL_ACTIONS_KEY_TIMEOUT;
266    }
267
268    /**
269     * Creates a new configuration for the specified context. The configuration depends on
270     * various parameters of the context, like the dimension of the display or the density
271     * of the display.
272     *
273     * @param context The application context used to initialize this view configuration.
274     *
275     * @see #get(android.content.Context)
276     * @see android.util.DisplayMetrics
277     */
278    private ViewConfiguration(Context context) {
279        final Resources res = context.getResources();
280        final DisplayMetrics metrics = res.getDisplayMetrics();
281        final Configuration config = res.getConfiguration();
282        final float density = metrics.density;
283        final float sizeAndDensity;
284        if (config.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE)) {
285            sizeAndDensity = density * 1.5f;
286        } else {
287            sizeAndDensity = density;
288        }
289
290        mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f);
291        mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f);
292        mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);
293        mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
294        mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
295
296        // Size of the screen in bytes, in ARGB_8888 format
297        final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
298        final Display display = win.getDefaultDisplay();
299        final Point size = new Point();
300        display.getRealSize(size);
301        mMaximumDrawingCacheSize = 4 * size.x * size.y;
302
303        mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f);
304        mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
305
306        if (!sHasPermanentMenuKeySet) {
307            final int configVal = res.getInteger(
308                    com.android.internal.R.integer.config_overrideHasPermanentMenuKey);
309
310            switch (configVal) {
311                default:
312                case HAS_PERMANENT_MENU_KEY_AUTODETECT: {
313                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
314                    try {
315                        sHasPermanentMenuKey = !wm.hasNavigationBar();
316                        sHasPermanentMenuKeySet = true;
317                    } catch (RemoteException ex) {
318                        sHasPermanentMenuKey = false;
319                    }
320                }
321                break;
322
323                case HAS_PERMANENT_MENU_KEY_TRUE:
324                    sHasPermanentMenuKey = true;
325                    sHasPermanentMenuKeySet = true;
326                    break;
327
328                case HAS_PERMANENT_MENU_KEY_FALSE:
329                    sHasPermanentMenuKey = false;
330                    sHasPermanentMenuKeySet = true;
331                    break;
332            }
333        }
334
335        mFadingMarqueeEnabled = res.getBoolean(
336                com.android.internal.R.bool.config_ui_enableFadingMarquee);
337        mTouchSlop = res.getDimensionPixelSize(
338                com.android.internal.R.dimen.config_viewConfigurationTouchSlop);
339        mPagingTouchSlop = mTouchSlop * 2;
340
341        mDoubleTapTouchSlop = mTouchSlop;
342
343        mMinimumFlingVelocity = res.getDimensionPixelSize(
344                com.android.internal.R.dimen.config_viewMinFlingVelocity);
345        mMaximumFlingVelocity = res.getDimensionPixelSize(
346                com.android.internal.R.dimen.config_viewMaxFlingVelocity);
347        mGlobalActionsKeyTimeout = res.getInteger(
348                com.android.internal.R.integer.config_globalActionsKeyTimeout);
349    }
350
351    /**
352     * Returns a configuration for the specified context. The configuration depends on
353     * various parameters of the context, like the dimension of the display or the
354     * density of the display.
355     *
356     * @param context The application context used to initialize the view configuration.
357     */
358    public static ViewConfiguration get(Context context) {
359        final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
360        final int density = (int) (100.0f * metrics.density);
361
362        ViewConfiguration configuration = sConfigurations.get(density);
363        if (configuration == null) {
364            configuration = new ViewConfiguration(context);
365            sConfigurations.put(density, configuration);
366        }
367
368        return configuration;
369    }
370
371    /**
372     * @return The width of the horizontal scrollbar and the height of the vertical
373     *         scrollbar in dips
374     *
375     * @deprecated Use {@link #getScaledScrollBarSize()} instead.
376     */
377    @Deprecated
378    public static int getScrollBarSize() {
379        return SCROLL_BAR_SIZE;
380    }
381
382    /**
383     * @return The width of the horizontal scrollbar and the height of the vertical
384     *         scrollbar in pixels
385     */
386    public int getScaledScrollBarSize() {
387        return mScrollbarSize;
388    }
389
390    /**
391     * @return Duration of the fade when scrollbars fade away in milliseconds
392     */
393    public static int getScrollBarFadeDuration() {
394        return SCROLL_BAR_FADE_DURATION;
395    }
396
397    /**
398     * @return Default delay before the scrollbars fade in milliseconds
399     */
400    public static int getScrollDefaultDelay() {
401        return SCROLL_BAR_DEFAULT_DELAY;
402    }
403
404    /**
405     * @return the length of the fading edges in dips
406     *
407     * @deprecated Use {@link #getScaledFadingEdgeLength()} instead.
408     */
409    @Deprecated
410    public static int getFadingEdgeLength() {
411        return FADING_EDGE_LENGTH;
412    }
413
414    /**
415     * @return the length of the fading edges in pixels
416     */
417    public int getScaledFadingEdgeLength() {
418        return mFadingEdgeLength;
419    }
420
421    /**
422     * @return the duration in milliseconds of the pressed state in child
423     * components.
424     */
425    public static int getPressedStateDuration() {
426        return PRESSED_STATE_DURATION;
427    }
428
429    /**
430     * @return the duration in milliseconds before a press turns into
431     * a long press
432     */
433    public static int getLongPressTimeout() {
434        return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT,
435                DEFAULT_LONG_PRESS_TIMEOUT);
436    }
437
438    /**
439     * @return the time before the first key repeat in milliseconds.
440     */
441    public static int getKeyRepeatTimeout() {
442        return getLongPressTimeout();
443    }
444
445    /**
446     * @return the time between successive key repeats in milliseconds.
447     */
448    public static int getKeyRepeatDelay() {
449        return KEY_REPEAT_DELAY;
450    }
451
452    /**
453     * @return the duration in milliseconds we will wait to see if a touch event
454     * is a tap or a scroll. If the user does not move within this interval, it is
455     * considered to be a tap.
456     */
457    public static int getTapTimeout() {
458        return TAP_TIMEOUT;
459    }
460
461    /**
462     * @return the duration in milliseconds we will wait to see if a touch event
463     * is a jump tap. If the user does not move within this interval, it is
464     * considered to be a tap.
465     */
466    public static int getJumpTapTimeout() {
467        return JUMP_TAP_TIMEOUT;
468    }
469
470    /**
471     * @return the duration in milliseconds between the first tap's up event and
472     * the second tap's down event for an interaction to be considered a
473     * double-tap.
474     */
475    public static int getDoubleTapTimeout() {
476        return DOUBLE_TAP_TIMEOUT;
477    }
478
479    /**
480     * @return the minimum duration in milliseconds between the first tap's
481     * up event and the second tap's down event for an interaction to be considered a
482     * double-tap.
483     *
484     * @hide
485     */
486    public static int getDoubleTapMinTime() {
487        return DOUBLE_TAP_MIN_TIME;
488    }
489
490    /**
491     * @return the maximum duration in milliseconds between a touch pad
492     * touch and release for a given touch to be considered a tap (click) as
493     * opposed to a hover movement gesture.
494     * @hide
495     */
496    public static int getHoverTapTimeout() {
497        return HOVER_TAP_TIMEOUT;
498    }
499
500    /**
501     * @return the maximum distance in pixels that a touch pad touch can move
502     * before being released for it to be considered a tap (click) as opposed
503     * to a hover movement gesture.
504     * @hide
505     */
506    public static int getHoverTapSlop() {
507        return HOVER_TAP_SLOP;
508    }
509
510    /**
511     * @return Inset in dips to look for touchable content when the user touches the edge of the
512     *         screen
513     *
514     * @deprecated Use {@link #getScaledEdgeSlop()} instead.
515     */
516    @Deprecated
517    public static int getEdgeSlop() {
518        return EDGE_SLOP;
519    }
520
521    /**
522     * @return Inset in pixels to look for touchable content when the user touches the edge of the
523     *         screen
524     */
525    public int getScaledEdgeSlop() {
526        return mEdgeSlop;
527    }
528
529    /**
530     * @return Distance in dips a touch can wander before we think the user is scrolling
531     *
532     * @deprecated Use {@link #getScaledTouchSlop()} instead.
533     */
534    @Deprecated
535    public static int getTouchSlop() {
536        return TOUCH_SLOP;
537    }
538
539    /**
540     * @return Distance in pixels a touch can wander before we think the user is scrolling
541     */
542    public int getScaledTouchSlop() {
543        return mTouchSlop;
544    }
545
546    /**
547     * @return Distance in pixels the first touch can wander before we do not consider this a
548     * potential double tap event
549     * @hide
550     */
551    public int getScaledDoubleTapTouchSlop() {
552        return mDoubleTapTouchSlop;
553    }
554
555    /**
556     * @return Distance in pixels a touch can wander before we think the user is scrolling a full
557     * page
558     */
559    public int getScaledPagingTouchSlop() {
560        return mPagingTouchSlop;
561    }
562
563    /**
564     * @return Distance in dips between the first touch and second touch to still be
565     *         considered a double tap
566     * @deprecated Use {@link #getScaledDoubleTapSlop()} instead.
567     * @hide The only client of this should be GestureDetector, which needs this
568     *       for clients that still use its deprecated constructor.
569     */
570    @Deprecated
571    public static int getDoubleTapSlop() {
572        return DOUBLE_TAP_SLOP;
573    }
574
575    /**
576     * @return Distance in pixels between the first touch and second touch to still be
577     *         considered a double tap
578     */
579    public int getScaledDoubleTapSlop() {
580        return mDoubleTapSlop;
581    }
582
583    /**
584     * Interval for dispatching a recurring accessibility event in milliseconds.
585     * This interval guarantees that a recurring event will be send at most once
586     * during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame.
587     *
588     * @return The delay in milliseconds.
589     *
590     * @hide
591     */
592    public static long getSendRecurringAccessibilityEventsInterval() {
593        return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS;
594    }
595
596    /**
597     * @return Distance in dips a touch must be outside the bounds of a window for it
598     * to be counted as outside the window for purposes of dismissing that
599     * window.
600     *
601     * @deprecated Use {@link #getScaledWindowTouchSlop()} instead.
602     */
603    @Deprecated
604    public static int getWindowTouchSlop() {
605        return WINDOW_TOUCH_SLOP;
606    }
607
608    /**
609     * @return Distance in pixels a touch must be outside the bounds of a window for it
610     * to be counted as outside the window for purposes of dismissing that window.
611     */
612    public int getScaledWindowTouchSlop() {
613        return mWindowTouchSlop;
614    }
615
616    /**
617     * @return Minimum velocity to initiate a fling, as measured in dips per second.
618     *
619     * @deprecated Use {@link #getScaledMinimumFlingVelocity()} instead.
620     */
621    @Deprecated
622    public static int getMinimumFlingVelocity() {
623        return MINIMUM_FLING_VELOCITY;
624    }
625
626    /**
627     * @return Minimum velocity to initiate a fling, as measured in pixels per second.
628     */
629    public int getScaledMinimumFlingVelocity() {
630        return mMinimumFlingVelocity;
631    }
632
633    /**
634     * @return Maximum velocity to initiate a fling, as measured in dips per second.
635     *
636     * @deprecated Use {@link #getScaledMaximumFlingVelocity()} instead.
637     */
638    @Deprecated
639    public static int getMaximumFlingVelocity() {
640        return MAXIMUM_FLING_VELOCITY;
641    }
642
643    /**
644     * @return Maximum velocity to initiate a fling, as measured in pixels per second.
645     */
646    public int getScaledMaximumFlingVelocity() {
647        return mMaximumFlingVelocity;
648    }
649
650    /**
651     * The maximum drawing cache size expressed in bytes.
652     *
653     * @return the maximum size of View's drawing cache expressed in bytes
654     *
655     * @deprecated Use {@link #getScaledMaximumDrawingCacheSize()} instead.
656     */
657    @Deprecated
658    public static int getMaximumDrawingCacheSize() {
659        //noinspection deprecation
660        return MAXIMUM_DRAWING_CACHE_SIZE;
661    }
662
663    /**
664     * The maximum drawing cache size expressed in bytes.
665     *
666     * @return the maximum size of View's drawing cache expressed in bytes
667     */
668    public int getScaledMaximumDrawingCacheSize() {
669        return mMaximumDrawingCacheSize;
670    }
671
672    /**
673     * @return The maximum distance a View should overscroll by when showing edge effects (in
674     * pixels).
675     */
676    public int getScaledOverscrollDistance() {
677        return mOverscrollDistance;
678    }
679
680    /**
681     * @return The maximum distance a View should overfling by when showing edge effects (in
682     * pixels).
683     */
684    public int getScaledOverflingDistance() {
685        return mOverflingDistance;
686    }
687
688    /**
689     * The amount of time that the zoom controls should be
690     * displayed on the screen expressed in milliseconds.
691     *
692     * @return the time the zoom controls should be visible expressed
693     * in milliseconds.
694     */
695    public static long getZoomControlsTimeout() {
696        return ZOOM_CONTROLS_TIMEOUT;
697    }
698
699    /**
700     * The amount of time a user needs to press the relevant key to bring up
701     * the global actions dialog.
702     *
703     * @return how long a user needs to press the relevant key to bring up
704     *   the global actions dialog.
705     * @deprecated This timeout should not be used by applications
706     */
707    @Deprecated
708    public static long getGlobalActionKeyTimeout() {
709        return GLOBAL_ACTIONS_KEY_TIMEOUT;
710    }
711
712    /**
713     * The amount of time a user needs to press the relevant key to bring up
714     * the global actions dialog.
715     *
716     * @return how long a user needs to press the relevant key to bring up
717     *   the global actions dialog.
718     * @hide
719     */
720    public long getDeviceGlobalActionKeyTimeout() {
721        return mGlobalActionsKeyTimeout;
722    }
723
724    /**
725     * The amount of friction applied to scrolls and flings.
726     *
727     * @return A scalar dimensionless value representing the coefficient of
728     *         friction.
729     */
730    public static float getScrollFriction() {
731        return SCROLL_FRICTION;
732    }
733
734    /**
735     * Report if the device has a permanent menu key available to the user.
736     *
737     * <p>As of Android 3.0, devices may not have a permanent menu key available.
738     * Apps should use the action bar to present menu options to users.
739     * However, there are some apps where the action bar is inappropriate
740     * or undesirable. This method may be used to detect if a menu key is present.
741     * If not, applications should provide another on-screen affordance to access
742     * functionality.
743     *
744     * @return true if a permanent menu key is present, false otherwise.
745     */
746    public boolean hasPermanentMenuKey() {
747        return sHasPermanentMenuKey;
748    }
749
750    /**
751     * @hide
752     * @return Whether or not marquee should use fading edges.
753     */
754    public boolean isFadingMarqueeEnabled() {
755        return mFadingMarqueeEnabled;
756    }
757}
758