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