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 com.android.internal.R;
     20 import com.android.internal.view.menu.MenuBuilder;
     21 
     22 import android.content.Context;
     23 import android.content.res.Configuration;
     24 import android.content.res.Resources;
     25 import android.content.res.TypedArray;
     26 import android.graphics.Bitmap;
     27 import android.graphics.Canvas;
     28 import android.graphics.Interpolator;
     29 import android.graphics.LinearGradient;
     30 import android.graphics.Matrix;
     31 import android.graphics.Paint;
     32 import android.graphics.PixelFormat;
     33 import android.graphics.Point;
     34 import android.graphics.PorterDuff;
     35 import android.graphics.PorterDuffXfermode;
     36 import android.graphics.Rect;
     37 import android.graphics.Region;
     38 import android.graphics.Shader;
     39 import android.graphics.drawable.ColorDrawable;
     40 import android.graphics.drawable.Drawable;
     41 import android.os.Handler;
     42 import android.os.IBinder;
     43 import android.os.Message;
     44 import android.os.Parcel;
     45 import android.os.Parcelable;
     46 import android.os.RemoteException;
     47 import android.os.SystemClock;
     48 import android.os.SystemProperties;
     49 import android.util.AttributeSet;
     50 import android.util.Config;
     51 import android.util.EventLog;
     52 import android.util.Log;
     53 import android.util.Pool;
     54 import android.util.Poolable;
     55 import android.util.PoolableManager;
     56 import android.util.Pools;
     57 import android.util.SparseArray;
     58 import android.view.ContextMenu.ContextMenuInfo;
     59 import android.view.accessibility.AccessibilityEvent;
     60 import android.view.accessibility.AccessibilityEventSource;
     61 import android.view.accessibility.AccessibilityManager;
     62 import android.view.animation.Animation;
     63 import android.view.animation.AnimationUtils;
     64 import android.view.inputmethod.EditorInfo;
     65 import android.view.inputmethod.InputConnection;
     66 import android.view.inputmethod.InputMethodManager;
     67 import android.widget.ScrollBarDrawable;
     68 
     69 import java.lang.ref.SoftReference;
     70 import java.lang.reflect.InvocationTargetException;
     71 import java.lang.reflect.Method;
     72 import java.util.ArrayList;
     73 import java.util.Arrays;
     74 import java.util.WeakHashMap;
     75 
     76 /**
     77  * <p>
     78  * This class represents the basic building block for user interface components. A View
     79  * occupies a rectangular area on the screen and is responsible for drawing and
     80  * event handling. View is the base class for <em>widgets</em>, which are
     81  * used to create interactive UI components (buttons, text fields, etc.). The
     82  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
     83  * are invisible containers that hold other Views (or other ViewGroups) and define
     84  * their layout properties.
     85  * </p>
     86  *
     87  * <div class="special">
     88  * <p>For an introduction to using this class to develop your
     89  * application's user interface, read the Developer Guide documentation on
     90  * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics
     91  * include:
     92  * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a>
     93  * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>
     94  * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a>
     95  * <br/><a href="{@docRoot}guide/topics/ui/binding.html">Binding to Data with AdapterView</a>
     96  * <br/><a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
     97  * <br/><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>
     98  * <br/><a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
     99  * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>.
    100  * </p>
    101  * </div>
    102  *
    103  * <a name="Using"></a>
    104  * <h3>Using Views</h3>
    105  * <p>
    106  * All of the views in a window are arranged in a single tree. You can add views
    107  * either from code or by specifying a tree of views in one or more XML layout
    108  * files. There are many specialized subclasses of views that act as controls or
    109  * are capable of displaying text, images, or other content.
    110  * </p>
    111  * <p>
    112  * Once you have created a tree of views, there are typically a few types of
    113  * common operations you may wish to perform:
    114  * <ul>
    115  * <li><strong>Set properties:</strong> for example setting the text of a
    116  * {@link android.widget.TextView}. The available properties and the methods
    117  * that set them will vary among the different subclasses of views. Note that
    118  * properties that are known at build time can be set in the XML layout
    119  * files.</li>
    120  * <li><strong>Set focus:</strong> The framework will handled moving focus in
    121  * response to user input. To force focus to a specific view, call
    122  * {@link #requestFocus}.</li>
    123  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
    124  * that will be notified when something interesting happens to the view. For
    125  * example, all views will let you set a listener to be notified when the view
    126  * gains or loses focus. You can register such a listener using
    127  * {@link #setOnFocusChangeListener}. Other view subclasses offer more
    128  * specialized listeners. For example, a Button exposes a listener to notify
    129  * clients when the button is clicked.</li>
    130  * <li><strong>Set visibility:</strong> You can hide or show views using
    131  * {@link #setVisibility}.</li>
    132  * </ul>
    133  * </p>
    134  * <p><em>
    135  * Note: The Android framework is responsible for measuring, laying out and
    136  * drawing views. You should not call methods that perform these actions on
    137  * views yourself unless you are actually implementing a
    138  * {@link android.view.ViewGroup}.
    139  * </em></p>
    140  *
    141  * <a name="Lifecycle"></a>
    142  * <h3>Implementing a Custom View</h3>
    143  *
    144  * <p>
    145  * To implement a custom view, you will usually begin by providing overrides for
    146  * some of the standard methods that the framework calls on all views. You do
    147  * not need to override all of these methods. In fact, you can start by just
    148  * overriding {@link #onDraw(android.graphics.Canvas)}.
    149  * <table border="2" width="85%" align="center" cellpadding="5">
    150  *     <thead>
    151  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
    152  *     </thead>
    153  *
    154  *     <tbody>
    155  *     <tr>
    156  *         <td rowspan="2">Creation</td>
    157  *         <td>Constructors</td>
    158  *         <td>There is a form of the constructor that are called when the view
    159  *         is created from code and a form that is called when the view is
    160  *         inflated from a layout file. The second form should parse and apply
    161  *         any attributes defined in the layout file.
    162  *         </td>
    163  *     </tr>
    164  *     <tr>
    165  *         <td><code>{@link #onFinishInflate()}</code></td>
    166  *         <td>Called after a view and all of its children has been inflated
    167  *         from XML.</td>
    168  *     </tr>
    169  *
    170  *     <tr>
    171  *         <td rowspan="3">Layout</td>
    172  *         <td><code>{@link #onMeasure}</code></td>
    173  *         <td>Called to determine the size requirements for this view and all
    174  *         of its children.
    175  *         </td>
    176  *     </tr>
    177  *     <tr>
    178  *         <td><code>{@link #onLayout}</code></td>
    179  *         <td>Called when this view should assign a size and position to all
    180  *         of its children.
    181  *         </td>
    182  *     </tr>
    183  *     <tr>
    184  *         <td><code>{@link #onSizeChanged}</code></td>
    185  *         <td>Called when the size of this view has changed.
    186  *         </td>
    187  *     </tr>
    188  *
    189  *     <tr>
    190  *         <td>Drawing</td>
    191  *         <td><code>{@link #onDraw}</code></td>
    192  *         <td>Called when the view should render its content.
    193  *         </td>
    194  *     </tr>
    195  *
    196  *     <tr>
    197  *         <td rowspan="4">Event processing</td>
    198  *         <td><code>{@link #onKeyDown}</code></td>
    199  *         <td>Called when a new key event occurs.
    200  *         </td>
    201  *     </tr>
    202  *     <tr>
    203  *         <td><code>{@link #onKeyUp}</code></td>
    204  *         <td>Called when a key up event occurs.
    205  *         </td>
    206  *     </tr>
    207  *     <tr>
    208  *         <td><code>{@link #onTrackballEvent}</code></td>
    209  *         <td>Called when a trackball motion event occurs.
    210  *         </td>
    211  *     </tr>
    212  *     <tr>
    213  *         <td><code>{@link #onTouchEvent}</code></td>
    214  *         <td>Called when a touch screen motion event occurs.
    215  *         </td>
    216  *     </tr>
    217  *
    218  *     <tr>
    219  *         <td rowspan="2">Focus</td>
    220  *         <td><code>{@link #onFocusChanged}</code></td>
    221  *         <td>Called when the view gains or loses focus.
    222  *         </td>
    223  *     </tr>
    224  *
    225  *     <tr>
    226  *         <td><code>{@link #onWindowFocusChanged}</code></td>
    227  *         <td>Called when the window containing the view gains or loses focus.
    228  *         </td>
    229  *     </tr>
    230  *
    231  *     <tr>
    232  *         <td rowspan="3">Attaching</td>
    233  *         <td><code>{@link #onAttachedToWindow()}</code></td>
    234  *         <td>Called when the view is attached to a window.
    235  *         </td>
    236  *     </tr>
    237  *
    238  *     <tr>
    239  *         <td><code>{@link #onDetachedFromWindow}</code></td>
    240  *         <td>Called when the view is detached from its window.
    241  *         </td>
    242  *     </tr>
    243  *
    244  *     <tr>
    245  *         <td><code>{@link #onWindowVisibilityChanged}</code></td>
    246  *         <td>Called when the visibility of the window containing the view
    247  *         has changed.
    248  *         </td>
    249  *     </tr>
    250  *     </tbody>
    251  *
    252  * </table>
    253  * </p>
    254  *
    255  * <a name="IDs"></a>
    256  * <h3>IDs</h3>
    257  * Views may have an integer id associated with them. These ids are typically
    258  * assigned in the layout XML files, and are used to find specific views within
    259  * the view tree. A common pattern is to:
    260  * <ul>
    261  * <li>Define a Button in the layout file and assign it a unique ID.
    262  * <pre>
    263  * &lt;Button id="@+id/my_button"
    264  *     android:layout_width="wrap_content"
    265  *     android:layout_height="wrap_content"
    266  *     android:text="@string/my_button_text"/&gt;
    267  * </pre></li>
    268  * <li>From the onCreate method of an Activity, find the Button
    269  * <pre class="prettyprint">
    270  *      Button myButton = (Button) findViewById(R.id.my_button);
    271  * </pre></li>
    272  * </ul>
    273  * <p>
    274  * View IDs need not be unique throughout the tree, but it is good practice to
    275  * ensure that they are at least unique within the part of the tree you are
    276  * searching.
    277  * </p>
    278  *
    279  * <a name="Position"></a>
    280  * <h3>Position</h3>
    281  * <p>
    282  * The geometry of a view is that of a rectangle. A view has a location,
    283  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
    284  * two dimensions, expressed as a width and a height. The unit for location
    285  * and dimensions is the pixel.
    286  * </p>
    287  *
    288  * <p>
    289  * It is possible to retrieve the location of a view by invoking the methods
    290  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
    291  * coordinate of the rectangle representing the view. The latter returns the
    292  * top, or Y, coordinate of the rectangle representing the view. These methods
    293  * both return the location of the view relative to its parent. For instance,
    294  * when getLeft() returns 20, that means the view is located 20 pixels to the
    295  * right of the left edge of its direct parent.
    296  * </p>
    297  *
    298  * <p>
    299  * In addition, several convenience methods are offered to avoid unnecessary
    300  * computations, namely {@link #getRight()} and {@link #getBottom()}.
    301  * These methods return the coordinates of the right and bottom edges of the
    302  * rectangle representing the view. For instance, calling {@link #getRight()}
    303  * is similar to the following computation: <code>getLeft() + getWidth()</code>
    304  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
    305  * </p>
    306  *
    307  * <a name="SizePaddingMargins"></a>
    308  * <h3>Size, padding and margins</h3>
    309  * <p>
    310  * The size of a view is expressed with a width and a height. A view actually
    311  * possess two pairs of width and height values.
    312  * </p>
    313  *
    314  * <p>
    315  * The first pair is known as <em>measured width</em> and
    316  * <em>measured height</em>. These dimensions define how big a view wants to be
    317  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
    318  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
    319  * and {@link #getMeasuredHeight()}.
    320  * </p>
    321  *
    322  * <p>
    323  * The second pair is simply known as <em>width</em> and <em>height</em>, or
    324  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
    325  * dimensions define the actual size of the view on screen, at drawing time and
    326  * after layout. These values may, but do not have to, be different from the
    327  * measured width and height. The width and height can be obtained by calling
    328  * {@link #getWidth()} and {@link #getHeight()}.
    329  * </p>
    330  *
    331  * <p>
    332  * To measure its dimensions, a view takes into account its padding. The padding
    333  * is expressed in pixels for the left, top, right and bottom parts of the view.
    334  * Padding can be used to offset the content of the view by a specific amount of
    335  * pixels. For instance, a left padding of 2 will push the view's content by
    336  * 2 pixels to the right of the left edge. Padding can be set using the
    337  * {@link #setPadding(int, int, int, int)} method and queried by calling
    338  * {@link #getPaddingLeft()}, {@link #getPaddingTop()},
    339  * {@link #getPaddingRight()} and {@link #getPaddingBottom()}.
    340  * </p>
    341  *
    342  * <p>
    343  * Even though a view can define a padding, it does not provide any support for
    344  * margins. However, view groups provide such a support. Refer to
    345  * {@link android.view.ViewGroup} and
    346  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
    347  * </p>
    348  *
    349  * <a name="Layout"></a>
    350  * <h3>Layout</h3>
    351  * <p>
    352  * Layout is a two pass process: a measure pass and a layout pass. The measuring
    353  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
    354  * of the view tree. Each view pushes dimension specifications down the tree
    355  * during the recursion. At the end of the measure pass, every view has stored
    356  * its measurements. The second pass happens in
    357  * {@link #layout(int,int,int,int)} and is also top-down. During
    358  * this pass each parent is responsible for positioning all of its children
    359  * using the sizes computed in the measure pass.
    360  * </p>
    361  *
    362  * <p>
    363  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
    364  * {@link #getMeasuredHeight()} values must be set, along with those for all of
    365  * that view's descendants. A view's measured width and measured height values
    366  * must respect the constraints imposed by the view's parents. This guarantees
    367  * that at the end of the measure pass, all parents accept all of their
    368  * children's measurements. A parent view may call measure() more than once on
    369  * its children. For example, the parent may measure each child once with
    370  * unspecified dimensions to find out how big they want to be, then call
    371  * measure() on them again with actual numbers if the sum of all the children's
    372  * unconstrained sizes is too big or too small.
    373  * </p>
    374  *
    375  * <p>
    376  * The measure pass uses two classes to communicate dimensions. The
    377  * {@link MeasureSpec} class is used by views to tell their parents how they
    378  * want to be measured and positioned. The base LayoutParams class just
    379  * describes how big the view wants to be for both width and height. For each
    380  * dimension, it can specify one of:
    381  * <ul>
    382  * <li> an exact number
    383  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
    384  * (minus padding)
    385  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
    386  * enclose its content (plus padding).
    387  * </ul>
    388  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
    389  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
    390  * an X and Y value.
    391  * </p>
    392  *
    393  * <p>
    394  * MeasureSpecs are used to push requirements down the tree from parent to
    395  * child. A MeasureSpec can be in one of three modes:
    396  * <ul>
    397  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
    398  * of a child view. For example, a LinearLayout may call measure() on its child
    399  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
    400  * tall the child view wants to be given a width of 240 pixels.
    401  * <li>EXACTLY: This is used by the parent to impose an exact size on the
    402  * child. The child must use this size, and guarantee that all of its
    403  * descendants will fit within this size.
    404  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
    405  * child. The child must gurantee that it and all of its descendants will fit
    406  * within this size.
    407  * </ul>
    408  * </p>
    409  *
    410  * <p>
    411  * To intiate a layout, call {@link #requestLayout}. This method is typically
    412  * called by a view on itself when it believes that is can no longer fit within
    413  * its current bounds.
    414  * </p>
    415  *
    416  * <a name="Drawing"></a>
    417  * <h3>Drawing</h3>
    418  * <p>
    419  * Drawing is handled by walking the tree and rendering each view that
    420  * intersects the the invalid region. Because the tree is traversed in-order,
    421  * this means that parents will draw before (i.e., behind) their children, with
    422  * siblings drawn in the order they appear in the tree.
    423  * If you set a background drawable for a View, then the View will draw it for you
    424  * before calling back to its <code>onDraw()</code> method.
    425  * </p>
    426  *
    427  * <p>
    428  * Note that the framework will not draw views that are not in the invalid region.
    429  * </p>
    430  *
    431  * <p>
    432  * To force a view to draw, call {@link #invalidate()}.
    433  * </p>
    434  *
    435  * <a name="EventHandlingThreading"></a>
    436  * <h3>Event Handling and Threading</h3>
    437  * <p>
    438  * The basic cycle of a view is as follows:
    439  * <ol>
    440  * <li>An event comes in and is dispatched to the appropriate view. The view
    441  * handles the event and notifies any listeners.</li>
    442  * <li>If in the course of processing the event, the view's bounds may need
    443  * to be changed, the view will call {@link #requestLayout()}.</li>
    444  * <li>Similarly, if in the course of processing the event the view's appearance
    445  * may need to be changed, the view will call {@link #invalidate()}.</li>
    446  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
    447  * the framework will take care of measuring, laying out, and drawing the tree
    448  * as appropriate.</li>
    449  * </ol>
    450  * </p>
    451  *
    452  * <p><em>Note: The entire view tree is single threaded. You must always be on
    453  * the UI thread when calling any method on any view.</em>
    454  * If you are doing work on other threads and want to update the state of a view
    455  * from that thread, you should use a {@link Handler}.
    456  * </p>
    457  *
    458  * <a name="FocusHandling"></a>
    459  * <h3>Focus Handling</h3>
    460  * <p>
    461  * The framework will handle routine focus movement in response to user input.
    462  * This includes changing the focus as views are removed or hidden, or as new
    463  * views become available. Views indicate their willingness to take focus
    464  * through the {@link #isFocusable} method. To change whether a view can take
    465  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
    466  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
    467  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
    468  * </p>
    469  * <p>
    470  * Focus movement is based on an algorithm which finds the nearest neighbor in a
    471  * given direction. In rare cases, the default algorithm may not match the
    472  * intended behavior of the developer. In these situations, you can provide
    473  * explicit overrides by using these XML attributes in the layout file:
    474  * <pre>
    475  * nextFocusDown
    476  * nextFocusLeft
    477  * nextFocusRight
    478  * nextFocusUp
    479  * </pre>
    480  * </p>
    481  *
    482  *
    483  * <p>
    484  * To get a particular view to take focus, call {@link #requestFocus()}.
    485  * </p>
    486  *
    487  * <a name="TouchMode"></a>
    488  * <h3>Touch Mode</h3>
    489  * <p>
    490  * When a user is navigating a user interface via directional keys such as a D-pad, it is
    491  * necessary to give focus to actionable items such as buttons so the user can see
    492  * what will take input.  If the device has touch capabilities, however, and the user
    493  * begins interacting with the interface by touching it, it is no longer necessary to
    494  * always highlight, or give focus to, a particular view.  This motivates a mode
    495  * for interaction named 'touch mode'.
    496  * </p>
    497  * <p>
    498  * For a touch capable device, once the user touches the screen, the device
    499  * will enter touch mode.  From this point onward, only views for which
    500  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
    501  * Other views that are touchable, like buttons, will not take focus when touched; they will
    502  * only fire the on click listeners.
    503  * </p>
    504  * <p>
    505  * Any time a user hits a directional key, such as a D-pad direction, the view device will
    506  * exit touch mode, and find a view to take focus, so that the user may resume interacting
    507  * with the user interface without touching the screen again.
    508  * </p>
    509  * <p>
    510  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
    511  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
    512  * </p>
    513  *
    514  * <a name="Scrolling"></a>
    515  * <h3>Scrolling</h3>
    516  * <p>
    517  * The framework provides basic support for views that wish to internally
    518  * scroll their content. This includes keeping track of the X and Y scroll
    519  * offset as well as mechanisms for drawing scrollbars. See
    520  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
    521  * {@link #awakenScrollBars()} for more details.
    522  * </p>
    523  *
    524  * <a name="Tags"></a>
    525  * <h3>Tags</h3>
    526  * <p>
    527  * Unlike IDs, tags are not used to identify views. Tags are essentially an
    528  * extra piece of information that can be associated with a view. They are most
    529  * often used as a convenience to store data related to views in the views
    530  * themselves rather than by putting them in a separate structure.
    531  * </p>
    532  *
    533  * <a name="Animation"></a>
    534  * <h3>Animation</h3>
    535  * <p>
    536  * You can attach an {@link Animation} object to a view using
    537  * {@link #setAnimation(Animation)} or
    538  * {@link #startAnimation(Animation)}. The animation can alter the scale,
    539  * rotation, translation and alpha of a view over time. If the animation is
    540  * attached to a view that has children, the animation will affect the entire
    541  * subtree rooted by that node. When an animation is started, the framework will
    542  * take care of redrawing the appropriate views until the animation completes.
    543  * </p>
    544  *
    545  * <a name="Security"></a>
    546  * <h3>Security</h3>
    547  * <p>
    548  * Sometimes it is essential that an application be able to verify that an action
    549  * is being performed with the full knowledge and consent of the user, such as
    550  * granting a permission request, making a purchase or clicking on an advertisement.
    551  * Unfortunately, a malicious application could try to spoof the user into
    552  * performing these actions, unaware, by concealing the intended purpose of the view.
    553  * As a remedy, the framework offers a touch filtering mechanism that can be used to
    554  * improve the security of views that provide access to sensitive functionality.
    555  * </p><p>
    556  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured} or set the
    557  * andoird:filterTouchesWhenObscured attribute to true.  When enabled, the framework
    558  * will discard touches that are received whenever the view's window is obscured by
    559  * another visible window.  As a result, the view will not receive touches whenever a
    560  * toast, dialog or other window appears above the view's window.
    561  * </p><p>
    562  * For more fine-grained control over security, consider overriding the
    563  * {@link #onFilterTouchEventForSecurity} method to implement your own security policy.
    564  * See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
    565  * </p>
    566  *
    567  * @attr ref android.R.styleable#View_background
    568  * @attr ref android.R.styleable#View_clickable
    569  * @attr ref android.R.styleable#View_contentDescription
    570  * @attr ref android.R.styleable#View_drawingCacheQuality
    571  * @attr ref android.R.styleable#View_duplicateParentState
    572  * @attr ref android.R.styleable#View_id
    573  * @attr ref android.R.styleable#View_fadingEdge
    574  * @attr ref android.R.styleable#View_fadingEdgeLength
    575  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
    576  * @attr ref android.R.styleable#View_fitsSystemWindows
    577  * @attr ref android.R.styleable#View_isScrollContainer
    578  * @attr ref android.R.styleable#View_focusable
    579  * @attr ref android.R.styleable#View_focusableInTouchMode
    580  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
    581  * @attr ref android.R.styleable#View_keepScreenOn
    582  * @attr ref android.R.styleable#View_longClickable
    583  * @attr ref android.R.styleable#View_minHeight
    584  * @attr ref android.R.styleable#View_minWidth
    585  * @attr ref android.R.styleable#View_nextFocusDown
    586  * @attr ref android.R.styleable#View_nextFocusLeft
    587  * @attr ref android.R.styleable#View_nextFocusRight
    588  * @attr ref android.R.styleable#View_nextFocusUp
    589  * @attr ref android.R.styleable#View_onClick
    590  * @attr ref android.R.styleable#View_padding
    591  * @attr ref android.R.styleable#View_paddingBottom
    592  * @attr ref android.R.styleable#View_paddingLeft
    593  * @attr ref android.R.styleable#View_paddingRight
    594  * @attr ref android.R.styleable#View_paddingTop
    595  * @attr ref android.R.styleable#View_saveEnabled
    596  * @attr ref android.R.styleable#View_scrollX
    597  * @attr ref android.R.styleable#View_scrollY
    598  * @attr ref android.R.styleable#View_scrollbarSize
    599  * @attr ref android.R.styleable#View_scrollbarStyle
    600  * @attr ref android.R.styleable#View_scrollbars
    601  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
    602  * @attr ref android.R.styleable#View_scrollbarFadeDuration
    603  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
    604  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
    605  * @attr ref android.R.styleable#View_scrollbarThumbVertical
    606  * @attr ref android.R.styleable#View_scrollbarTrackVertical
    607  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
    608  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
    609  * @attr ref android.R.styleable#View_soundEffectsEnabled
    610  * @attr ref android.R.styleable#View_tag
    611  * @attr ref android.R.styleable#View_visibility
    612  *
    613  * @see android.view.ViewGroup
    614  */
    615 public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
    616     private static final boolean DBG = false;
    617 
    618     /**
    619      * The logging tag used by this class with android.util.Log.
    620      */
    621     protected static final String VIEW_LOG_TAG = "View";
    622 
    623     /**
    624      * Used to mark a View that has no ID.
    625      */
    626     public static final int NO_ID = -1;
    627 
    628     /**
    629      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
    630      * calling setFlags.
    631      */
    632     private static final int NOT_FOCUSABLE = 0x00000000;
    633 
    634     /**
    635      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
    636      * setFlags.
    637      */
    638     private static final int FOCUSABLE = 0x00000001;
    639 
    640     /**
    641      * Mask for use with setFlags indicating bits used for focus.
    642      */
    643     private static final int FOCUSABLE_MASK = 0x00000001;
    644 
    645     /**
    646      * This view will adjust its padding to fit sytem windows (e.g. status bar)
    647      */
    648     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
    649 
    650     /**
    651      * This view is visible.  Use with {@link #setVisibility}.
    652      */
    653     public static final int VISIBLE = 0x00000000;
    654 
    655     /**
    656      * This view is invisible, but it still takes up space for layout purposes.
    657      * Use with {@link #setVisibility}.
    658      */
    659     public static final int INVISIBLE = 0x00000004;
    660 
    661     /**
    662      * This view is invisible, and it doesn't take any space for layout
    663      * purposes. Use with {@link #setVisibility}.
    664      */
    665     public static final int GONE = 0x00000008;
    666 
    667     /**
    668      * Mask for use with setFlags indicating bits used for visibility.
    669      * {@hide}
    670      */
    671     static final int VISIBILITY_MASK = 0x0000000C;
    672 
    673     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
    674 
    675     /**
    676      * This view is enabled. Intrepretation varies by subclass.
    677      * Use with ENABLED_MASK when calling setFlags.
    678      * {@hide}
    679      */
    680     static final int ENABLED = 0x00000000;
    681 
    682     /**
    683      * This view is disabled. Intrepretation varies by subclass.
    684      * Use with ENABLED_MASK when calling setFlags.
    685      * {@hide}
    686      */
    687     static final int DISABLED = 0x00000020;
    688 
    689    /**
    690     * Mask for use with setFlags indicating bits used for indicating whether
    691     * this view is enabled
    692     * {@hide}
    693     */
    694     static final int ENABLED_MASK = 0x00000020;
    695 
    696     /**
    697      * This view won't draw. {@link #onDraw} won't be called and further
    698      * optimizations
    699      * will be performed. It is okay to have this flag set and a background.
    700      * Use with DRAW_MASK when calling setFlags.
    701      * {@hide}
    702      */
    703     static final int WILL_NOT_DRAW = 0x00000080;
    704 
    705     /**
    706      * Mask for use with setFlags indicating bits used for indicating whether
    707      * this view is will draw
    708      * {@hide}
    709      */
    710     static final int DRAW_MASK = 0x00000080;
    711 
    712     /**
    713      * <p>This view doesn't show scrollbars.</p>
    714      * {@hide}
    715      */
    716     static final int SCROLLBARS_NONE = 0x00000000;
    717 
    718     /**
    719      * <p>This view shows horizontal scrollbars.</p>
    720      * {@hide}
    721      */
    722     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
    723 
    724     /**
    725      * <p>This view shows vertical scrollbars.</p>
    726      * {@hide}
    727      */
    728     static final int SCROLLBARS_VERTICAL = 0x00000200;
    729 
    730     /**
    731      * <p>Mask for use with setFlags indicating bits used for indicating which
    732      * scrollbars are enabled.</p>
    733      * {@hide}
    734      */
    735     static final int SCROLLBARS_MASK = 0x00000300;
    736 
    737     /**
    738      * Indicates that the view should filter touches when its window is obscured.
    739      * Refer to the class comments for more information about this security feature.
    740      * {@hide}
    741      */
    742     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
    743 
    744     // note flag value 0x00000800 is now available for next flags...
    745 
    746     /**
    747      * <p>This view doesn't show fading edges.</p>
    748      * {@hide}
    749      */
    750     static final int FADING_EDGE_NONE = 0x00000000;
    751 
    752     /**
    753      * <p>This view shows horizontal fading edges.</p>
    754      * {@hide}
    755      */
    756     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
    757 
    758     /**
    759      * <p>This view shows vertical fading edges.</p>
    760      * {@hide}
    761      */
    762     static final int FADING_EDGE_VERTICAL = 0x00002000;
    763 
    764     /**
    765      * <p>Mask for use with setFlags indicating bits used for indicating which
    766      * fading edges are enabled.</p>
    767      * {@hide}
    768      */
    769     static final int FADING_EDGE_MASK = 0x00003000;
    770 
    771     /**
    772      * <p>Indicates this view can be clicked. When clickable, a View reacts
    773      * to clicks by notifying the OnClickListener.<p>
    774      * {@hide}
    775      */
    776     static final int CLICKABLE = 0x00004000;
    777 
    778     /**
    779      * <p>Indicates this view is caching its drawing into a bitmap.</p>
    780      * {@hide}
    781      */
    782     static final int DRAWING_CACHE_ENABLED = 0x00008000;
    783 
    784     /**
    785      * <p>Indicates that no icicle should be saved for this view.<p>
    786      * {@hide}
    787      */
    788     static final int SAVE_DISABLED = 0x000010000;
    789 
    790     /**
    791      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
    792      * property.</p>
    793      * {@hide}
    794      */
    795     static final int SAVE_DISABLED_MASK = 0x000010000;
    796 
    797     /**
    798      * <p>Indicates that no drawing cache should ever be created for this view.<p>
    799      * {@hide}
    800      */
    801     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
    802 
    803     /**
    804      * <p>Indicates this view can take / keep focus when int touch mode.</p>
    805      * {@hide}
    806      */
    807     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
    808 
    809     /**
    810      * <p>Enables low quality mode for the drawing cache.</p>
    811      */
    812     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
    813 
    814     /**
    815      * <p>Enables high quality mode for the drawing cache.</p>
    816      */
    817     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
    818 
    819     /**
    820      * <p>Enables automatic quality mode for the drawing cache.</p>
    821      */
    822     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
    823 
    824     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
    825             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
    826     };
    827 
    828     /**
    829      * <p>Mask for use with setFlags indicating bits used for the cache
    830      * quality property.</p>
    831      * {@hide}
    832      */
    833     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
    834 
    835     /**
    836      * <p>
    837      * Indicates this view can be long clicked. When long clickable, a View
    838      * reacts to long clicks by notifying the OnLongClickListener or showing a
    839      * context menu.
    840      * </p>
    841      * {@hide}
    842      */
    843     static final int LONG_CLICKABLE = 0x00200000;
    844 
    845     /**
    846      * <p>Indicates that this view gets its drawable states from its direct parent
    847      * and ignores its original internal states.</p>
    848      *
    849      * @hide
    850      */
    851     static final int DUPLICATE_PARENT_STATE = 0x00400000;
    852 
    853     /**
    854      * The scrollbar style to display the scrollbars inside the content area,
    855      * without increasing the padding. The scrollbars will be overlaid with
    856      * translucency on the view's content.
    857      */
    858     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
    859 
    860     /**
    861      * The scrollbar style to display the scrollbars inside the padded area,
    862      * increasing the padding of the view. The scrollbars will not overlap the
    863      * content area of the view.
    864      */
    865     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
    866 
    867     /**
    868      * The scrollbar style to display the scrollbars at the edge of the view,
    869      * without increasing the padding. The scrollbars will be overlaid with
    870      * translucency.
    871      */
    872     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
    873 
    874     /**
    875      * The scrollbar style to display the scrollbars at the edge of the view,
    876      * increasing the padding of the view. The scrollbars will only overlap the
    877      * background, if any.
    878      */
    879     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
    880 
    881     /**
    882      * Mask to check if the scrollbar style is overlay or inset.
    883      * {@hide}
    884      */
    885     static final int SCROLLBARS_INSET_MASK = 0x01000000;
    886 
    887     /**
    888      * Mask to check if the scrollbar style is inside or outside.
    889      * {@hide}
    890      */
    891     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
    892 
    893     /**
    894      * Mask for scrollbar style.
    895      * {@hide}
    896      */
    897     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
    898 
    899     /**
    900      * View flag indicating that the screen should remain on while the
    901      * window containing this view is visible to the user.  This effectively
    902      * takes care of automatically setting the WindowManager's
    903      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
    904      */
    905     public static final int KEEP_SCREEN_ON = 0x04000000;
    906 
    907     /**
    908      * View flag indicating whether this view should have sound effects enabled
    909      * for events such as clicking and touching.
    910      */
    911     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
    912 
    913     /**
    914      * View flag indicating whether this view should have haptic feedback
    915      * enabled for events such as long presses.
    916      */
    917     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
    918 
    919     /**
    920      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
    921      * should add all focusable Views regardless if they are focusable in touch mode.
    922      */
    923     public static final int FOCUSABLES_ALL = 0x00000000;
    924 
    925     /**
    926      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
    927      * should add only Views focusable in touch mode.
    928      */
    929     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
    930 
    931     /**
    932      * Use with {@link #focusSearch}. Move focus to the previous selectable
    933      * item.
    934      */
    935     public static final int FOCUS_BACKWARD = 0x00000001;
    936 
    937     /**
    938      * Use with {@link #focusSearch}. Move focus to the next selectable
    939      * item.
    940      */
    941     public static final int FOCUS_FORWARD = 0x00000002;
    942 
    943     /**
    944      * Use with {@link #focusSearch}. Move focus to the left.
    945      */
    946     public static final int FOCUS_LEFT = 0x00000011;
    947 
    948     /**
    949      * Use with {@link #focusSearch}. Move focus up.
    950      */
    951     public static final int FOCUS_UP = 0x00000021;
    952 
    953     /**
    954      * Use with {@link #focusSearch}. Move focus to the right.
    955      */
    956     public static final int FOCUS_RIGHT = 0x00000042;
    957 
    958     /**
    959      * Use with {@link #focusSearch}. Move focus down.
    960      */
    961     public static final int FOCUS_DOWN = 0x00000082;
    962 
    963     /**
    964      * Base View state sets
    965      */
    966     // Singles
    967     /**
    968      * Indicates the view has no states set. States are used with
    969      * {@link android.graphics.drawable.Drawable} to change the drawing of the
    970      * view depending on its state.
    971      *
    972      * @see android.graphics.drawable.Drawable
    973      * @see #getDrawableState()
    974      */
    975     protected static final int[] EMPTY_STATE_SET = {};
    976     /**
    977      * Indicates the view is enabled. States are used with
    978      * {@link android.graphics.drawable.Drawable} to change the drawing of the
    979      * view depending on its state.
    980      *
    981      * @see android.graphics.drawable.Drawable
    982      * @see #getDrawableState()
    983      */
    984     protected static final int[] ENABLED_STATE_SET = {R.attr.state_enabled};
    985     /**
    986      * Indicates the view is focused. States are used with
    987      * {@link android.graphics.drawable.Drawable} to change the drawing of the
    988      * view depending on its state.
    989      *
    990      * @see android.graphics.drawable.Drawable
    991      * @see #getDrawableState()
    992      */
    993     protected static final int[] FOCUSED_STATE_SET = {R.attr.state_focused};
    994     /**
    995      * Indicates the view is selected. States are used with
    996      * {@link android.graphics.drawable.Drawable} to change the drawing of the
    997      * view depending on its state.
    998      *
    999      * @see android.graphics.drawable.Drawable
   1000      * @see #getDrawableState()
   1001      */
   1002     protected static final int[] SELECTED_STATE_SET = {R.attr.state_selected};
   1003     /**
   1004      * Indicates the view is pressed. States are used with
   1005      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1006      * view depending on its state.
   1007      *
   1008      * @see android.graphics.drawable.Drawable
   1009      * @see #getDrawableState()
   1010      * @hide
   1011      */
   1012     protected static final int[] PRESSED_STATE_SET = {R.attr.state_pressed};
   1013     /**
   1014      * Indicates the view's window has focus. States are used with
   1015      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1016      * view depending on its state.
   1017      *
   1018      * @see android.graphics.drawable.Drawable
   1019      * @see #getDrawableState()
   1020      */
   1021     protected static final int[] WINDOW_FOCUSED_STATE_SET =
   1022             {R.attr.state_window_focused};
   1023     // Doubles
   1024     /**
   1025      * Indicates the view is enabled and has the focus.
   1026      *
   1027      * @see #ENABLED_STATE_SET
   1028      * @see #FOCUSED_STATE_SET
   1029      */
   1030     protected static final int[] ENABLED_FOCUSED_STATE_SET =
   1031             stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET);
   1032     /**
   1033      * Indicates the view is enabled and selected.
   1034      *
   1035      * @see #ENABLED_STATE_SET
   1036      * @see #SELECTED_STATE_SET
   1037      */
   1038     protected static final int[] ENABLED_SELECTED_STATE_SET =
   1039             stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET);
   1040     /**
   1041      * Indicates the view is enabled and that its window has focus.
   1042      *
   1043      * @see #ENABLED_STATE_SET
   1044      * @see #WINDOW_FOCUSED_STATE_SET
   1045      */
   1046     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET =
   1047             stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1048     /**
   1049      * Indicates the view is focused and selected.
   1050      *
   1051      * @see #FOCUSED_STATE_SET
   1052      * @see #SELECTED_STATE_SET
   1053      */
   1054     protected static final int[] FOCUSED_SELECTED_STATE_SET =
   1055             stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET);
   1056     /**
   1057      * Indicates the view has the focus and that its window has the focus.
   1058      *
   1059      * @see #FOCUSED_STATE_SET
   1060      * @see #WINDOW_FOCUSED_STATE_SET
   1061      */
   1062     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET =
   1063             stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1064     /**
   1065      * Indicates the view is selected and that its window has the focus.
   1066      *
   1067      * @see #SELECTED_STATE_SET
   1068      * @see #WINDOW_FOCUSED_STATE_SET
   1069      */
   1070     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET =
   1071             stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1072     // Triples
   1073     /**
   1074      * Indicates the view is enabled, focused and selected.
   1075      *
   1076      * @see #ENABLED_STATE_SET
   1077      * @see #FOCUSED_STATE_SET
   1078      * @see #SELECTED_STATE_SET
   1079      */
   1080     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET =
   1081             stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
   1082     /**
   1083      * Indicates the view is enabled, focused and its window has the focus.
   1084      *
   1085      * @see #ENABLED_STATE_SET
   1086      * @see #FOCUSED_STATE_SET
   1087      * @see #WINDOW_FOCUSED_STATE_SET
   1088      */
   1089     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
   1090             stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1091     /**
   1092      * Indicates the view is enabled, selected and its window has the focus.
   1093      *
   1094      * @see #ENABLED_STATE_SET
   1095      * @see #SELECTED_STATE_SET
   1096      * @see #WINDOW_FOCUSED_STATE_SET
   1097      */
   1098     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET =
   1099             stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1100     /**
   1101      * Indicates the view is focused, selected and its window has the focus.
   1102      *
   1103      * @see #FOCUSED_STATE_SET
   1104      * @see #SELECTED_STATE_SET
   1105      * @see #WINDOW_FOCUSED_STATE_SET
   1106      */
   1107     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
   1108             stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1109     /**
   1110      * Indicates the view is enabled, focused, selected and its window
   1111      * has the focus.
   1112      *
   1113      * @see #ENABLED_STATE_SET
   1114      * @see #FOCUSED_STATE_SET
   1115      * @see #SELECTED_STATE_SET
   1116      * @see #WINDOW_FOCUSED_STATE_SET
   1117      */
   1118     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
   1119             stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET,
   1120                           WINDOW_FOCUSED_STATE_SET);
   1121 
   1122     /**
   1123      * Indicates the view is pressed and its window has the focus.
   1124      *
   1125      * @see #PRESSED_STATE_SET
   1126      * @see #WINDOW_FOCUSED_STATE_SET
   1127      */
   1128     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET =
   1129             stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1130 
   1131     /**
   1132      * Indicates the view is pressed and selected.
   1133      *
   1134      * @see #PRESSED_STATE_SET
   1135      * @see #SELECTED_STATE_SET
   1136      */
   1137     protected static final int[] PRESSED_SELECTED_STATE_SET =
   1138             stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET);
   1139 
   1140     /**
   1141      * Indicates the view is pressed, selected and its window has the focus.
   1142      *
   1143      * @see #PRESSED_STATE_SET
   1144      * @see #SELECTED_STATE_SET
   1145      * @see #WINDOW_FOCUSED_STATE_SET
   1146      */
   1147     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
   1148             stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1149 
   1150     /**
   1151      * Indicates the view is pressed and focused.
   1152      *
   1153      * @see #PRESSED_STATE_SET
   1154      * @see #FOCUSED_STATE_SET
   1155      */
   1156     protected static final int[] PRESSED_FOCUSED_STATE_SET =
   1157             stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET);
   1158 
   1159     /**
   1160      * Indicates the view is pressed, focused and its window has the focus.
   1161      *
   1162      * @see #PRESSED_STATE_SET
   1163      * @see #FOCUSED_STATE_SET
   1164      * @see #WINDOW_FOCUSED_STATE_SET
   1165      */
   1166     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
   1167             stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1168 
   1169     /**
   1170      * Indicates the view is pressed, focused and selected.
   1171      *
   1172      * @see #PRESSED_STATE_SET
   1173      * @see #SELECTED_STATE_SET
   1174      * @see #FOCUSED_STATE_SET
   1175      */
   1176     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET =
   1177             stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
   1178 
   1179     /**
   1180      * Indicates the view is pressed, focused, selected and its window has the focus.
   1181      *
   1182      * @see #PRESSED_STATE_SET
   1183      * @see #FOCUSED_STATE_SET
   1184      * @see #SELECTED_STATE_SET
   1185      * @see #WINDOW_FOCUSED_STATE_SET
   1186      */
   1187     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
   1188             stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1189 
   1190     /**
   1191      * Indicates the view is pressed and enabled.
   1192      *
   1193      * @see #PRESSED_STATE_SET
   1194      * @see #ENABLED_STATE_SET
   1195      */
   1196     protected static final int[] PRESSED_ENABLED_STATE_SET =
   1197             stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET);
   1198 
   1199     /**
   1200      * Indicates the view is pressed, enabled and its window has the focus.
   1201      *
   1202      * @see #PRESSED_STATE_SET
   1203      * @see #ENABLED_STATE_SET
   1204      * @see #WINDOW_FOCUSED_STATE_SET
   1205      */
   1206     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET =
   1207             stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1208 
   1209     /**
   1210      * Indicates the view is pressed, enabled and selected.
   1211      *
   1212      * @see #PRESSED_STATE_SET
   1213      * @see #ENABLED_STATE_SET
   1214      * @see #SELECTED_STATE_SET
   1215      */
   1216     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET =
   1217             stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET);
   1218 
   1219     /**
   1220      * Indicates the view is pressed, enabled, selected and its window has the
   1221      * focus.
   1222      *
   1223      * @see #PRESSED_STATE_SET
   1224      * @see #ENABLED_STATE_SET
   1225      * @see #SELECTED_STATE_SET
   1226      * @see #WINDOW_FOCUSED_STATE_SET
   1227      */
   1228     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET =
   1229             stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1230 
   1231     /**
   1232      * Indicates the view is pressed, enabled and focused.
   1233      *
   1234      * @see #PRESSED_STATE_SET
   1235      * @see #ENABLED_STATE_SET
   1236      * @see #FOCUSED_STATE_SET
   1237      */
   1238     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET =
   1239             stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET);
   1240 
   1241     /**
   1242      * Indicates the view is pressed, enabled, focused and its window has the
   1243      * focus.
   1244      *
   1245      * @see #PRESSED_STATE_SET
   1246      * @see #ENABLED_STATE_SET
   1247      * @see #FOCUSED_STATE_SET
   1248      * @see #WINDOW_FOCUSED_STATE_SET
   1249      */
   1250     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
   1251             stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1252 
   1253     /**
   1254      * Indicates the view is pressed, enabled, focused and selected.
   1255      *
   1256      * @see #PRESSED_STATE_SET
   1257      * @see #ENABLED_STATE_SET
   1258      * @see #SELECTED_STATE_SET
   1259      * @see #FOCUSED_STATE_SET
   1260      */
   1261     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET =
   1262             stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
   1263 
   1264     /**
   1265      * Indicates the view is pressed, enabled, focused, selected and its window
   1266      * has the focus.
   1267      *
   1268      * @see #PRESSED_STATE_SET
   1269      * @see #ENABLED_STATE_SET
   1270      * @see #SELECTED_STATE_SET
   1271      * @see #FOCUSED_STATE_SET
   1272      * @see #WINDOW_FOCUSED_STATE_SET
   1273      */
   1274     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
   1275             stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
   1276 
   1277     /**
   1278      * The order here is very important to {@link #getDrawableState()}
   1279      */
   1280     private static final int[][] VIEW_STATE_SETS = {
   1281         EMPTY_STATE_SET,                                           // 0 0 0 0 0
   1282         WINDOW_FOCUSED_STATE_SET,                                  // 0 0 0 0 1
   1283         SELECTED_STATE_SET,                                        // 0 0 0 1 0
   1284         SELECTED_WINDOW_FOCUSED_STATE_SET,                         // 0 0 0 1 1
   1285         FOCUSED_STATE_SET,                                         // 0 0 1 0 0
   1286         FOCUSED_WINDOW_FOCUSED_STATE_SET,                          // 0 0 1 0 1
   1287         FOCUSED_SELECTED_STATE_SET,                                // 0 0 1 1 0
   1288         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 0 0 1 1 1
   1289         ENABLED_STATE_SET,                                         // 0 1 0 0 0
   1290         ENABLED_WINDOW_FOCUSED_STATE_SET,                          // 0 1 0 0 1
   1291         ENABLED_SELECTED_STATE_SET,                                // 0 1 0 1 0
   1292         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 0 1 0 1 1
   1293         ENABLED_FOCUSED_STATE_SET,                                 // 0 1 1 0 0
   1294         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,                  // 0 1 1 0 1
   1295         ENABLED_FOCUSED_SELECTED_STATE_SET,                        // 0 1 1 1 0
   1296         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 0 1 1 1 1
   1297         PRESSED_STATE_SET,                                         // 1 0 0 0 0
   1298         PRESSED_WINDOW_FOCUSED_STATE_SET,                          // 1 0 0 0 1
   1299         PRESSED_SELECTED_STATE_SET,                                // 1 0 0 1 0
   1300         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 1 0 0 1 1
   1301         PRESSED_FOCUSED_STATE_SET,                                 // 1 0 1 0 0
   1302         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET,                  // 1 0 1 0 1
   1303         PRESSED_FOCUSED_SELECTED_STATE_SET,                        // 1 0 1 1 0
   1304         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 1 0 1 1 1
   1305         PRESSED_ENABLED_STATE_SET,                                 // 1 1 0 0 0
   1306         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET,                  // 1 1 0 0 1
   1307         PRESSED_ENABLED_SELECTED_STATE_SET,                        // 1 1 0 1 0
   1308         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 1 1 0 1 1
   1309         PRESSED_ENABLED_FOCUSED_STATE_SET,                         // 1 1 1 0 0
   1310         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,          // 1 1 1 0 1
   1311         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET,                // 1 1 1 1 0
   1312         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 1 1
   1313     };
   1314 
   1315     /**
   1316      * Used by views that contain lists of items. This state indicates that
   1317      * the view is showing the last item.
   1318      * @hide
   1319      */
   1320     protected static final int[] LAST_STATE_SET = {R.attr.state_last};
   1321     /**
   1322      * Used by views that contain lists of items. This state indicates that
   1323      * the view is showing the first item.
   1324      * @hide
   1325      */
   1326     protected static final int[] FIRST_STATE_SET = {R.attr.state_first};
   1327     /**
   1328      * Used by views that contain lists of items. This state indicates that
   1329      * the view is showing the middle item.
   1330      * @hide
   1331      */
   1332     protected static final int[] MIDDLE_STATE_SET = {R.attr.state_middle};
   1333     /**
   1334      * Used by views that contain lists of items. This state indicates that
   1335      * the view is showing only one item.
   1336      * @hide
   1337      */
   1338     protected static final int[] SINGLE_STATE_SET = {R.attr.state_single};
   1339     /**
   1340      * Used by views that contain lists of items. This state indicates that
   1341      * the view is pressed and showing the last item.
   1342      * @hide
   1343      */
   1344     protected static final int[] PRESSED_LAST_STATE_SET = {R.attr.state_last, R.attr.state_pressed};
   1345     /**
   1346      * Used by views that contain lists of items. This state indicates that
   1347      * the view is pressed and showing the first item.
   1348      * @hide
   1349      */
   1350     protected static final int[] PRESSED_FIRST_STATE_SET = {R.attr.state_first, R.attr.state_pressed};
   1351     /**
   1352      * Used by views that contain lists of items. This state indicates that
   1353      * the view is pressed and showing the middle item.
   1354      * @hide
   1355      */
   1356     protected static final int[] PRESSED_MIDDLE_STATE_SET = {R.attr.state_middle, R.attr.state_pressed};
   1357     /**
   1358      * Used by views that contain lists of items. This state indicates that
   1359      * the view is pressed and showing only one item.
   1360      * @hide
   1361      */
   1362     protected static final int[] PRESSED_SINGLE_STATE_SET = {R.attr.state_single, R.attr.state_pressed};
   1363 
   1364     /**
   1365      * Temporary Rect currently for use in setBackground().  This will probably
   1366      * be extended in the future to hold our own class with more than just
   1367      * a Rect. :)
   1368      */
   1369     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
   1370 
   1371     /**
   1372      * Map used to store views' tags.
   1373      */
   1374     private static WeakHashMap<View, SparseArray<Object>> sTags;
   1375 
   1376     /**
   1377      * Lock used to access sTags.
   1378      */
   1379     private static final Object sTagsLock = new Object();
   1380 
   1381     /**
   1382      * The animation currently associated with this view.
   1383      * @hide
   1384      */
   1385     protected Animation mCurrentAnimation = null;
   1386 
   1387     /**
   1388      * Width as measured during measure pass.
   1389      * {@hide}
   1390      */
   1391     @ViewDebug.ExportedProperty(category = "measurement")
   1392     protected int mMeasuredWidth;
   1393 
   1394     /**
   1395      * Height as measured during measure pass.
   1396      * {@hide}
   1397      */
   1398     @ViewDebug.ExportedProperty(category = "measurement")
   1399     protected int mMeasuredHeight;
   1400 
   1401     /**
   1402      * The view's identifier.
   1403      * {@hide}
   1404      *
   1405      * @see #setId(int)
   1406      * @see #getId()
   1407      */
   1408     @ViewDebug.ExportedProperty(resolveId = true)
   1409     int mID = NO_ID;
   1410 
   1411     /**
   1412      * The view's tag.
   1413      * {@hide}
   1414      *
   1415      * @see #setTag(Object)
   1416      * @see #getTag()
   1417      */
   1418     protected Object mTag;
   1419 
   1420     // for mPrivateFlags:
   1421     /** {@hide} */
   1422     static final int WANTS_FOCUS                    = 0x00000001;
   1423     /** {@hide} */
   1424     static final int FOCUSED                        = 0x00000002;
   1425     /** {@hide} */
   1426     static final int SELECTED                       = 0x00000004;
   1427     /** {@hide} */
   1428     static final int IS_ROOT_NAMESPACE              = 0x00000008;
   1429     /** {@hide} */
   1430     static final int HAS_BOUNDS                     = 0x00000010;
   1431     /** {@hide} */
   1432     static final int DRAWN                          = 0x00000020;
   1433     /**
   1434      * When this flag is set, this view is running an animation on behalf of its
   1435      * children and should therefore not cancel invalidate requests, even if they
   1436      * lie outside of this view's bounds.
   1437      *
   1438      * {@hide}
   1439      */
   1440     static final int DRAW_ANIMATION                 = 0x00000040;
   1441     /** {@hide} */
   1442     static final int SKIP_DRAW                      = 0x00000080;
   1443     /** {@hide} */
   1444     static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
   1445     /** {@hide} */
   1446     static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
   1447     /** {@hide} */
   1448     static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
   1449     /** {@hide} */
   1450     static final int MEASURED_DIMENSION_SET         = 0x00000800;
   1451     /** {@hide} */
   1452     static final int FORCE_LAYOUT                   = 0x00001000;
   1453     /** {@hide} */
   1454     static final int LAYOUT_REQUIRED                = 0x00002000;
   1455 
   1456     private static final int PRESSED                = 0x00004000;
   1457 
   1458     /** {@hide} */
   1459     static final int DRAWING_CACHE_VALID            = 0x00008000;
   1460     /**
   1461      * Flag used to indicate that this view should be drawn once more (and only once
   1462      * more) after its animation has completed.
   1463      * {@hide}
   1464      */
   1465     static final int ANIMATION_STARTED              = 0x00010000;
   1466 
   1467     private static final int SAVE_STATE_CALLED      = 0x00020000;
   1468 
   1469     /**
   1470      * Indicates that the View returned true when onSetAlpha() was called and that
   1471      * the alpha must be restored.
   1472      * {@hide}
   1473      */
   1474     static final int ALPHA_SET                      = 0x00040000;
   1475 
   1476     /**
   1477      * Set by {@link #setScrollContainer(boolean)}.
   1478      */
   1479     static final int SCROLL_CONTAINER               = 0x00080000;
   1480 
   1481     /**
   1482      * Set by {@link #setScrollContainer(boolean)}.
   1483      */
   1484     static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
   1485 
   1486     /**
   1487      * View flag indicating whether this view was invalidated (fully or partially.)
   1488      *
   1489      * @hide
   1490      */
   1491     static final int DIRTY                          = 0x00200000;
   1492 
   1493     /**
   1494      * View flag indicating whether this view was invalidated by an opaque
   1495      * invalidate request.
   1496      *
   1497      * @hide
   1498      */
   1499     static final int DIRTY_OPAQUE                   = 0x00400000;
   1500 
   1501     /**
   1502      * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
   1503      *
   1504      * @hide
   1505      */
   1506     static final int DIRTY_MASK                     = 0x00600000;
   1507 
   1508     /**
   1509      * Indicates whether the background is opaque.
   1510      *
   1511      * @hide
   1512      */
   1513     static final int OPAQUE_BACKGROUND              = 0x00800000;
   1514 
   1515     /**
   1516      * Indicates whether the scrollbars are opaque.
   1517      *
   1518      * @hide
   1519      */
   1520     static final int OPAQUE_SCROLLBARS              = 0x01000000;
   1521 
   1522     /**
   1523      * Indicates whether the view is opaque.
   1524      *
   1525      * @hide
   1526      */
   1527     static final int OPAQUE_MASK                    = 0x01800000;
   1528 
   1529     /**
   1530      * Indicates a prepressed state;
   1531      * the short time between ACTION_DOWN and recognizing
   1532      * a 'real' press. Prepressed is used to recognize quick taps
   1533      * even when they are shorter than ViewConfiguration.getTapTimeout().
   1534      *
   1535      * @hide
   1536      */
   1537     private static final int PREPRESSED             = 0x02000000;
   1538 
   1539     /**
   1540      * Indicates whether the view is temporarily detached.
   1541      *
   1542      * @hide
   1543      */
   1544     static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
   1545 
   1546     /**
   1547      * Indicates that we should awaken scroll bars once attached
   1548      *
   1549      * @hide
   1550      */
   1551     private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
   1552 
   1553     /**
   1554      * Always allow a user to over-scroll this view, provided it is a
   1555      * view that can scroll.
   1556      *
   1557      * @see #getOverScrollMode()
   1558      * @see #setOverScrollMode(int)
   1559      */
   1560     public static final int OVER_SCROLL_ALWAYS = 0;
   1561 
   1562     /**
   1563      * Allow a user to over-scroll this view only if the content is large
   1564      * enough to meaningfully scroll, provided it is a view that can scroll.
   1565      *
   1566      * @see #getOverScrollMode()
   1567      * @see #setOverScrollMode(int)
   1568      */
   1569     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
   1570 
   1571     /**
   1572      * Never allow a user to over-scroll this view.
   1573      *
   1574      * @see #getOverScrollMode()
   1575      * @see #setOverScrollMode(int)
   1576      */
   1577     public static final int OVER_SCROLL_NEVER = 2;
   1578 
   1579     /**
   1580      * Controls the over-scroll mode for this view.
   1581      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
   1582      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
   1583      * and {@link #OVER_SCROLL_NEVER}.
   1584      */
   1585     private int mOverScrollMode;
   1586 
   1587     /**
   1588      * The parent this view is attached to.
   1589      * {@hide}
   1590      *
   1591      * @see #getParent()
   1592      */
   1593     protected ViewParent mParent;
   1594 
   1595     /**
   1596      * {@hide}
   1597      */
   1598     AttachInfo mAttachInfo;
   1599 
   1600     /**
   1601      * {@hide}
   1602      */
   1603     @ViewDebug.ExportedProperty(flagMapping = {
   1604         @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
   1605                 name = "FORCE_LAYOUT"),
   1606         @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
   1607                 name = "LAYOUT_REQUIRED"),
   1608         @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
   1609             name = "DRAWING_CACHE_INVALID", outputIf = false),
   1610         @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
   1611         @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
   1612         @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
   1613         @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
   1614     })
   1615     int mPrivateFlags;
   1616 
   1617     /**
   1618      * Count of how many windows this view has been attached to.
   1619      */
   1620     int mWindowAttachCount;
   1621 
   1622     /**
   1623      * The layout parameters associated with this view and used by the parent
   1624      * {@link android.view.ViewGroup} to determine how this view should be
   1625      * laid out.
   1626      * {@hide}
   1627      */
   1628     protected ViewGroup.LayoutParams mLayoutParams;
   1629 
   1630     /**
   1631      * The view flags hold various views states.
   1632      * {@hide}
   1633      */
   1634     @ViewDebug.ExportedProperty
   1635     int mViewFlags;
   1636 
   1637     /**
   1638      * The distance in pixels from the left edge of this view's parent
   1639      * to the left edge of this view.
   1640      * {@hide}
   1641      */
   1642     @ViewDebug.ExportedProperty(category = "layout")
   1643     protected int mLeft;
   1644     /**
   1645      * The distance in pixels from the left edge of this view's parent
   1646      * to the right edge of this view.
   1647      * {@hide}
   1648      */
   1649     @ViewDebug.ExportedProperty(category = "layout")
   1650     protected int mRight;
   1651     /**
   1652      * The distance in pixels from the top edge of this view's parent
   1653      * to the top edge of this view.
   1654      * {@hide}
   1655      */
   1656     @ViewDebug.ExportedProperty(category = "layout")
   1657     protected int mTop;
   1658     /**
   1659      * The distance in pixels from the top edge of this view's parent
   1660      * to the bottom edge of this view.
   1661      * {@hide}
   1662      */
   1663     @ViewDebug.ExportedProperty(category = "layout")
   1664     protected int mBottom;
   1665 
   1666     /**
   1667      * The offset, in pixels, by which the content of this view is scrolled
   1668      * horizontally.
   1669      * {@hide}
   1670      */
   1671     @ViewDebug.ExportedProperty(category = "scrolling")
   1672     protected int mScrollX;
   1673     /**
   1674      * The offset, in pixels, by which the content of this view is scrolled
   1675      * vertically.
   1676      * {@hide}
   1677      */
   1678     @ViewDebug.ExportedProperty(category = "scrolling")
   1679     protected int mScrollY;
   1680 
   1681     /**
   1682      * The left padding in pixels, that is the distance in pixels between the
   1683      * left edge of this view and the left edge of its content.
   1684      * {@hide}
   1685      */
   1686     @ViewDebug.ExportedProperty(category = "padding")
   1687     protected int mPaddingLeft;
   1688     /**
   1689      * The right padding in pixels, that is the distance in pixels between the
   1690      * right edge of this view and the right edge of its content.
   1691      * {@hide}
   1692      */
   1693     @ViewDebug.ExportedProperty(category = "padding")
   1694     protected int mPaddingRight;
   1695     /**
   1696      * The top padding in pixels, that is the distance in pixels between the
   1697      * top edge of this view and the top edge of its content.
   1698      * {@hide}
   1699      */
   1700     @ViewDebug.ExportedProperty(category = "padding")
   1701     protected int mPaddingTop;
   1702     /**
   1703      * The bottom padding in pixels, that is the distance in pixels between the
   1704      * bottom edge of this view and the bottom edge of its content.
   1705      * {@hide}
   1706      */
   1707     @ViewDebug.ExportedProperty(category = "padding")
   1708     protected int mPaddingBottom;
   1709 
   1710     /**
   1711      * Briefly describes the view and is primarily used for accessibility support.
   1712      */
   1713     private CharSequence mContentDescription;
   1714 
   1715     /**
   1716      * Cache the paddingRight set by the user to append to the scrollbar's size.
   1717      */
   1718     @ViewDebug.ExportedProperty(category = "padding")
   1719     int mUserPaddingRight;
   1720 
   1721     /**
   1722      * Cache the paddingBottom set by the user to append to the scrollbar's size.
   1723      */
   1724     @ViewDebug.ExportedProperty(category = "padding")
   1725     int mUserPaddingBottom;
   1726 
   1727     /**
   1728      * @hide
   1729      */
   1730     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
   1731     /**
   1732      * @hide
   1733      */
   1734     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
   1735 
   1736     private Resources mResources = null;
   1737 
   1738     private Drawable mBGDrawable;
   1739 
   1740     private int mBackgroundResource;
   1741     private boolean mBackgroundSizeChanged;
   1742 
   1743     /**
   1744      * Listener used to dispatch focus change events.
   1745      * This field should be made private, so it is hidden from the SDK.
   1746      * {@hide}
   1747      */
   1748     protected OnFocusChangeListener mOnFocusChangeListener;
   1749 
   1750     /**
   1751      * Listener used to dispatch click events.
   1752      * This field should be made private, so it is hidden from the SDK.
   1753      * {@hide}
   1754      */
   1755     protected OnClickListener mOnClickListener;
   1756 
   1757     /**
   1758      * Listener used to dispatch long click events.
   1759      * This field should be made private, so it is hidden from the SDK.
   1760      * {@hide}
   1761      */
   1762     protected OnLongClickListener mOnLongClickListener;
   1763 
   1764     /**
   1765      * Listener used to build the context menu.
   1766      * This field should be made private, so it is hidden from the SDK.
   1767      * {@hide}
   1768      */
   1769     protected OnCreateContextMenuListener mOnCreateContextMenuListener;
   1770 
   1771     private OnKeyListener mOnKeyListener;
   1772 
   1773     private OnTouchListener mOnTouchListener;
   1774 
   1775     /**
   1776      * The application environment this view lives in.
   1777      * This field should be made private, so it is hidden from the SDK.
   1778      * {@hide}
   1779      */
   1780     protected Context mContext;
   1781 
   1782     private ScrollabilityCache mScrollCache;
   1783 
   1784     private int[] mDrawableState = null;
   1785 
   1786     private SoftReference<Bitmap> mDrawingCache;
   1787     private SoftReference<Bitmap> mUnscaledDrawingCache;
   1788 
   1789     /**
   1790      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
   1791      * the user may specify which view to go to next.
   1792      */
   1793     private int mNextFocusLeftId = View.NO_ID;
   1794 
   1795     /**
   1796      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
   1797      * the user may specify which view to go to next.
   1798      */
   1799     private int mNextFocusRightId = View.NO_ID;
   1800 
   1801     /**
   1802      * When this view has focus and the next focus is {@link #FOCUS_UP},
   1803      * the user may specify which view to go to next.
   1804      */
   1805     private int mNextFocusUpId = View.NO_ID;
   1806 
   1807     /**
   1808      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
   1809      * the user may specify which view to go to next.
   1810      */
   1811     private int mNextFocusDownId = View.NO_ID;
   1812 
   1813     private CheckForLongPress mPendingCheckForLongPress;
   1814     private CheckForTap mPendingCheckForTap = null;
   1815     private PerformClick mPerformClick;
   1816 
   1817     private UnsetPressedState mUnsetPressedState;
   1818 
   1819     /**
   1820      * Whether the long press's action has been invoked.  The tap's action is invoked on the
   1821      * up event while a long press is invoked as soon as the long press duration is reached, so
   1822      * a long press could be performed before the tap is checked, in which case the tap's action
   1823      * should not be invoked.
   1824      */
   1825     private boolean mHasPerformedLongPress;
   1826 
   1827     /**
   1828      * The minimum height of the view. We'll try our best to have the height
   1829      * of this view to at least this amount.
   1830      */
   1831     @ViewDebug.ExportedProperty(category = "measurement")
   1832     private int mMinHeight;
   1833 
   1834     /**
   1835      * The minimum width of the view. We'll try our best to have the width
   1836      * of this view to at least this amount.
   1837      */
   1838     @ViewDebug.ExportedProperty(category = "measurement")
   1839     private int mMinWidth;
   1840 
   1841     /**
   1842      * The delegate to handle touch events that are physically in this view
   1843      * but should be handled by another view.
   1844      */
   1845     private TouchDelegate mTouchDelegate = null;
   1846 
   1847     /**
   1848      * Solid color to use as a background when creating the drawing cache. Enables
   1849      * the cache to use 16 bit bitmaps instead of 32 bit.
   1850      */
   1851     private int mDrawingCacheBackgroundColor = 0;
   1852 
   1853     /**
   1854      * Special tree observer used when mAttachInfo is null.
   1855      */
   1856     private ViewTreeObserver mFloatingTreeObserver;
   1857 
   1858     /**
   1859      * Cache the touch slop from the context that created the view.
   1860      */
   1861     private int mTouchSlop;
   1862 
   1863     // Used for debug only
   1864     static long sInstanceCount = 0;
   1865 
   1866     /**
   1867      * Simple constructor to use when creating a view from code.
   1868      *
   1869      * @param context The Context the view is running in, through which it can
   1870      *        access the current theme, resources, etc.
   1871      */
   1872     public View(Context context) {
   1873         mContext = context;
   1874         mResources = context != null ? context.getResources() : null;
   1875         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
   1876         // Used for debug only
   1877         //++sInstanceCount;
   1878         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
   1879         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
   1880     }
   1881 
   1882     /**
   1883      * Constructor that is called when inflating a view from XML. This is called
   1884      * when a view is being constructed from an XML file, supplying attributes
   1885      * that were specified in the XML file. This version uses a default style of
   1886      * 0, so the only attribute values applied are those in the Context's Theme
   1887      * and the given AttributeSet.
   1888      *
   1889      * <p>
   1890      * The method onFinishInflate() will be called after all children have been
   1891      * added.
   1892      *
   1893      * @param context The Context the view is running in, through which it can
   1894      *        access the current theme, resources, etc.
   1895      * @param attrs The attributes of the XML tag that is inflating the view.
   1896      * @see #View(Context, AttributeSet, int)
   1897      */
   1898     public View(Context context, AttributeSet attrs) {
   1899         this(context, attrs, 0);
   1900     }
   1901 
   1902     /**
   1903      * Perform inflation from XML and apply a class-specific base style. This
   1904      * constructor of View allows subclasses to use their own base style when
   1905      * they are inflating. For example, a Button class's constructor would call
   1906      * this version of the super class constructor and supply
   1907      * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
   1908      * the theme's button style to modify all of the base view attributes (in
   1909      * particular its background) as well as the Button class's attributes.
   1910      *
   1911      * @param context The Context the view is running in, through which it can
   1912      *        access the current theme, resources, etc.
   1913      * @param attrs The attributes of the XML tag that is inflating the view.
   1914      * @param defStyle The default style to apply to this view. If 0, no style
   1915      *        will be applied (beyond what is included in the theme). This may
   1916      *        either be an attribute resource, whose value will be retrieved
   1917      *        from the current theme, or an explicit style resource.
   1918      * @see #View(Context, AttributeSet)
   1919      */
   1920     public View(Context context, AttributeSet attrs, int defStyle) {
   1921         this(context);
   1922 
   1923         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
   1924                 defStyle, 0);
   1925 
   1926         Drawable background = null;
   1927 
   1928         int leftPadding = -1;
   1929         int topPadding = -1;
   1930         int rightPadding = -1;
   1931         int bottomPadding = -1;
   1932 
   1933         int padding = -1;
   1934 
   1935         int viewFlagValues = 0;
   1936         int viewFlagMasks = 0;
   1937 
   1938         boolean setScrollContainer = false;
   1939 
   1940         int x = 0;
   1941         int y = 0;
   1942 
   1943         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
   1944 
   1945         int overScrollMode = mOverScrollMode;
   1946         final int N = a.getIndexCount();
   1947         for (int i = 0; i < N; i++) {
   1948             int attr = a.getIndex(i);
   1949             switch (attr) {
   1950                 case com.android.internal.R.styleable.View_background:
   1951                     background = a.getDrawable(attr);
   1952                     break;
   1953                 case com.android.internal.R.styleable.View_padding:
   1954                     padding = a.getDimensionPixelSize(attr, -1);
   1955                     break;
   1956                  case com.android.internal.R.styleable.View_paddingLeft:
   1957                     leftPadding = a.getDimensionPixelSize(attr, -1);
   1958                     break;
   1959                 case com.android.internal.R.styleable.View_paddingTop:
   1960                     topPadding = a.getDimensionPixelSize(attr, -1);
   1961                     break;
   1962                 case com.android.internal.R.styleable.View_paddingRight:
   1963                     rightPadding = a.getDimensionPixelSize(attr, -1);
   1964                     break;
   1965                 case com.android.internal.R.styleable.View_paddingBottom:
   1966                     bottomPadding = a.getDimensionPixelSize(attr, -1);
   1967                     break;
   1968                 case com.android.internal.R.styleable.View_scrollX:
   1969                     x = a.getDimensionPixelOffset(attr, 0);
   1970                     break;
   1971                 case com.android.internal.R.styleable.View_scrollY:
   1972                     y = a.getDimensionPixelOffset(attr, 0);
   1973                     break;
   1974                 case com.android.internal.R.styleable.View_id:
   1975                     mID = a.getResourceId(attr, NO_ID);
   1976                     break;
   1977                 case com.android.internal.R.styleable.View_tag:
   1978                     mTag = a.getText(attr);
   1979                     break;
   1980                 case com.android.internal.R.styleable.View_fitsSystemWindows:
   1981                     if (a.getBoolean(attr, false)) {
   1982                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
   1983                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
   1984                     }
   1985                     break;
   1986                 case com.android.internal.R.styleable.View_focusable:
   1987                     if (a.getBoolean(attr, false)) {
   1988                         viewFlagValues |= FOCUSABLE;
   1989                         viewFlagMasks |= FOCUSABLE_MASK;
   1990                     }
   1991                     break;
   1992                 case com.android.internal.R.styleable.View_focusableInTouchMode:
   1993                     if (a.getBoolean(attr, false)) {
   1994                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
   1995                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
   1996                     }
   1997                     break;
   1998                 case com.android.internal.R.styleable.View_clickable:
   1999                     if (a.getBoolean(attr, false)) {
   2000                         viewFlagValues |= CLICKABLE;
   2001                         viewFlagMasks |= CLICKABLE;
   2002                     }
   2003                     break;
   2004                 case com.android.internal.R.styleable.View_longClickable:
   2005                     if (a.getBoolean(attr, false)) {
   2006                         viewFlagValues |= LONG_CLICKABLE;
   2007                         viewFlagMasks |= LONG_CLICKABLE;
   2008                     }
   2009                     break;
   2010                 case com.android.internal.R.styleable.View_saveEnabled:
   2011                     if (!a.getBoolean(attr, true)) {
   2012                         viewFlagValues |= SAVE_DISABLED;
   2013                         viewFlagMasks |= SAVE_DISABLED_MASK;
   2014                     }
   2015                     break;
   2016                 case com.android.internal.R.styleable.View_duplicateParentState:
   2017                     if (a.getBoolean(attr, false)) {
   2018                         viewFlagValues |= DUPLICATE_PARENT_STATE;
   2019                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
   2020                     }
   2021                     break;
   2022                 case com.android.internal.R.styleable.View_visibility:
   2023                     final int visibility = a.getInt(attr, 0);
   2024                     if (visibility != 0) {
   2025                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
   2026                         viewFlagMasks |= VISIBILITY_MASK;
   2027                     }
   2028                     break;
   2029                 case com.android.internal.R.styleable.View_drawingCacheQuality:
   2030                     final int cacheQuality = a.getInt(attr, 0);
   2031                     if (cacheQuality != 0) {
   2032                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
   2033                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
   2034                     }
   2035                     break;
   2036                 case com.android.internal.R.styleable.View_contentDescription:
   2037                     mContentDescription = a.getString(attr);
   2038                     break;
   2039                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
   2040                     if (!a.getBoolean(attr, true)) {
   2041                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
   2042                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
   2043                     }
   2044                     break;
   2045                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
   2046                     if (!a.getBoolean(attr, true)) {
   2047                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
   2048                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
   2049                     }
   2050                     break;
   2051                 case R.styleable.View_scrollbars:
   2052                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
   2053                     if (scrollbars != SCROLLBARS_NONE) {
   2054                         viewFlagValues |= scrollbars;
   2055                         viewFlagMasks |= SCROLLBARS_MASK;
   2056                         initializeScrollbars(a);
   2057                     }
   2058                     break;
   2059                 case R.styleable.View_fadingEdge:
   2060                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
   2061                     if (fadingEdge != FADING_EDGE_NONE) {
   2062                         viewFlagValues |= fadingEdge;
   2063                         viewFlagMasks |= FADING_EDGE_MASK;
   2064                         initializeFadingEdge(a);
   2065                     }
   2066                     break;
   2067                 case R.styleable.View_scrollbarStyle:
   2068                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
   2069                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   2070                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
   2071                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
   2072                     }
   2073                     break;
   2074                 case R.styleable.View_isScrollContainer:
   2075                     setScrollContainer = true;
   2076                     if (a.getBoolean(attr, false)) {
   2077                         setScrollContainer(true);
   2078                     }
   2079                     break;
   2080                 case com.android.internal.R.styleable.View_keepScreenOn:
   2081                     if (a.getBoolean(attr, false)) {
   2082                         viewFlagValues |= KEEP_SCREEN_ON;
   2083                         viewFlagMasks |= KEEP_SCREEN_ON;
   2084                     }
   2085                     break;
   2086                 case R.styleable.View_filterTouchesWhenObscured:
   2087                     if (a.getBoolean(attr, false)) {
   2088                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
   2089                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
   2090                     }
   2091                     break;
   2092                 case R.styleable.View_nextFocusLeft:
   2093                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
   2094                     break;
   2095                 case R.styleable.View_nextFocusRight:
   2096                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
   2097                     break;
   2098                 case R.styleable.View_nextFocusUp:
   2099                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
   2100                     break;
   2101                 case R.styleable.View_nextFocusDown:
   2102                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
   2103                     break;
   2104                 case R.styleable.View_minWidth:
   2105                     mMinWidth = a.getDimensionPixelSize(attr, 0);
   2106                     break;
   2107                 case R.styleable.View_minHeight:
   2108                     mMinHeight = a.getDimensionPixelSize(attr, 0);
   2109                     break;
   2110                 case R.styleable.View_onClick:
   2111                     if (context.isRestricted()) {
   2112                         throw new IllegalStateException("The android:onClick attribute cannot "
   2113                                 + "be used within a restricted context");
   2114                     }
   2115 
   2116                     final String handlerName = a.getString(attr);
   2117                     if (handlerName != null) {
   2118                         setOnClickListener(new OnClickListener() {
   2119                             private Method mHandler;
   2120 
   2121                             public void onClick(View v) {
   2122                                 if (mHandler == null) {
   2123                                     try {
   2124                                         mHandler = getContext().getClass().getMethod(handlerName,
   2125                                                 View.class);
   2126                                     } catch (NoSuchMethodException e) {
   2127                                         int id = getId();
   2128                                         String idText = id == NO_ID ? "" : " with id '"
   2129                                                 + getContext().getResources().getResourceEntryName(
   2130                                                     id) + "'";
   2131                                         throw new IllegalStateException("Could not find a method " +
   2132                                                 handlerName + "(View) in the activity "
   2133                                                 + getContext().getClass() + " for onClick handler"
   2134                                                 + " on view " + View.this.getClass() + idText, e);
   2135                                     }
   2136                                 }
   2137 
   2138                                 try {
   2139                                     mHandler.invoke(getContext(), View.this);
   2140                                 } catch (IllegalAccessException e) {
   2141                                     throw new IllegalStateException("Could not execute non "
   2142                                             + "public method of the activity", e);
   2143                                 } catch (InvocationTargetException e) {
   2144                                     throw new IllegalStateException("Could not execute "
   2145                                             + "method of the activity", e);
   2146                                 }
   2147                             }
   2148                         });
   2149                     }
   2150                     break;
   2151                 case R.styleable.View_overScrollMode:
   2152                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
   2153                     break;
   2154             }
   2155         }
   2156 
   2157         setOverScrollMode(overScrollMode);
   2158 
   2159         if (background != null) {
   2160             setBackgroundDrawable(background);
   2161         }
   2162 
   2163         if (padding >= 0) {
   2164             leftPadding = padding;
   2165             topPadding = padding;
   2166             rightPadding = padding;
   2167             bottomPadding = padding;
   2168         }
   2169 
   2170         // If the user specified the padding (either with android:padding or
   2171         // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
   2172         // use the default padding or the padding from the background drawable
   2173         // (stored at this point in mPadding*)
   2174         setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
   2175                 topPadding >= 0 ? topPadding : mPaddingTop,
   2176                 rightPadding >= 0 ? rightPadding : mPaddingRight,
   2177                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
   2178 
   2179         if (viewFlagMasks != 0) {
   2180             setFlags(viewFlagValues, viewFlagMasks);
   2181         }
   2182 
   2183         // Needs to be called after mViewFlags is set
   2184         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   2185             recomputePadding();
   2186         }
   2187 
   2188         if (x != 0 || y != 0) {
   2189             scrollTo(x, y);
   2190         }
   2191 
   2192         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
   2193             setScrollContainer(true);
   2194         }
   2195 
   2196         computeOpaqueFlags();
   2197 
   2198         a.recycle();
   2199     }
   2200 
   2201     /**
   2202      * Non-public constructor for use in testing
   2203      */
   2204     View() {
   2205     }
   2206 
   2207     // Used for debug only
   2208     /*
   2209     @Override
   2210     protected void finalize() throws Throwable {
   2211         super.finalize();
   2212         --sInstanceCount;
   2213     }
   2214     */
   2215 
   2216     /**
   2217      * <p>
   2218      * Initializes the fading edges from a given set of styled attributes. This
   2219      * method should be called by subclasses that need fading edges and when an
   2220      * instance of these subclasses is created programmatically rather than
   2221      * being inflated from XML. This method is automatically called when the XML
   2222      * is inflated.
   2223      * </p>
   2224      *
   2225      * @param a the styled attributes set to initialize the fading edges from
   2226      */
   2227     protected void initializeFadingEdge(TypedArray a) {
   2228         initScrollCache();
   2229 
   2230         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
   2231                 R.styleable.View_fadingEdgeLength,
   2232                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
   2233     }
   2234 
   2235     /**
   2236      * Returns the size of the vertical faded edges used to indicate that more
   2237      * content in this view is visible.
   2238      *
   2239      * @return The size in pixels of the vertical faded edge or 0 if vertical
   2240      *         faded edges are not enabled for this view.
   2241      * @attr ref android.R.styleable#View_fadingEdgeLength
   2242      */
   2243     public int getVerticalFadingEdgeLength() {
   2244         if (isVerticalFadingEdgeEnabled()) {
   2245             ScrollabilityCache cache = mScrollCache;
   2246             if (cache != null) {
   2247                 return cache.fadingEdgeLength;
   2248             }
   2249         }
   2250         return 0;
   2251     }
   2252 
   2253     /**
   2254      * Set the size of the faded edge used to indicate that more content in this
   2255      * view is available.  Will not change whether the fading edge is enabled; use
   2256      * {@link #setVerticalFadingEdgeEnabled} or {@link #setHorizontalFadingEdgeEnabled}
   2257      * to enable the fading edge for the vertical or horizontal fading edges.
   2258      *
   2259      * @param length The size in pixels of the faded edge used to indicate that more
   2260      *        content in this view is visible.
   2261      */
   2262     public void setFadingEdgeLength(int length) {
   2263         initScrollCache();
   2264         mScrollCache.fadingEdgeLength = length;
   2265     }
   2266 
   2267     /**
   2268      * Returns the size of the horizontal faded edges used to indicate that more
   2269      * content in this view is visible.
   2270      *
   2271      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
   2272      *         faded edges are not enabled for this view.
   2273      * @attr ref android.R.styleable#View_fadingEdgeLength
   2274      */
   2275     public int getHorizontalFadingEdgeLength() {
   2276         if (isHorizontalFadingEdgeEnabled()) {
   2277             ScrollabilityCache cache = mScrollCache;
   2278             if (cache != null) {
   2279                 return cache.fadingEdgeLength;
   2280             }
   2281         }
   2282         return 0;
   2283     }
   2284 
   2285     /**
   2286      * Returns the width of the vertical scrollbar.
   2287      *
   2288      * @return The width in pixels of the vertical scrollbar or 0 if there
   2289      *         is no vertical scrollbar.
   2290      */
   2291     public int getVerticalScrollbarWidth() {
   2292         ScrollabilityCache cache = mScrollCache;
   2293         if (cache != null) {
   2294             ScrollBarDrawable scrollBar = cache.scrollBar;
   2295             if (scrollBar != null) {
   2296                 int size = scrollBar.getSize(true);
   2297                 if (size <= 0) {
   2298                     size = cache.scrollBarSize;
   2299                 }
   2300                 return size;
   2301             }
   2302             return 0;
   2303         }
   2304         return 0;
   2305     }
   2306 
   2307     /**
   2308      * Returns the height of the horizontal scrollbar.
   2309      *
   2310      * @return The height in pixels of the horizontal scrollbar or 0 if
   2311      *         there is no horizontal scrollbar.
   2312      */
   2313     protected int getHorizontalScrollbarHeight() {
   2314         ScrollabilityCache cache = mScrollCache;
   2315         if (cache != null) {
   2316             ScrollBarDrawable scrollBar = cache.scrollBar;
   2317             if (scrollBar != null) {
   2318                 int size = scrollBar.getSize(false);
   2319                 if (size <= 0) {
   2320                     size = cache.scrollBarSize;
   2321                 }
   2322                 return size;
   2323             }
   2324             return 0;
   2325         }
   2326         return 0;
   2327     }
   2328 
   2329     /**
   2330      * <p>
   2331      * Initializes the scrollbars from a given set of styled attributes. This
   2332      * method should be called by subclasses that need scrollbars and when an
   2333      * instance of these subclasses is created programmatically rather than
   2334      * being inflated from XML. This method is automatically called when the XML
   2335      * is inflated.
   2336      * </p>
   2337      *
   2338      * @param a the styled attributes set to initialize the scrollbars from
   2339      */
   2340     protected void initializeScrollbars(TypedArray a) {
   2341         initScrollCache();
   2342 
   2343         final ScrollabilityCache scrollabilityCache = mScrollCache;
   2344 
   2345         if (scrollabilityCache.scrollBar == null) {
   2346             scrollabilityCache.scrollBar = new ScrollBarDrawable();
   2347         }
   2348 
   2349         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
   2350 
   2351         if (!fadeScrollbars) {
   2352             scrollabilityCache.state = ScrollabilityCache.ON;
   2353         }
   2354         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   2355 
   2356 
   2357         scrollabilityCache.scrollBarFadeDuration = a.getInt(
   2358                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
   2359                         .getScrollBarFadeDuration());
   2360         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
   2361                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
   2362                 ViewConfiguration.getScrollDefaultDelay());
   2363 
   2364 
   2365         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
   2366                 com.android.internal.R.styleable.View_scrollbarSize,
   2367                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
   2368 
   2369         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
   2370         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
   2371 
   2372         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
   2373         if (thumb != null) {
   2374             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
   2375         }
   2376 
   2377         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
   2378                 false);
   2379         if (alwaysDraw) {
   2380             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
   2381         }
   2382 
   2383         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
   2384         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
   2385 
   2386         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
   2387         if (thumb != null) {
   2388             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
   2389         }
   2390 
   2391         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
   2392                 false);
   2393         if (alwaysDraw) {
   2394             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
   2395         }
   2396 
   2397         // Re-apply user/background padding so that scrollbar(s) get added
   2398         recomputePadding();
   2399     }
   2400 
   2401     /**
   2402      * <p>
   2403      * Initalizes the scrollability cache if necessary.
   2404      * </p>
   2405      */
   2406     private void initScrollCache() {
   2407         if (mScrollCache == null) {
   2408             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
   2409         }
   2410     }
   2411 
   2412     /**
   2413      * Register a callback to be invoked when focus of this view changed.
   2414      *
   2415      * @param l The callback that will run.
   2416      */
   2417     public void setOnFocusChangeListener(OnFocusChangeListener l) {
   2418         mOnFocusChangeListener = l;
   2419     }
   2420 
   2421     /**
   2422      * Returns the focus-change callback registered for this view.
   2423      *
   2424      * @return The callback, or null if one is not registered.
   2425      */
   2426     public OnFocusChangeListener getOnFocusChangeListener() {
   2427         return mOnFocusChangeListener;
   2428     }
   2429 
   2430     /**
   2431      * Register a callback to be invoked when this view is clicked. If this view is not
   2432      * clickable, it becomes clickable.
   2433      *
   2434      * @param l The callback that will run
   2435      *
   2436      * @see #setClickable(boolean)
   2437      */
   2438     public void setOnClickListener(OnClickListener l) {
   2439         if (!isClickable()) {
   2440             setClickable(true);
   2441         }
   2442         mOnClickListener = l;
   2443     }
   2444 
   2445     /**
   2446      * Register a callback to be invoked when this view is clicked and held. If this view is not
   2447      * long clickable, it becomes long clickable.
   2448      *
   2449      * @param l The callback that will run
   2450      *
   2451      * @see #setLongClickable(boolean)
   2452      */
   2453     public void setOnLongClickListener(OnLongClickListener l) {
   2454         if (!isLongClickable()) {
   2455             setLongClickable(true);
   2456         }
   2457         mOnLongClickListener = l;
   2458     }
   2459 
   2460     /**
   2461      * Register a callback to be invoked when the context menu for this view is
   2462      * being built. If this view is not long clickable, it becomes long clickable.
   2463      *
   2464      * @param l The callback that will run
   2465      *
   2466      */
   2467     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
   2468         if (!isLongClickable()) {
   2469             setLongClickable(true);
   2470         }
   2471         mOnCreateContextMenuListener = l;
   2472     }
   2473 
   2474     /**
   2475      * Call this view's OnClickListener, if it is defined.
   2476      *
   2477      * @return True there was an assigned OnClickListener that was called, false
   2478      *         otherwise is returned.
   2479      */
   2480     public boolean performClick() {
   2481         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
   2482 
   2483         if (mOnClickListener != null) {
   2484             playSoundEffect(SoundEffectConstants.CLICK);
   2485             mOnClickListener.onClick(this);
   2486             return true;
   2487         }
   2488 
   2489         return false;
   2490     }
   2491 
   2492     /**
   2493      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
   2494      * OnLongClickListener did not consume the event.
   2495      *
   2496      * @return True if one of the above receivers consumed the event, false otherwise.
   2497      */
   2498     public boolean performLongClick() {
   2499         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
   2500 
   2501         boolean handled = false;
   2502         if (mOnLongClickListener != null) {
   2503             handled = mOnLongClickListener.onLongClick(View.this);
   2504         }
   2505         if (!handled) {
   2506             handled = showContextMenu();
   2507         }
   2508         if (handled) {
   2509             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
   2510         }
   2511         return handled;
   2512     }
   2513 
   2514     /**
   2515      * Bring up the context menu for this view.
   2516      *
   2517      * @return Whether a context menu was displayed.
   2518      */
   2519     public boolean showContextMenu() {
   2520         return getParent().showContextMenuForChild(this);
   2521     }
   2522 
   2523     /**
   2524      * Register a callback to be invoked when a key is pressed in this view.
   2525      * @param l the key listener to attach to this view
   2526      */
   2527     public void setOnKeyListener(OnKeyListener l) {
   2528         mOnKeyListener = l;
   2529     }
   2530 
   2531     /**
   2532      * Register a callback to be invoked when a touch event is sent to this view.
   2533      * @param l the touch listener to attach to this view
   2534      */
   2535     public void setOnTouchListener(OnTouchListener l) {
   2536         mOnTouchListener = l;
   2537     }
   2538 
   2539     /**
   2540      * Give this view focus. This will cause {@link #onFocusChanged} to be called.
   2541      *
   2542      * Note: this does not check whether this {@link View} should get focus, it just
   2543      * gives it focus no matter what.  It should only be called internally by framework
   2544      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
   2545      *
   2546      * @param direction values are View.FOCUS_UP, View.FOCUS_DOWN,
   2547      *        View.FOCUS_LEFT or View.FOCUS_RIGHT. This is the direction which
   2548      *        focus moved when requestFocus() is called. It may not always
   2549      *        apply, in which case use the default View.FOCUS_DOWN.
   2550      * @param previouslyFocusedRect The rectangle of the view that had focus
   2551      *        prior in this View's coordinate system.
   2552      */
   2553     void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
   2554         if (DBG) {
   2555             System.out.println(this + " requestFocus()");
   2556         }
   2557 
   2558         if ((mPrivateFlags & FOCUSED) == 0) {
   2559             mPrivateFlags |= FOCUSED;
   2560 
   2561             if (mParent != null) {
   2562                 mParent.requestChildFocus(this, this);
   2563             }
   2564 
   2565             onFocusChanged(true, direction, previouslyFocusedRect);
   2566             refreshDrawableState();
   2567         }
   2568     }
   2569 
   2570     /**
   2571      * Request that a rectangle of this view be visible on the screen,
   2572      * scrolling if necessary just enough.
   2573      *
   2574      * <p>A View should call this if it maintains some notion of which part
   2575      * of its content is interesting.  For example, a text editing view
   2576      * should call this when its cursor moves.
   2577      *
   2578      * @param rectangle The rectangle.
   2579      * @return Whether any parent scrolled.
   2580      */
   2581     public boolean requestRectangleOnScreen(Rect rectangle) {
   2582         return requestRectangleOnScreen(rectangle, false);
   2583     }
   2584 
   2585     /**
   2586      * Request that a rectangle of this view be visible on the screen,
   2587      * scrolling if necessary just enough.
   2588      *
   2589      * <p>A View should call this if it maintains some notion of which part
   2590      * of its content is interesting.  For example, a text editing view
   2591      * should call this when its cursor moves.
   2592      *
   2593      * <p>When <code>immediate</code> is set to true, scrolling will not be
   2594      * animated.
   2595      *
   2596      * @param rectangle The rectangle.
   2597      * @param immediate True to forbid animated scrolling, false otherwise
   2598      * @return Whether any parent scrolled.
   2599      */
   2600     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
   2601         View child = this;
   2602         ViewParent parent = mParent;
   2603         boolean scrolled = false;
   2604         while (parent != null) {
   2605             scrolled |= parent.requestChildRectangleOnScreen(child,
   2606                     rectangle, immediate);
   2607 
   2608             // offset rect so next call has the rectangle in the
   2609             // coordinate system of its direct child.
   2610             rectangle.offset(child.getLeft(), child.getTop());
   2611             rectangle.offset(-child.getScrollX(), -child.getScrollY());
   2612 
   2613             if (!(parent instanceof View)) {
   2614                 break;
   2615             }
   2616 
   2617             child = (View) parent;
   2618             parent = child.getParent();
   2619         }
   2620         return scrolled;
   2621     }
   2622 
   2623     /**
   2624      * Called when this view wants to give up focus. This will cause
   2625      * {@link #onFocusChanged} to be called.
   2626      */
   2627     public void clearFocus() {
   2628         if (DBG) {
   2629             System.out.println(this + " clearFocus()");
   2630         }
   2631 
   2632         if ((mPrivateFlags & FOCUSED) != 0) {
   2633             mPrivateFlags &= ~FOCUSED;
   2634 
   2635             if (mParent != null) {
   2636                 mParent.clearChildFocus(this);
   2637             }
   2638 
   2639             onFocusChanged(false, 0, null);
   2640             refreshDrawableState();
   2641         }
   2642     }
   2643 
   2644     /**
   2645      * Called to clear the focus of a view that is about to be removed.
   2646      * Doesn't call clearChildFocus, which prevents this view from taking
   2647      * focus again before it has been removed from the parent
   2648      */
   2649     void clearFocusForRemoval() {
   2650         if ((mPrivateFlags & FOCUSED) != 0) {
   2651             mPrivateFlags &= ~FOCUSED;
   2652 
   2653             onFocusChanged(false, 0, null);
   2654             refreshDrawableState();
   2655         }
   2656     }
   2657 
   2658     /**
   2659      * Called internally by the view system when a new view is getting focus.
   2660      * This is what clears the old focus.
   2661      */
   2662     void unFocus() {
   2663         if (DBG) {
   2664             System.out.println(this + " unFocus()");
   2665         }
   2666 
   2667         if ((mPrivateFlags & FOCUSED) != 0) {
   2668             mPrivateFlags &= ~FOCUSED;
   2669 
   2670             onFocusChanged(false, 0, null);
   2671             refreshDrawableState();
   2672         }
   2673     }
   2674 
   2675     /**
   2676      * Returns true if this view has focus iteself, or is the ancestor of the
   2677      * view that has focus.
   2678      *
   2679      * @return True if this view has or contains focus, false otherwise.
   2680      */
   2681     @ViewDebug.ExportedProperty(category = "focus")
   2682     public boolean hasFocus() {
   2683         return (mPrivateFlags & FOCUSED) != 0;
   2684     }
   2685 
   2686     /**
   2687      * Returns true if this view is focusable or if it contains a reachable View
   2688      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
   2689      * is a View whose parents do not block descendants focus.
   2690      *
   2691      * Only {@link #VISIBLE} views are considered focusable.
   2692      *
   2693      * @return True if the view is focusable or if the view contains a focusable
   2694      *         View, false otherwise.
   2695      *
   2696      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
   2697      */
   2698     public boolean hasFocusable() {
   2699         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
   2700     }
   2701 
   2702     /**
   2703      * Called by the view system when the focus state of this view changes.
   2704      * When the focus change event is caused by directional navigation, direction
   2705      * and previouslyFocusedRect provide insight into where the focus is coming from.
   2706      * When overriding, be sure to call up through to the super class so that
   2707      * the standard focus handling will occur.
   2708      *
   2709      * @param gainFocus True if the View has focus; false otherwise.
   2710      * @param direction The direction focus has moved when requestFocus()
   2711      *                  is called to give this view focus. Values are
   2712      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT} or
   2713      *                  {@link #FOCUS_RIGHT}. It may not always apply, in which
   2714      *                  case use the default.
   2715      * @param previouslyFocusedRect The rectangle, in this view's coordinate
   2716      *        system, of the previously focused view.  If applicable, this will be
   2717      *        passed in as finer grained information about where the focus is coming
   2718      *        from (in addition to direction).  Will be <code>null</code> otherwise.
   2719      */
   2720     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
   2721         if (gainFocus) {
   2722             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
   2723         }
   2724 
   2725         InputMethodManager imm = InputMethodManager.peekInstance();
   2726         if (!gainFocus) {
   2727             if (isPressed()) {
   2728                 setPressed(false);
   2729             }
   2730             if (imm != null && mAttachInfo != null
   2731                     && mAttachInfo.mHasWindowFocus) {
   2732                 imm.focusOut(this);
   2733             }
   2734             onFocusLost();
   2735         } else if (imm != null && mAttachInfo != null
   2736                 && mAttachInfo.mHasWindowFocus) {
   2737             imm.focusIn(this);
   2738         }
   2739 
   2740         invalidate();
   2741         if (mOnFocusChangeListener != null) {
   2742             mOnFocusChangeListener.onFocusChange(this, gainFocus);
   2743         }
   2744 
   2745         if (mAttachInfo != null) {
   2746             mAttachInfo.mKeyDispatchState.reset(this);
   2747         }
   2748     }
   2749 
   2750     /**
   2751      * {@inheritDoc}
   2752      */
   2753     public void sendAccessibilityEvent(int eventType) {
   2754         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   2755             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
   2756         }
   2757     }
   2758 
   2759     /**
   2760      * {@inheritDoc}
   2761      */
   2762     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
   2763         event.setClassName(getClass().getName());
   2764         event.setPackageName(getContext().getPackageName());
   2765         event.setEnabled(isEnabled());
   2766         event.setContentDescription(mContentDescription);
   2767 
   2768         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
   2769             ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
   2770             getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
   2771             event.setItemCount(focusablesTempList.size());
   2772             event.setCurrentItemIndex(focusablesTempList.indexOf(this));
   2773             focusablesTempList.clear();
   2774         }
   2775 
   2776         dispatchPopulateAccessibilityEvent(event);
   2777 
   2778         AccessibilityManager.getInstance(mContext).sendAccessibilityEvent(event);
   2779     }
   2780 
   2781     /**
   2782      * Dispatches an {@link AccessibilityEvent} to the {@link View} children
   2783      * to be populated.
   2784      *
   2785      * @param event The event.
   2786      *
   2787      * @return True if the event population was completed.
   2788      */
   2789     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
   2790         return false;
   2791     }
   2792 
   2793     /**
   2794      * Gets the {@link View} description. It briefly describes the view and is
   2795      * primarily used for accessibility support. Set this property to enable
   2796      * better accessibility support for your application. This is especially
   2797      * true for views that do not have textual representation (For example,
   2798      * ImageButton).
   2799      *
   2800      * @return The content descriptiopn.
   2801      *
   2802      * @attr ref android.R.styleable#View_contentDescription
   2803      */
   2804     public CharSequence getContentDescription() {
   2805         return mContentDescription;
   2806     }
   2807 
   2808     /**
   2809      * Sets the {@link View} description. It briefly describes the view and is
   2810      * primarily used for accessibility support. Set this property to enable
   2811      * better accessibility support for your application. This is especially
   2812      * true for views that do not have textual representation (For example,
   2813      * ImageButton).
   2814      *
   2815      * @param contentDescription The content description.
   2816      *
   2817      * @attr ref android.R.styleable#View_contentDescription
   2818      */
   2819     public void setContentDescription(CharSequence contentDescription) {
   2820         mContentDescription = contentDescription;
   2821     }
   2822 
   2823     /**
   2824      * Invoked whenever this view loses focus, either by losing window focus or by losing
   2825      * focus within its window. This method can be used to clear any state tied to the
   2826      * focus. For instance, if a button is held pressed with the trackball and the window
   2827      * loses focus, this method can be used to cancel the press.
   2828      *
   2829      * Subclasses of View overriding this method should always call super.onFocusLost().
   2830      *
   2831      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
   2832      * @see #onWindowFocusChanged(boolean)
   2833      *
   2834      * @hide pending API council approval
   2835      */
   2836     protected void onFocusLost() {
   2837         resetPressedState();
   2838     }
   2839 
   2840     private void resetPressedState() {
   2841         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   2842             return;
   2843         }
   2844 
   2845         if (isPressed()) {
   2846             setPressed(false);
   2847 
   2848             if (!mHasPerformedLongPress) {
   2849                 removeLongPressCallback();
   2850             }
   2851         }
   2852     }
   2853 
   2854     /**
   2855      * Returns true if this view has focus
   2856      *
   2857      * @return True if this view has focus, false otherwise.
   2858      */
   2859     @ViewDebug.ExportedProperty(category = "focus")
   2860     public boolean isFocused() {
   2861         return (mPrivateFlags & FOCUSED) != 0;
   2862     }
   2863 
   2864     /**
   2865      * Find the view in the hierarchy rooted at this view that currently has
   2866      * focus.
   2867      *
   2868      * @return The view that currently has focus, or null if no focused view can
   2869      *         be found.
   2870      */
   2871     public View findFocus() {
   2872         return (mPrivateFlags & FOCUSED) != 0 ? this : null;
   2873     }
   2874 
   2875     /**
   2876      * Change whether this view is one of the set of scrollable containers in
   2877      * its window.  This will be used to determine whether the window can
   2878      * resize or must pan when a soft input area is open -- scrollable
   2879      * containers allow the window to use resize mode since the container
   2880      * will appropriately shrink.
   2881      */
   2882     public void setScrollContainer(boolean isScrollContainer) {
   2883         if (isScrollContainer) {
   2884             if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
   2885                 mAttachInfo.mScrollContainers.add(this);
   2886                 mPrivateFlags |= SCROLL_CONTAINER_ADDED;
   2887             }
   2888             mPrivateFlags |= SCROLL_CONTAINER;
   2889         } else {
   2890             if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
   2891                 mAttachInfo.mScrollContainers.remove(this);
   2892             }
   2893             mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
   2894         }
   2895     }
   2896 
   2897     /**
   2898      * Returns the quality of the drawing cache.
   2899      *
   2900      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   2901      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   2902      *
   2903      * @see #setDrawingCacheQuality(int)
   2904      * @see #setDrawingCacheEnabled(boolean)
   2905      * @see #isDrawingCacheEnabled()
   2906      *
   2907      * @attr ref android.R.styleable#View_drawingCacheQuality
   2908      */
   2909     public int getDrawingCacheQuality() {
   2910         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
   2911     }
   2912 
   2913     /**
   2914      * Set the drawing cache quality of this view. This value is used only when the
   2915      * drawing cache is enabled
   2916      *
   2917      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   2918      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   2919      *
   2920      * @see #getDrawingCacheQuality()
   2921      * @see #setDrawingCacheEnabled(boolean)
   2922      * @see #isDrawingCacheEnabled()
   2923      *
   2924      * @attr ref android.R.styleable#View_drawingCacheQuality
   2925      */
   2926     public void setDrawingCacheQuality(int quality) {
   2927         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
   2928     }
   2929 
   2930     /**
   2931      * Returns whether the screen should remain on, corresponding to the current
   2932      * value of {@link #KEEP_SCREEN_ON}.
   2933      *
   2934      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
   2935      *
   2936      * @see #setKeepScreenOn(boolean)
   2937      *
   2938      * @attr ref android.R.styleable#View_keepScreenOn
   2939      */
   2940     public boolean getKeepScreenOn() {
   2941         return (mViewFlags & KEEP_SCREEN_ON) != 0;
   2942     }
   2943 
   2944     /**
   2945      * Controls whether the screen should remain on, modifying the
   2946      * value of {@link #KEEP_SCREEN_ON}.
   2947      *
   2948      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
   2949      *
   2950      * @see #getKeepScreenOn()
   2951      *
   2952      * @attr ref android.R.styleable#View_keepScreenOn
   2953      */
   2954     public void setKeepScreenOn(boolean keepScreenOn) {
   2955         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
   2956     }
   2957 
   2958     /**
   2959      * @return The user specified next focus ID.
   2960      *
   2961      * @attr ref android.R.styleable#View_nextFocusLeft
   2962      */
   2963     public int getNextFocusLeftId() {
   2964         return mNextFocusLeftId;
   2965     }
   2966 
   2967     /**
   2968      * Set the id of the view to use for the next focus
   2969      *
   2970      * @param nextFocusLeftId
   2971      *
   2972      * @attr ref android.R.styleable#View_nextFocusLeft
   2973      */
   2974     public void setNextFocusLeftId(int nextFocusLeftId) {
   2975         mNextFocusLeftId = nextFocusLeftId;
   2976     }
   2977 
   2978     /**
   2979      * @return The user specified next focus ID.
   2980      *
   2981      * @attr ref android.R.styleable#View_nextFocusRight
   2982      */
   2983     public int getNextFocusRightId() {
   2984         return mNextFocusRightId;
   2985     }
   2986 
   2987     /**
   2988      * Set the id of the view to use for the next focus
   2989      *
   2990      * @param nextFocusRightId
   2991      *
   2992      * @attr ref android.R.styleable#View_nextFocusRight
   2993      */
   2994     public void setNextFocusRightId(int nextFocusRightId) {
   2995         mNextFocusRightId = nextFocusRightId;
   2996     }
   2997 
   2998     /**
   2999      * @return The user specified next focus ID.
   3000      *
   3001      * @attr ref android.R.styleable#View_nextFocusUp
   3002      */
   3003     public int getNextFocusUpId() {
   3004         return mNextFocusUpId;
   3005     }
   3006 
   3007     /**
   3008      * Set the id of the view to use for the next focus
   3009      *
   3010      * @param nextFocusUpId
   3011      *
   3012      * @attr ref android.R.styleable#View_nextFocusUp
   3013      */
   3014     public void setNextFocusUpId(int nextFocusUpId) {
   3015         mNextFocusUpId = nextFocusUpId;
   3016     }
   3017 
   3018     /**
   3019      * @return The user specified next focus ID.
   3020      *
   3021      * @attr ref android.R.styleable#View_nextFocusDown
   3022      */
   3023     public int getNextFocusDownId() {
   3024         return mNextFocusDownId;
   3025     }
   3026 
   3027     /**
   3028      * Set the id of the view to use for the next focus
   3029      *
   3030      * @param nextFocusDownId
   3031      *
   3032      * @attr ref android.R.styleable#View_nextFocusDown
   3033      */
   3034     public void setNextFocusDownId(int nextFocusDownId) {
   3035         mNextFocusDownId = nextFocusDownId;
   3036     }
   3037 
   3038     /**
   3039      * Returns the visibility of this view and all of its ancestors
   3040      *
   3041      * @return True if this view and all of its ancestors are {@link #VISIBLE}
   3042      */
   3043     public boolean isShown() {
   3044         View current = this;
   3045         //noinspection ConstantConditions
   3046         do {
   3047             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   3048                 return false;
   3049             }
   3050             ViewParent parent = current.mParent;
   3051             if (parent == null) {
   3052                 return false; // We are not attached to the view root
   3053             }
   3054             if (!(parent instanceof View)) {
   3055                 return true;
   3056             }
   3057             current = (View) parent;
   3058         } while (current != null);
   3059 
   3060         return false;
   3061     }
   3062 
   3063     /**
   3064      * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
   3065      * is set
   3066      *
   3067      * @param insets Insets for system windows
   3068      *
   3069      * @return True if this view applied the insets, false otherwise
   3070      */
   3071     protected boolean fitSystemWindows(Rect insets) {
   3072         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
   3073             mPaddingLeft = insets.left;
   3074             mPaddingTop = insets.top;
   3075             mPaddingRight = insets.right;
   3076             mPaddingBottom = insets.bottom;
   3077             requestLayout();
   3078             return true;
   3079         }
   3080         return false;
   3081     }
   3082 
   3083     /**
   3084      * Determine if this view has the FITS_SYSTEM_WINDOWS flag set.
   3085      * @return True if window has FITS_SYSTEM_WINDOWS set
   3086      *
   3087      * @hide
   3088      */
   3089     public boolean isFitsSystemWindowsFlagSet() {
   3090         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
   3091     }
   3092 
   3093     /**
   3094      * Returns the visibility status for this view.
   3095      *
   3096      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   3097      * @attr ref android.R.styleable#View_visibility
   3098      */
   3099     @ViewDebug.ExportedProperty(mapping = {
   3100         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
   3101         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
   3102         @ViewDebug.IntToString(from = GONE,      to = "GONE")
   3103     })
   3104     public int getVisibility() {
   3105         return mViewFlags & VISIBILITY_MASK;
   3106     }
   3107 
   3108     /**
   3109      * Set the enabled state of this view.
   3110      *
   3111      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   3112      * @attr ref android.R.styleable#View_visibility
   3113      */
   3114     @RemotableViewMethod
   3115     public void setVisibility(int visibility) {
   3116         setFlags(visibility, VISIBILITY_MASK);
   3117         if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
   3118     }
   3119 
   3120     /**
   3121      * Returns the enabled status for this view. The interpretation of the
   3122      * enabled state varies by subclass.
   3123      *
   3124      * @return True if this view is enabled, false otherwise.
   3125      */
   3126     @ViewDebug.ExportedProperty
   3127     public boolean isEnabled() {
   3128         return (mViewFlags & ENABLED_MASK) == ENABLED;
   3129     }
   3130 
   3131     /**
   3132      * Set the enabled state of this view. The interpretation of the enabled
   3133      * state varies by subclass.
   3134      *
   3135      * @param enabled True if this view is enabled, false otherwise.
   3136      */
   3137     @RemotableViewMethod
   3138     public void setEnabled(boolean enabled) {
   3139         if (enabled == isEnabled()) return;
   3140 
   3141         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
   3142 
   3143         /*
   3144          * The View most likely has to change its appearance, so refresh
   3145          * the drawable state.
   3146          */
   3147         refreshDrawableState();
   3148 
   3149         // Invalidate too, since the default behavior for views is to be
   3150         // be drawn at 50% alpha rather than to change the drawable.
   3151         invalidate();
   3152     }
   3153 
   3154     /**
   3155      * Set whether this view can receive the focus.
   3156      *
   3157      * Setting this to false will also ensure that this view is not focusable
   3158      * in touch mode.
   3159      *
   3160      * @param focusable If true, this view can receive the focus.
   3161      *
   3162      * @see #setFocusableInTouchMode(boolean)
   3163      * @attr ref android.R.styleable#View_focusable
   3164      */
   3165     public void setFocusable(boolean focusable) {
   3166         if (!focusable) {
   3167             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
   3168         }
   3169         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
   3170     }
   3171 
   3172     /**
   3173      * Set whether this view can receive focus while in touch mode.
   3174      *
   3175      * Setting this to true will also ensure that this view is focusable.
   3176      *
   3177      * @param focusableInTouchMode If true, this view can receive the focus while
   3178      *   in touch mode.
   3179      *
   3180      * @see #setFocusable(boolean)
   3181      * @attr ref android.R.styleable#View_focusableInTouchMode
   3182      */
   3183     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
   3184         // Focusable in touch mode should always be set before the focusable flag
   3185         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
   3186         // which, in touch mode, will not successfully request focus on this view
   3187         // because the focusable in touch mode flag is not set
   3188         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
   3189         if (focusableInTouchMode) {
   3190             setFlags(FOCUSABLE, FOCUSABLE_MASK);
   3191         }
   3192     }
   3193 
   3194     /**
   3195      * Set whether this view should have sound effects enabled for events such as
   3196      * clicking and touching.
   3197      *
   3198      * <p>You may wish to disable sound effects for a view if you already play sounds,
   3199      * for instance, a dial key that plays dtmf tones.
   3200      *
   3201      * @param soundEffectsEnabled whether sound effects are enabled for this view.
   3202      * @see #isSoundEffectsEnabled()
   3203      * @see #playSoundEffect(int)
   3204      * @attr ref android.R.styleable#View_soundEffectsEnabled
   3205      */
   3206     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
   3207         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
   3208     }
   3209 
   3210     /**
   3211      * @return whether this view should have sound effects enabled for events such as
   3212      *     clicking and touching.
   3213      *
   3214      * @see #setSoundEffectsEnabled(boolean)
   3215      * @see #playSoundEffect(int)
   3216      * @attr ref android.R.styleable#View_soundEffectsEnabled
   3217      */
   3218     @ViewDebug.ExportedProperty
   3219     public boolean isSoundEffectsEnabled() {
   3220         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
   3221     }
   3222 
   3223     /**
   3224      * Set whether this view should have haptic feedback for events such as
   3225      * long presses.
   3226      *
   3227      * <p>You may wish to disable haptic feedback if your view already controls
   3228      * its own haptic feedback.
   3229      *
   3230      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
   3231      * @see #isHapticFeedbackEnabled()
   3232      * @see #performHapticFeedback(int)
   3233      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   3234      */
   3235     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
   3236         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
   3237     }
   3238 
   3239     /**
   3240      * @return whether this view should have haptic feedback enabled for events
   3241      * long presses.
   3242      *
   3243      * @see #setHapticFeedbackEnabled(boolean)
   3244      * @see #performHapticFeedback(int)
   3245      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   3246      */
   3247     @ViewDebug.ExportedProperty
   3248     public boolean isHapticFeedbackEnabled() {
   3249         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
   3250     }
   3251 
   3252     /**
   3253      * If this view doesn't do any drawing on its own, set this flag to
   3254      * allow further optimizations. By default, this flag is not set on
   3255      * View, but could be set on some View subclasses such as ViewGroup.
   3256      *
   3257      * Typically, if you override {@link #onDraw} you should clear this flag.
   3258      *
   3259      * @param willNotDraw whether or not this View draw on its own
   3260      */
   3261     public void setWillNotDraw(boolean willNotDraw) {
   3262         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
   3263     }
   3264 
   3265     /**
   3266      * Returns whether or not this View draws on its own.
   3267      *
   3268      * @return true if this view has nothing to draw, false otherwise
   3269      */
   3270     @ViewDebug.ExportedProperty(category = "drawing")
   3271     public boolean willNotDraw() {
   3272         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
   3273     }
   3274 
   3275     /**
   3276      * When a View's drawing cache is enabled, drawing is redirected to an
   3277      * offscreen bitmap. Some views, like an ImageView, must be able to
   3278      * bypass this mechanism if they already draw a single bitmap, to avoid
   3279      * unnecessary usage of the memory.
   3280      *
   3281      * @param willNotCacheDrawing true if this view does not cache its
   3282      *        drawing, false otherwise
   3283      */
   3284     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
   3285         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
   3286     }
   3287 
   3288     /**
   3289      * Returns whether or not this View can cache its drawing or not.
   3290      *
   3291      * @return true if this view does not cache its drawing, false otherwise
   3292      */
   3293     @ViewDebug.ExportedProperty(category = "drawing")
   3294     public boolean willNotCacheDrawing() {
   3295         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
   3296     }
   3297 
   3298     /**
   3299      * Indicates whether this view reacts to click events or not.
   3300      *
   3301      * @return true if the view is clickable, false otherwise
   3302      *
   3303      * @see #setClickable(boolean)
   3304      * @attr ref android.R.styleable#View_clickable
   3305      */
   3306     @ViewDebug.ExportedProperty
   3307     public boolean isClickable() {
   3308         return (mViewFlags & CLICKABLE) == CLICKABLE;
   3309     }
   3310 
   3311     /**
   3312      * Enables or disables click events for this view. When a view
   3313      * is clickable it will change its state to "pressed" on every click.
   3314      * Subclasses should set the view clickable to visually react to
   3315      * user's clicks.
   3316      *
   3317      * @param clickable true to make the view clickable, false otherwise
   3318      *
   3319      * @see #isClickable()
   3320      * @attr ref android.R.styleable#View_clickable
   3321      */
   3322     public void setClickable(boolean clickable) {
   3323         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
   3324     }
   3325 
   3326     /**
   3327      * Indicates whether this view reacts to long click events or not.
   3328      *
   3329      * @return true if the view is long clickable, false otherwise
   3330      *
   3331      * @see #setLongClickable(boolean)
   3332      * @attr ref android.R.styleable#View_longClickable
   3333      */
   3334     public boolean isLongClickable() {
   3335         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   3336     }
   3337 
   3338     /**
   3339      * Enables or disables long click events for this view. When a view is long
   3340      * clickable it reacts to the user holding down the button for a longer
   3341      * duration than a tap. This event can either launch the listener or a
   3342      * context menu.
   3343      *
   3344      * @param longClickable true to make the view long clickable, false otherwise
   3345      * @see #isLongClickable()
   3346      * @attr ref android.R.styleable#View_longClickable
   3347      */
   3348     public void setLongClickable(boolean longClickable) {
   3349         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
   3350     }
   3351 
   3352     /**
   3353      * Sets the pressed that for this view.
   3354      *
   3355      * @see #isClickable()
   3356      * @see #setClickable(boolean)
   3357      *
   3358      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
   3359      *        the View's internal state from a previously set "pressed" state.
   3360      */
   3361     public void setPressed(boolean pressed) {
   3362         if (pressed) {
   3363             mPrivateFlags |= PRESSED;
   3364         } else {
   3365             mPrivateFlags &= ~PRESSED;
   3366         }
   3367         refreshDrawableState();
   3368         dispatchSetPressed(pressed);
   3369     }
   3370 
   3371     /**
   3372      * Dispatch setPressed to all of this View's children.
   3373      *
   3374      * @see #setPressed(boolean)
   3375      *
   3376      * @param pressed The new pressed state
   3377      */
   3378     protected void dispatchSetPressed(boolean pressed) {
   3379     }
   3380 
   3381     /**
   3382      * Indicates whether the view is currently in pressed state. Unless
   3383      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
   3384      * the pressed state.
   3385      *
   3386      * @see #setPressed
   3387      * @see #isClickable()
   3388      * @see #setClickable(boolean)
   3389      *
   3390      * @return true if the view is currently pressed, false otherwise
   3391      */
   3392     public boolean isPressed() {
   3393         return (mPrivateFlags & PRESSED) == PRESSED;
   3394     }
   3395 
   3396     /**
   3397      * Indicates whether this view will save its state (that is,
   3398      * whether its {@link #onSaveInstanceState} method will be called).
   3399      *
   3400      * @return Returns true if the view state saving is enabled, else false.
   3401      *
   3402      * @see #setSaveEnabled(boolean)
   3403      * @attr ref android.R.styleable#View_saveEnabled
   3404      */
   3405     public boolean isSaveEnabled() {
   3406         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
   3407     }
   3408 
   3409     /**
   3410      * Controls whether the saving of this view's state is
   3411      * enabled (that is, whether its {@link #onSaveInstanceState} method
   3412      * will be called).  Note that even if freezing is enabled, the
   3413      * view still must have an id assigned to it (via {@link #setId setId()})
   3414      * for its state to be saved.  This flag can only disable the
   3415      * saving of this view; any child views may still have their state saved.
   3416      *
   3417      * @param enabled Set to false to <em>disable</em> state saving, or true
   3418      * (the default) to allow it.
   3419      *
   3420      * @see #isSaveEnabled()
   3421      * @see #setId(int)
   3422      * @see #onSaveInstanceState()
   3423      * @attr ref android.R.styleable#View_saveEnabled
   3424      */
   3425     public void setSaveEnabled(boolean enabled) {
   3426         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
   3427     }
   3428 
   3429     /**
   3430      * Gets whether the framework should discard touches when the view's
   3431      * window is obscured by another visible window.
   3432      * Refer to the {@link View} security documentation for more details.
   3433      *
   3434      * @return True if touch filtering is enabled.
   3435      *
   3436      * @see #setFilterTouchesWhenObscured(boolean)
   3437      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   3438      */
   3439     @ViewDebug.ExportedProperty
   3440     public boolean getFilterTouchesWhenObscured() {
   3441         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
   3442     }
   3443 
   3444     /**
   3445      * Sets whether the framework should discard touches when the view's
   3446      * window is obscured by another visible window.
   3447      * Refer to the {@link View} security documentation for more details.
   3448      *
   3449      * @param enabled True if touch filtering should be enabled.
   3450      *
   3451      * @see #getFilterTouchesWhenObscured
   3452      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   3453      */
   3454     public void setFilterTouchesWhenObscured(boolean enabled) {
   3455         setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
   3456                 FILTER_TOUCHES_WHEN_OBSCURED);
   3457     }
   3458 
   3459     /**
   3460      * Returns whether this View is able to take focus.
   3461      *
   3462      * @return True if this view can take focus, or false otherwise.
   3463      * @attr ref android.R.styleable#View_focusable
   3464      */
   3465     @ViewDebug.ExportedProperty(category = "focus")
   3466     public final boolean isFocusable() {
   3467         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
   3468     }
   3469 
   3470     /**
   3471      * When a view is focusable, it may not want to take focus when in touch mode.
   3472      * For example, a button would like focus when the user is navigating via a D-pad
   3473      * so that the user can click on it, but once the user starts touching the screen,
   3474      * the button shouldn't take focus
   3475      * @return Whether the view is focusable in touch mode.
   3476      * @attr ref android.R.styleable#View_focusableInTouchMode
   3477      */
   3478     @ViewDebug.ExportedProperty
   3479     public final boolean isFocusableInTouchMode() {
   3480         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
   3481     }
   3482 
   3483     /**
   3484      * Find the nearest view in the specified direction that can take focus.
   3485      * This does not actually give focus to that view.
   3486      *
   3487      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   3488      *
   3489      * @return The nearest focusable in the specified direction, or null if none
   3490      *         can be found.
   3491      */
   3492     public View focusSearch(int direction) {
   3493         if (mParent != null) {
   3494             return mParent.focusSearch(this, direction);
   3495         } else {
   3496             return null;
   3497         }
   3498     }
   3499 
   3500     /**
   3501      * This method is the last chance for the focused view and its ancestors to
   3502      * respond to an arrow key. This is called when the focused view did not
   3503      * consume the key internally, nor could the view system find a new view in
   3504      * the requested direction to give focus to.
   3505      *
   3506      * @param focused The currently focused view.
   3507      * @param direction The direction focus wants to move. One of FOCUS_UP,
   3508      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
   3509      * @return True if the this view consumed this unhandled move.
   3510      */
   3511     public boolean dispatchUnhandledMove(View focused, int direction) {
   3512         return false;
   3513     }
   3514 
   3515     /**
   3516      * If a user manually specified the next view id for a particular direction,
   3517      * use the root to look up the view.  Once a view is found, it is cached
   3518      * for future lookups.
   3519      * @param root The root view of the hierarchy containing this view.
   3520      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   3521      * @return The user specified next view, or null if there is none.
   3522      */
   3523     View findUserSetNextFocus(View root, int direction) {
   3524         switch (direction) {
   3525             case FOCUS_LEFT:
   3526                 if (mNextFocusLeftId == View.NO_ID) return null;
   3527                 return findViewShouldExist(root, mNextFocusLeftId);
   3528             case FOCUS_RIGHT:
   3529                 if (mNextFocusRightId == View.NO_ID) return null;
   3530                 return findViewShouldExist(root, mNextFocusRightId);
   3531             case FOCUS_UP:
   3532                 if (mNextFocusUpId == View.NO_ID) return null;
   3533                 return findViewShouldExist(root, mNextFocusUpId);
   3534             case FOCUS_DOWN:
   3535                 if (mNextFocusDownId == View.NO_ID) return null;
   3536                 return findViewShouldExist(root, mNextFocusDownId);
   3537         }
   3538         return null;
   3539     }
   3540 
   3541     private static View findViewShouldExist(View root, int childViewId) {
   3542         View result = root.findViewById(childViewId);
   3543         if (result == null) {
   3544             Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
   3545                     + "by user for id " + childViewId);
   3546         }
   3547         return result;
   3548     }
   3549 
   3550     /**
   3551      * Find and return all focusable views that are descendants of this view,
   3552      * possibly including this view if it is focusable itself.
   3553      *
   3554      * @param direction The direction of the focus
   3555      * @return A list of focusable views
   3556      */
   3557     public ArrayList<View> getFocusables(int direction) {
   3558         ArrayList<View> result = new ArrayList<View>(24);
   3559         addFocusables(result, direction);
   3560         return result;
   3561     }
   3562 
   3563     /**
   3564      * Add any focusable views that are descendants of this view (possibly
   3565      * including this view if it is focusable itself) to views.  If we are in touch mode,
   3566      * only add views that are also focusable in touch mode.
   3567      *
   3568      * @param views Focusable views found so far
   3569      * @param direction The direction of the focus
   3570      */
   3571     public void addFocusables(ArrayList<View> views, int direction) {
   3572         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
   3573     }
   3574 
   3575     /**
   3576      * Adds any focusable views that are descendants of this view (possibly
   3577      * including this view if it is focusable itself) to views. This method
   3578      * adds all focusable views regardless if we are in touch mode or
   3579      * only views focusable in touch mode if we are in touch mode depending on
   3580      * the focusable mode paramater.
   3581      *
   3582      * @param views Focusable views found so far or null if all we are interested is
   3583      *        the number of focusables.
   3584      * @param direction The direction of the focus.
   3585      * @param focusableMode The type of focusables to be added.
   3586      *
   3587      * @see #FOCUSABLES_ALL
   3588      * @see #FOCUSABLES_TOUCH_MODE
   3589      */
   3590     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
   3591         if (!isFocusable()) {
   3592             return;
   3593         }
   3594 
   3595         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
   3596                 isInTouchMode() && !isFocusableInTouchMode()) {
   3597             return;
   3598         }
   3599 
   3600         if (views != null) {
   3601             views.add(this);
   3602         }
   3603     }
   3604 
   3605     /**
   3606      * Find and return all touchable views that are descendants of this view,
   3607      * possibly including this view if it is touchable itself.
   3608      *
   3609      * @return A list of touchable views
   3610      */
   3611     public ArrayList<View> getTouchables() {
   3612         ArrayList<View> result = new ArrayList<View>();
   3613         addTouchables(result);
   3614         return result;
   3615     }
   3616 
   3617     /**
   3618      * Add any touchable views that are descendants of this view (possibly
   3619      * including this view if it is touchable itself) to views.
   3620      *
   3621      * @param views Touchable views found so far
   3622      */
   3623     public void addTouchables(ArrayList<View> views) {
   3624         final int viewFlags = mViewFlags;
   3625 
   3626         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   3627                 && (viewFlags & ENABLED_MASK) == ENABLED) {
   3628             views.add(this);
   3629         }
   3630     }
   3631 
   3632     /**
   3633      * Call this to try to give focus to a specific view or to one of its
   3634      * descendants.
   3635      *
   3636      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
   3637      * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
   3638      * while the device is in touch mode.
   3639      *
   3640      * See also {@link #focusSearch}, which is what you call to say that you
   3641      * have focus, and you want your parent to look for the next one.
   3642      *
   3643      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
   3644      * {@link #FOCUS_DOWN} and <code>null</code>.
   3645      *
   3646      * @return Whether this view or one of its descendants actually took focus.
   3647      */
   3648     public final boolean requestFocus() {
   3649         return requestFocus(View.FOCUS_DOWN);
   3650     }
   3651 
   3652 
   3653     /**
   3654      * Call this to try to give focus to a specific view or to one of its
   3655      * descendants and give it a hint about what direction focus is heading.
   3656      *
   3657      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
   3658      * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
   3659      * while the device is in touch mode.
   3660      *
   3661      * See also {@link #focusSearch}, which is what you call to say that you
   3662      * have focus, and you want your parent to look for the next one.
   3663      *
   3664      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
   3665      * <code>null</code> set for the previously focused rectangle.
   3666      *
   3667      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   3668      * @return Whether this view or one of its descendants actually took focus.
   3669      */
   3670     public final boolean requestFocus(int direction) {
   3671         return requestFocus(direction, null);
   3672     }
   3673 
   3674     /**
   3675      * Call this to try to give focus to a specific view or to one of its descendants
   3676      * and give it hints about the direction and a specific rectangle that the focus
   3677      * is coming from.  The rectangle can help give larger views a finer grained hint
   3678      * about where focus is coming from, and therefore, where to show selection, or
   3679      * forward focus change internally.
   3680      *
   3681      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
   3682      * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
   3683      * while the device is in touch mode.
   3684      *
   3685      * A View will not take focus if it is not visible.
   3686      *
   3687      * A View will not take focus if one of its parents has {@link android.view.ViewGroup#getDescendantFocusability()}
   3688      * equal to {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
   3689      *
   3690      * See also {@link #focusSearch}, which is what you call to say that you
   3691      * have focus, and you want your parent to look for the next one.
   3692      *
   3693      * You may wish to override this method if your custom {@link View} has an internal
   3694      * {@link View} that it wishes to forward the request to.
   3695      *
   3696      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   3697      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
   3698      *        to give a finer grained hint about where focus is coming from.  May be null
   3699      *        if there is no hint.
   3700      * @return Whether this view or one of its descendants actually took focus.
   3701      */
   3702     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
   3703         // need to be focusable
   3704         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
   3705                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   3706             return false;
   3707         }
   3708 
   3709         // need to be focusable in touch mode if in touch mode
   3710         if (isInTouchMode() &&
   3711                 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
   3712             return false;
   3713         }
   3714 
   3715         // need to not have any parents blocking us
   3716         if (hasAncestorThatBlocksDescendantFocus()) {
   3717             return false;
   3718         }
   3719 
   3720         handleFocusGainInternal(direction, previouslyFocusedRect);
   3721         return true;
   3722     }
   3723 
   3724     /**
   3725      * Call this to try to give focus to a specific view or to one of its descendants. This is a
   3726      * special variant of {@link #requestFocus() } that will allow views that are not focuable in
   3727      * touch mode to request focus when they are touched.
   3728      *
   3729      * @return Whether this view or one of its descendants actually took focus.
   3730      *
   3731      * @see #isInTouchMode()
   3732      *
   3733      */
   3734     public final boolean requestFocusFromTouch() {
   3735         // Leave touch mode if we need to
   3736         if (isInTouchMode()) {
   3737             View root = getRootView();
   3738             if (root != null) {
   3739                ViewRoot viewRoot = (ViewRoot)root.getParent();
   3740                if (viewRoot != null) {
   3741                    viewRoot.ensureTouchMode(false);
   3742                }
   3743             }
   3744         }
   3745         return requestFocus(View.FOCUS_DOWN);
   3746     }
   3747 
   3748     /**
   3749      * @return Whether any ancestor of this view blocks descendant focus.
   3750      */
   3751     private boolean hasAncestorThatBlocksDescendantFocus() {
   3752         ViewParent ancestor = mParent;
   3753         while (ancestor instanceof ViewGroup) {
   3754             final ViewGroup vgAncestor = (ViewGroup) ancestor;
   3755             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
   3756                 return true;
   3757             } else {
   3758                 ancestor = vgAncestor.getParent();
   3759             }
   3760         }
   3761         return false;
   3762     }
   3763 
   3764     /**
   3765      * @hide
   3766      */
   3767     public void dispatchStartTemporaryDetach() {
   3768         onStartTemporaryDetach();
   3769     }
   3770 
   3771     /**
   3772      * This is called when a container is going to temporarily detach a child, with
   3773      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
   3774      * It will either be followed by {@link #onFinishTemporaryDetach()} or
   3775      * {@link #onDetachedFromWindow()} when the container is done.
   3776      */
   3777     public void onStartTemporaryDetach() {
   3778         removeUnsetPressCallback();
   3779         mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
   3780     }
   3781 
   3782     /**
   3783      * @hide
   3784      */
   3785     public void dispatchFinishTemporaryDetach() {
   3786         onFinishTemporaryDetach();
   3787     }
   3788 
   3789     /**
   3790      * Called after {@link #onStartTemporaryDetach} when the container is done
   3791      * changing the view.
   3792      */
   3793     public void onFinishTemporaryDetach() {
   3794     }
   3795 
   3796     /**
   3797      * capture information of this view for later analysis: developement only
   3798      * check dynamic switch to make sure we only dump view
   3799      * when ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW) is set
   3800      */
   3801     private static void captureViewInfo(String subTag, View v) {
   3802         if (v == null || SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW, 0) == 0) {
   3803             return;
   3804         }
   3805         ViewDebug.dumpCapturedView(subTag, v);
   3806     }
   3807 
   3808     /**
   3809      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
   3810      * for this view's window.  Returns null if the view is not currently attached
   3811      * to the window.  Normally you will not need to use this directly, but
   3812      * just use the standard high-level event callbacks like {@link #onKeyDown}.
   3813      */
   3814     public KeyEvent.DispatcherState getKeyDispatcherState() {
   3815         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
   3816     }
   3817 
   3818     /**
   3819      * Dispatch a key event before it is processed by any input method
   3820      * associated with the view hierarchy.  This can be used to intercept
   3821      * key events in special situations before the IME consumes them; a
   3822      * typical example would be handling the BACK key to update the application's
   3823      * UI instead of allowing the IME to see it and close itself.
   3824      *
   3825      * @param event The key event to be dispatched.
   3826      * @return True if the event was handled, false otherwise.
   3827      */
   3828     public boolean dispatchKeyEventPreIme(KeyEvent event) {
   3829         return onKeyPreIme(event.getKeyCode(), event);
   3830     }
   3831 
   3832     /**
   3833      * Dispatch a key event to the next view on the focus path. This path runs
   3834      * from the top of the view tree down to the currently focused view. If this
   3835      * view has focus, it will dispatch to itself. Otherwise it will dispatch
   3836      * the next node down the focus path. This method also fires any key
   3837      * listeners.
   3838      *
   3839      * @param event The key event to be dispatched.
   3840      * @return True if the event was handled, false otherwise.
   3841      */
   3842     public boolean dispatchKeyEvent(KeyEvent event) {
   3843         // If any attached key listener a first crack at the event.
   3844         //noinspection SimplifiableIfStatement
   3845 
   3846         if (android.util.Config.LOGV) {
   3847             captureViewInfo("captureViewKeyEvent", this);
   3848         }
   3849 
   3850         if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   3851                 && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
   3852             return true;
   3853         }
   3854 
   3855         return event.dispatch(this, mAttachInfo != null
   3856                 ? mAttachInfo.mKeyDispatchState : null, this);
   3857     }
   3858 
   3859     /**
   3860      * Dispatches a key shortcut event.
   3861      *
   3862      * @param event The key event to be dispatched.
   3863      * @return True if the event was handled by the view, false otherwise.
   3864      */
   3865     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   3866         return onKeyShortcut(event.getKeyCode(), event);
   3867     }
   3868 
   3869     /**
   3870      * Pass the touch screen motion event down to the target view, or this
   3871      * view if it is the target.
   3872      *
   3873      * @param event The motion event to be dispatched.
   3874      * @return True if the event was handled by the view, false otherwise.
   3875      */
   3876     public boolean dispatchTouchEvent(MotionEvent event) {
   3877         if (!onFilterTouchEventForSecurity(event)) {
   3878             return false;
   3879         }
   3880 
   3881         if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
   3882                 mOnTouchListener.onTouch(this, event)) {
   3883             return true;
   3884         }
   3885         return onTouchEvent(event);
   3886     }
   3887 
   3888     /**
   3889      * Filter the touch event to apply security policies.
   3890      *
   3891      * @param event The motion event to be filtered.
   3892      * @return True if the event should be dispatched, false if the event should be dropped.
   3893      *
   3894      * @see #getFilterTouchesWhenObscured
   3895      */
   3896     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
   3897         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
   3898                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
   3899             // Window is obscured, drop this touch.
   3900             return false;
   3901         }
   3902         return true;
   3903     }
   3904 
   3905     /**
   3906      * Pass a trackball motion event down to the focused view.
   3907      *
   3908      * @param event The motion event to be dispatched.
   3909      * @return True if the event was handled by the view, false otherwise.
   3910      */
   3911     public boolean dispatchTrackballEvent(MotionEvent event) {
   3912         //Log.i("view", "view=" + this + ", " + event.toString());
   3913         return onTrackballEvent(event);
   3914     }
   3915 
   3916     /**
   3917      * Called when the window containing this view gains or loses window focus.
   3918      * ViewGroups should override to route to their children.
   3919      *
   3920      * @param hasFocus True if the window containing this view now has focus,
   3921      *        false otherwise.
   3922      */
   3923     public void dispatchWindowFocusChanged(boolean hasFocus) {
   3924         onWindowFocusChanged(hasFocus);
   3925     }
   3926 
   3927     /**
   3928      * Called when the window containing this view gains or loses focus.  Note
   3929      * that this is separate from view focus: to receive key events, both
   3930      * your view and its window must have focus.  If a window is displayed
   3931      * on top of yours that takes input focus, then your own window will lose
   3932      * focus but the view focus will remain unchanged.
   3933      *
   3934      * @param hasWindowFocus True if the window containing this view now has
   3935      *        focus, false otherwise.
   3936      */
   3937     public void onWindowFocusChanged(boolean hasWindowFocus) {
   3938         InputMethodManager imm = InputMethodManager.peekInstance();
   3939         if (!hasWindowFocus) {
   3940             if (isPressed()) {
   3941                 setPressed(false);
   3942             }
   3943             if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
   3944                 imm.focusOut(this);
   3945             }
   3946             removeLongPressCallback();
   3947             onFocusLost();
   3948         } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
   3949             imm.focusIn(this);
   3950         }
   3951         refreshDrawableState();
   3952     }
   3953 
   3954     /**
   3955      * Returns true if this view is in a window that currently has window focus.
   3956      * Note that this is not the same as the view itself having focus.
   3957      *
   3958      * @return True if this view is in a window that currently has window focus.
   3959      */
   3960     public boolean hasWindowFocus() {
   3961         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
   3962     }
   3963 
   3964     /**
   3965      * Dispatch a view visibility change down the view hierarchy.
   3966      * ViewGroups should override to route to their children.
   3967      * @param changedView The view whose visibility changed. Could be 'this' or
   3968      * an ancestor view.
   3969      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   3970      * {@link #INVISIBLE} or {@link #GONE}.
   3971      */
   3972     protected void dispatchVisibilityChanged(View changedView, int visibility) {
   3973         onVisibilityChanged(changedView, visibility);
   3974     }
   3975 
   3976     /**
   3977      * Called when the visibility of the view or an ancestor of the view is changed.
   3978      * @param changedView The view whose visibility changed. Could be 'this' or
   3979      * an ancestor view.
   3980      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   3981      * {@link #INVISIBLE} or {@link #GONE}.
   3982      */
   3983     protected void onVisibilityChanged(View changedView, int visibility) {
   3984         if (visibility == VISIBLE) {
   3985             if (mAttachInfo != null) {
   3986                 initialAwakenScrollBars();
   3987             } else {
   3988                 mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
   3989             }
   3990         }
   3991     }
   3992 
   3993     /**
   3994      * Dispatch a hint about whether this view is displayed. For instance, when
   3995      * a View moves out of the screen, it might receives a display hint indicating
   3996      * the view is not displayed. Applications should not <em>rely</em> on this hint
   3997      * as there is no guarantee that they will receive one.
   3998      *
   3999      * @param hint A hint about whether or not this view is displayed:
   4000      * {@link #VISIBLE} or {@link #INVISIBLE}.
   4001      */
   4002     public void dispatchDisplayHint(int hint) {
   4003         onDisplayHint(hint);
   4004     }
   4005 
   4006     /**
   4007      * Gives this view a hint about whether is displayed or not. For instance, when
   4008      * a View moves out of the screen, it might receives a display hint indicating
   4009      * the view is not displayed. Applications should not <em>rely</em> on this hint
   4010      * as there is no guarantee that they will receive one.
   4011      *
   4012      * @param hint A hint about whether or not this view is displayed:
   4013      * {@link #VISIBLE} or {@link #INVISIBLE}.
   4014      */
   4015     protected void onDisplayHint(int hint) {
   4016     }
   4017 
   4018     /**
   4019      * Dispatch a window visibility change down the view hierarchy.
   4020      * ViewGroups should override to route to their children.
   4021      *
   4022      * @param visibility The new visibility of the window.
   4023      *
   4024      * @see #onWindowVisibilityChanged
   4025      */
   4026     public void dispatchWindowVisibilityChanged(int visibility) {
   4027         onWindowVisibilityChanged(visibility);
   4028     }
   4029 
   4030     /**
   4031      * Called when the window containing has change its visibility
   4032      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
   4033      * that this tells you whether or not your window is being made visible
   4034      * to the window manager; this does <em>not</em> tell you whether or not
   4035      * your window is obscured by other windows on the screen, even if it
   4036      * is itself visible.
   4037      *
   4038      * @param visibility The new visibility of the window.
   4039      */
   4040     protected void onWindowVisibilityChanged(int visibility) {
   4041         if (visibility == VISIBLE) {
   4042             initialAwakenScrollBars();
   4043         }
   4044     }
   4045 
   4046     /**
   4047      * Returns the current visibility of the window this view is attached to
   4048      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
   4049      *
   4050      * @return Returns the current visibility of the view's window.
   4051      */
   4052     public int getWindowVisibility() {
   4053         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
   4054     }
   4055 
   4056     /**
   4057      * Retrieve the overall visible display size in which the window this view is
   4058      * attached to has been positioned in.  This takes into account screen
   4059      * decorations above the window, for both cases where the window itself
   4060      * is being position inside of them or the window is being placed under
   4061      * then and covered insets are used for the window to position its content
   4062      * inside.  In effect, this tells you the available area where content can
   4063      * be placed and remain visible to users.
   4064      *
   4065      * <p>This function requires an IPC back to the window manager to retrieve
   4066      * the requested information, so should not be used in performance critical
   4067      * code like drawing.
   4068      *
   4069      * @param outRect Filled in with the visible display frame.  If the view
   4070      * is not attached to a window, this is simply the raw display size.
   4071      */
   4072     public void getWindowVisibleDisplayFrame(Rect outRect) {
   4073         if (mAttachInfo != null) {
   4074             try {
   4075                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   4076             } catch (RemoteException e) {
   4077                 return;
   4078             }
   4079             // XXX This is really broken, and probably all needs to be done
   4080             // in the window manager, and we need to know more about whether
   4081             // we want the area behind or in front of the IME.
   4082             final Rect insets = mAttachInfo.mVisibleInsets;
   4083             outRect.left += insets.left;
   4084             outRect.top += insets.top;
   4085             outRect.right -= insets.right;
   4086             outRect.bottom -= insets.bottom;
   4087             return;
   4088         }
   4089         Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
   4090         outRect.set(0, 0, d.getWidth(), d.getHeight());
   4091     }
   4092 
   4093     /**
   4094      * Dispatch a notification about a resource configuration change down
   4095      * the view hierarchy.
   4096      * ViewGroups should override to route to their children.
   4097      *
   4098      * @param newConfig The new resource configuration.
   4099      *
   4100      * @see #onConfigurationChanged
   4101      */
   4102     public void dispatchConfigurationChanged(Configuration newConfig) {
   4103         onConfigurationChanged(newConfig);
   4104     }
   4105 
   4106     /**
   4107      * Called when the current configuration of the resources being used
   4108      * by the application have changed.  You can use this to decide when
   4109      * to reload resources that can changed based on orientation and other
   4110      * configuration characterstics.  You only need to use this if you are
   4111      * not relying on the normal {@link android.app.Activity} mechanism of
   4112      * recreating the activity instance upon a configuration change.
   4113      *
   4114      * @param newConfig The new resource configuration.
   4115      */
   4116     protected void onConfigurationChanged(Configuration newConfig) {
   4117     }
   4118 
   4119     /**
   4120      * Private function to aggregate all per-view attributes in to the view
   4121      * root.
   4122      */
   4123     void dispatchCollectViewAttributes(int visibility) {
   4124         performCollectViewAttributes(visibility);
   4125     }
   4126 
   4127     void performCollectViewAttributes(int visibility) {
   4128         //noinspection PointlessBitwiseExpression
   4129         if (((visibility | mViewFlags) & (VISIBILITY_MASK | KEEP_SCREEN_ON))
   4130                 == (VISIBLE | KEEP_SCREEN_ON)) {
   4131             mAttachInfo.mKeepScreenOn = true;
   4132         }
   4133     }
   4134 
   4135     void needGlobalAttributesUpdate(boolean force) {
   4136         AttachInfo ai = mAttachInfo;
   4137         if (ai != null) {
   4138             if (ai.mKeepScreenOn || force) {
   4139                 ai.mRecomputeGlobalAttributes = true;
   4140             }
   4141         }
   4142     }
   4143 
   4144     /**
   4145      * Returns whether the device is currently in touch mode.  Touch mode is entered
   4146      * once the user begins interacting with the device by touch, and affects various
   4147      * things like whether focus is always visible to the user.
   4148      *
   4149      * @return Whether the device is in touch mode.
   4150      */
   4151     @ViewDebug.ExportedProperty
   4152     public boolean isInTouchMode() {
   4153         if (mAttachInfo != null) {
   4154             return mAttachInfo.mInTouchMode;
   4155         } else {
   4156             return ViewRoot.isInTouchMode();
   4157         }
   4158     }
   4159 
   4160     /**
   4161      * Returns the context the view is running in, through which it can
   4162      * access the current theme, resources, etc.
   4163      *
   4164      * @return The view's Context.
   4165      */
   4166     @ViewDebug.CapturedViewProperty
   4167     public final Context getContext() {
   4168         return mContext;
   4169     }
   4170 
   4171     /**
   4172      * Handle a key event before it is processed by any input method
   4173      * associated with the view hierarchy.  This can be used to intercept
   4174      * key events in special situations before the IME consumes them; a
   4175      * typical example would be handling the BACK key to update the application's
   4176      * UI instead of allowing the IME to see it and close itself.
   4177      *
   4178      * @param keyCode The value in event.getKeyCode().
   4179      * @param event Description of the key event.
   4180      * @return If you handled the event, return true. If you want to allow the
   4181      *         event to be handled by the next receiver, return false.
   4182      */
   4183     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
   4184         return false;
   4185     }
   4186 
   4187     /**
   4188      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   4189      * KeyEvent.Callback.onKeyMultiple()}: perform press of the view
   4190      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
   4191      * is released, if the view is enabled and clickable.
   4192      *
   4193      * @param keyCode A key code that represents the button pressed, from
   4194      *                {@link android.view.KeyEvent}.
   4195      * @param event   The KeyEvent object that defines the button action.
   4196      */
   4197     public boolean onKeyDown(int keyCode, KeyEvent event) {
   4198         boolean result = false;
   4199 
   4200         switch (keyCode) {
   4201             case KeyEvent.KEYCODE_DPAD_CENTER:
   4202             case KeyEvent.KEYCODE_ENTER: {
   4203                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   4204                     return true;
   4205                 }
   4206                 // Long clickable items don't necessarily have to be clickable
   4207                 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
   4208                         (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
   4209                         (event.getRepeatCount() == 0)) {
   4210                     setPressed(true);
   4211                     if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
   4212                         postCheckForLongClick(0);
   4213                     }
   4214                     return true;
   4215                 }
   4216                 break;
   4217             }
   4218         }
   4219         return result;
   4220     }
   4221 
   4222     /**
   4223      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
   4224      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
   4225      * the event).
   4226      */
   4227     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
   4228         return false;
   4229     }
   4230 
   4231     /**
   4232      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   4233      * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view
   4234      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
   4235      * {@link KeyEvent#KEYCODE_ENTER} is released.
   4236      *
   4237      * @param keyCode A key code that represents the button pressed, from
   4238      *                {@link android.view.KeyEvent}.
   4239      * @param event   The KeyEvent object that defines the button action.
   4240      */
   4241     public boolean onKeyUp(int keyCode, KeyEvent event) {
   4242         boolean result = false;
   4243 
   4244         switch (keyCode) {
   4245             case KeyEvent.KEYCODE_DPAD_CENTER:
   4246             case KeyEvent.KEYCODE_ENTER: {
   4247                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   4248                     return true;
   4249                 }
   4250                 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
   4251                     setPressed(false);
   4252 
   4253                     if (!mHasPerformedLongPress) {
   4254                         // This is a tap, so remove the longpress check
   4255                         removeLongPressCallback();
   4256 
   4257                         result = performClick();
   4258                     }
   4259                 }
   4260                 break;
   4261             }
   4262         }
   4263         return result;
   4264     }
   4265 
   4266     /**
   4267      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   4268      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
   4269      * the event).
   4270      *
   4271      * @param keyCode     A key code that represents the button pressed, from
   4272      *                    {@link android.view.KeyEvent}.
   4273      * @param repeatCount The number of times the action was made.
   4274      * @param event       The KeyEvent object that defines the button action.
   4275      */
   4276     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
   4277         return false;
   4278     }
   4279 
   4280     /**
   4281      * Called when an unhandled key shortcut event occurs.
   4282      *
   4283      * @param keyCode The value in event.getKeyCode().
   4284      * @param event Description of the key event.
   4285      * @return If you handled the event, return true. If you want to allow the
   4286      *         event to be handled by the next receiver, return false.
   4287      */
   4288     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
   4289         return false;
   4290     }
   4291 
   4292     /**
   4293      * Check whether the called view is a text editor, in which case it
   4294      * would make sense to automatically display a soft input window for
   4295      * it.  Subclasses should override this if they implement
   4296      * {@link #onCreateInputConnection(EditorInfo)} to return true if
   4297      * a call on that method would return a non-null InputConnection, and
   4298      * they are really a first-class editor that the user would normally
   4299      * start typing on when the go into a window containing your view.
   4300      *
   4301      * <p>The default implementation always returns false.  This does
   4302      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
   4303      * will not be called or the user can not otherwise perform edits on your
   4304      * view; it is just a hint to the system that this is not the primary
   4305      * purpose of this view.
   4306      *
   4307      * @return Returns true if this view is a text editor, else false.
   4308      */
   4309     public boolean onCheckIsTextEditor() {
   4310         return false;
   4311     }
   4312 
   4313     /**
   4314      * Create a new InputConnection for an InputMethod to interact
   4315      * with the view.  The default implementation returns null, since it doesn't
   4316      * support input methods.  You can override this to implement such support.
   4317      * This is only needed for views that take focus and text input.
   4318      *
   4319      * <p>When implementing this, you probably also want to implement
   4320      * {@link #onCheckIsTextEditor()} to indicate you will return a
   4321      * non-null InputConnection.
   4322      *
   4323      * @param outAttrs Fill in with attribute information about the connection.
   4324      */
   4325     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   4326         return null;
   4327     }
   4328 
   4329     /**
   4330      * Called by the {@link android.view.inputmethod.InputMethodManager}
   4331      * when a view who is not the current
   4332      * input connection target is trying to make a call on the manager.  The
   4333      * default implementation returns false; you can override this to return
   4334      * true for certain views if you are performing InputConnection proxying
   4335      * to them.
   4336      * @param view The View that is making the InputMethodManager call.
   4337      * @return Return true to allow the call, false to reject.
   4338      */
   4339     public boolean checkInputConnectionProxy(View view) {
   4340         return false;
   4341     }
   4342 
   4343     /**
   4344      * Show the context menu for this view. It is not safe to hold on to the
   4345      * menu after returning from this method.
   4346      *
   4347      * You should normally not overload this method. Overload
   4348      * {@link #onCreateContextMenu(ContextMenu)} or define an
   4349      * {@link OnCreateContextMenuListener} to add items to the context menu.
   4350      *
   4351      * @param menu The context menu to populate
   4352      */
   4353     public void createContextMenu(ContextMenu menu) {
   4354         ContextMenuInfo menuInfo = getContextMenuInfo();
   4355 
   4356         // Sets the current menu info so all items added to menu will have
   4357         // my extra info set.
   4358         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
   4359 
   4360         onCreateContextMenu(menu);
   4361         if (mOnCreateContextMenuListener != null) {
   4362             mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
   4363         }
   4364 
   4365         // Clear the extra information so subsequent items that aren't mine don't
   4366         // have my extra info.
   4367         ((MenuBuilder)menu).setCurrentMenuInfo(null);
   4368 
   4369         if (mParent != null) {
   4370             mParent.createContextMenu(menu);
   4371         }
   4372     }
   4373 
   4374     /**
   4375      * Views should implement this if they have extra information to associate
   4376      * with the context menu. The return result is supplied as a parameter to
   4377      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
   4378      * callback.
   4379      *
   4380      * @return Extra information about the item for which the context menu
   4381      *         should be shown. This information will vary across different
   4382      *         subclasses of View.
   4383      */
   4384     protected ContextMenuInfo getContextMenuInfo() {
   4385         return null;
   4386     }
   4387 
   4388     /**
   4389      * Views should implement this if the view itself is going to add items to
   4390      * the context menu.
   4391      *
   4392      * @param menu the context menu to populate
   4393      */
   4394     protected void onCreateContextMenu(ContextMenu menu) {
   4395     }
   4396 
   4397     /**
   4398      * Implement this method to handle trackball motion events.  The
   4399      * <em>relative</em> movement of the trackball since the last event
   4400      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
   4401      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
   4402      * that a movement of 1 corresponds to the user pressing one DPAD key (so
   4403      * they will often be fractional values, representing the more fine-grained
   4404      * movement information available from a trackball).
   4405      *
   4406      * @param event The motion event.
   4407      * @return True if the event was handled, false otherwise.
   4408      */
   4409     public boolean onTrackballEvent(MotionEvent event) {
   4410         return false;
   4411     }
   4412 
   4413     /**
   4414      * Implement this method to handle touch screen motion events.
   4415      *
   4416      * @param event The motion event.
   4417      * @return True if the event was handled, false otherwise.
   4418      */
   4419     public boolean onTouchEvent(MotionEvent event) {
   4420         final int viewFlags = mViewFlags;
   4421 
   4422         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   4423             // A disabled view that is clickable still consumes the touch
   4424             // events, it just doesn't respond to them.
   4425             return (((viewFlags & CLICKABLE) == CLICKABLE ||
   4426                     (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
   4427         }
   4428 
   4429         if (mTouchDelegate != null) {
   4430             if (mTouchDelegate.onTouchEvent(event)) {
   4431                 return true;
   4432             }
   4433         }
   4434 
   4435         if (((viewFlags & CLICKABLE) == CLICKABLE ||
   4436                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
   4437             switch (event.getAction()) {
   4438                 case MotionEvent.ACTION_UP:
   4439                     boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
   4440                     if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
   4441                         // take focus if we don't have it already and we should in
   4442                         // touch mode.
   4443                         boolean focusTaken = false;
   4444                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
   4445                             focusTaken = requestFocus();
   4446                         }
   4447 
   4448                         if (!mHasPerformedLongPress) {
   4449                             // This is a tap, so remove the longpress check
   4450                             removeLongPressCallback();
   4451 
   4452                             // Only perform take click actions if we were in the pressed state
   4453                             if (!focusTaken) {
   4454                                 // Use a Runnable and post this rather than calling
   4455                                 // performClick directly. This lets other visual state
   4456                                 // of the view update before click actions start.
   4457                                 if (mPerformClick == null) {
   4458                                     mPerformClick = new PerformClick();
   4459                                 }
   4460                                 if (!post(mPerformClick)) {
   4461                                     performClick();
   4462                                 }
   4463                             }
   4464                         }
   4465 
   4466                         if (mUnsetPressedState == null) {
   4467                             mUnsetPressedState = new UnsetPressedState();
   4468                         }
   4469 
   4470                         if (prepressed) {
   4471                             mPrivateFlags |= PRESSED;
   4472                             refreshDrawableState();
   4473                             postDelayed(mUnsetPressedState,
   4474                                     ViewConfiguration.getPressedStateDuration());
   4475                         } else if (!post(mUnsetPressedState)) {
   4476                             // If the post failed, unpress right now
   4477                             mUnsetPressedState.run();
   4478                         }
   4479                         removeTapCallback();
   4480                     }
   4481                     break;
   4482 
   4483                 case MotionEvent.ACTION_DOWN:
   4484                     if (mPendingCheckForTap == null) {
   4485                         mPendingCheckForTap = new CheckForTap();
   4486                     }
   4487                     mPrivateFlags |= PREPRESSED;
   4488                     mHasPerformedLongPress = false;
   4489                     postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
   4490                     break;
   4491 
   4492                 case MotionEvent.ACTION_CANCEL:
   4493                     mPrivateFlags &= ~PRESSED;
   4494                     refreshDrawableState();
   4495                     removeTapCallback();
   4496                     break;
   4497 
   4498                 case MotionEvent.ACTION_MOVE:
   4499                     final int x = (int) event.getX();
   4500                     final int y = (int) event.getY();
   4501 
   4502                     // Be lenient about moving outside of buttons
   4503                     int slop = mTouchSlop;
   4504                     if ((x < 0 - slop) || (x >= getWidth() + slop) ||
   4505                             (y < 0 - slop) || (y >= getHeight() + slop)) {
   4506                         // Outside button
   4507                         removeTapCallback();
   4508                         if ((mPrivateFlags & PRESSED) != 0) {
   4509                             // Remove any future long press/tap checks
   4510                             removeLongPressCallback();
   4511 
   4512                             // Need to switch from pressed to not pressed
   4513                             mPrivateFlags &= ~PRESSED;
   4514                             refreshDrawableState();
   4515                         }
   4516                     }
   4517                     break;
   4518             }
   4519             return true;
   4520         }
   4521 
   4522         return false;
   4523     }
   4524 
   4525     /**
   4526      * Remove the longpress detection timer.
   4527      */
   4528     private void removeLongPressCallback() {
   4529         if (mPendingCheckForLongPress != null) {
   4530           removeCallbacks(mPendingCheckForLongPress);
   4531         }
   4532     }
   4533 
   4534     /**
   4535      * Remove the prepress detection timer.
   4536      */
   4537     private void removeUnsetPressCallback() {
   4538         if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
   4539             setPressed(false);
   4540             removeCallbacks(mUnsetPressedState);
   4541         }
   4542     }
   4543 
   4544     /**
   4545      * Remove the tap detection timer.
   4546      */
   4547     private void removeTapCallback() {
   4548         if (mPendingCheckForTap != null) {
   4549             mPrivateFlags &= ~PREPRESSED;
   4550             removeCallbacks(mPendingCheckForTap);
   4551         }
   4552     }
   4553 
   4554     /**
   4555      * Cancels a pending long press.  Your subclass can use this if you
   4556      * want the context menu to come up if the user presses and holds
   4557      * at the same place, but you don't want it to come up if they press
   4558      * and then move around enough to cause scrolling.
   4559      */
   4560     public void cancelLongPress() {
   4561         removeLongPressCallback();
   4562 
   4563         /*
   4564          * The prepressed state handled by the tap callback is a display
   4565          * construct, but the tap callback will post a long press callback
   4566          * less its own timeout. Remove it here.
   4567          */
   4568         removeTapCallback();
   4569     }
   4570 
   4571     /**
   4572      * Sets the TouchDelegate for this View.
   4573      */
   4574     public void setTouchDelegate(TouchDelegate delegate) {
   4575         mTouchDelegate = delegate;
   4576     }
   4577 
   4578     /**
   4579      * Gets the TouchDelegate for this View.
   4580      */
   4581     public TouchDelegate getTouchDelegate() {
   4582         return mTouchDelegate;
   4583     }
   4584 
   4585     /**
   4586      * Set flags controlling behavior of this view.
   4587      *
   4588      * @param flags Constant indicating the value which should be set
   4589      * @param mask Constant indicating the bit range that should be changed
   4590      */
   4591     void setFlags(int flags, int mask) {
   4592         int old = mViewFlags;
   4593         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
   4594 
   4595         int changed = mViewFlags ^ old;
   4596         if (changed == 0) {
   4597             return;
   4598         }
   4599         int privateFlags = mPrivateFlags;
   4600 
   4601         /* Check if the FOCUSABLE bit has changed */
   4602         if (((changed & FOCUSABLE_MASK) != 0) &&
   4603                 ((privateFlags & HAS_BOUNDS) !=0)) {
   4604             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
   4605                     && ((privateFlags & FOCUSED) != 0)) {
   4606                 /* Give up focus if we are no longer focusable */
   4607                 clearFocus();
   4608             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
   4609                     && ((privateFlags & FOCUSED) == 0)) {
   4610                 /*
   4611                  * Tell the view system that we are now available to take focus
   4612                  * if no one else already has it.
   4613                  */
   4614                 if (mParent != null) mParent.focusableViewAvailable(this);
   4615             }
   4616         }
   4617 
   4618         if ((flags & VISIBILITY_MASK) == VISIBLE) {
   4619             if ((changed & VISIBILITY_MASK) != 0) {
   4620                 /*
   4621                  * If this view is becoming visible, set the DRAWN flag so that
   4622                  * the next invalidate() will not be skipped.
   4623                  */
   4624                 mPrivateFlags |= DRAWN;
   4625 
   4626                 needGlobalAttributesUpdate(true);
   4627 
   4628                 // a view becoming visible is worth notifying the parent
   4629                 // about in case nothing has focus.  even if this specific view
   4630                 // isn't focusable, it may contain something that is, so let
   4631                 // the root view try to give this focus if nothing else does.
   4632                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
   4633                     mParent.focusableViewAvailable(this);
   4634                 }
   4635             }
   4636         }
   4637 
   4638         /* Check if the GONE bit has changed */
   4639         if ((changed & GONE) != 0) {
   4640             needGlobalAttributesUpdate(false);
   4641             requestLayout();
   4642             invalidate();
   4643 
   4644             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
   4645                 if (hasFocus()) clearFocus();
   4646                 destroyDrawingCache();
   4647             }
   4648             if (mAttachInfo != null) {
   4649                 mAttachInfo.mViewVisibilityChanged = true;
   4650             }
   4651         }
   4652 
   4653         /* Check if the VISIBLE bit has changed */
   4654         if ((changed & INVISIBLE) != 0) {
   4655             needGlobalAttributesUpdate(false);
   4656             invalidate();
   4657 
   4658             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
   4659                 // root view becoming invisible shouldn't clear focus
   4660                 if (getRootView() != this) {
   4661                     clearFocus();
   4662                 }
   4663             }
   4664             if (mAttachInfo != null) {
   4665                 mAttachInfo.mViewVisibilityChanged = true;
   4666             }
   4667         }
   4668 
   4669         if ((changed & VISIBILITY_MASK) != 0) {
   4670             dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
   4671         }
   4672 
   4673         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
   4674             destroyDrawingCache();
   4675         }
   4676 
   4677         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
   4678             destroyDrawingCache();
   4679             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   4680         }
   4681 
   4682         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
   4683             destroyDrawingCache();
   4684             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   4685         }
   4686 
   4687         if ((changed & DRAW_MASK) != 0) {
   4688             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
   4689                 if (mBGDrawable != null) {
   4690                     mPrivateFlags &= ~SKIP_DRAW;
   4691                     mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
   4692                 } else {
   4693                     mPrivateFlags |= SKIP_DRAW;
   4694                 }
   4695             } else {
   4696                 mPrivateFlags &= ~SKIP_DRAW;
   4697             }
   4698             requestLayout();
   4699             invalidate();
   4700         }
   4701 
   4702         if ((changed & KEEP_SCREEN_ON) != 0) {
   4703             if (mParent != null) {
   4704                 mParent.recomputeViewAttributes(this);
   4705             }
   4706         }
   4707     }
   4708 
   4709     /**
   4710      * Change the view's z order in the tree, so it's on top of other sibling
   4711      * views
   4712      */
   4713     public void bringToFront() {
   4714         if (mParent != null) {
   4715             mParent.bringChildToFront(this);
   4716         }
   4717     }
   4718 
   4719     /**
   4720      * This is called in response to an internal scroll in this view (i.e., the
   4721      * view scrolled its own contents). This is typically as a result of
   4722      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
   4723      * called.
   4724      *
   4725      * @param l Current horizontal scroll origin.
   4726      * @param t Current vertical scroll origin.
   4727      * @param oldl Previous horizontal scroll origin.
   4728      * @param oldt Previous vertical scroll origin.
   4729      */
   4730     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   4731         mBackgroundSizeChanged = true;
   4732 
   4733         final AttachInfo ai = mAttachInfo;
   4734         if (ai != null) {
   4735             ai.mViewScrollChanged = true;
   4736         }
   4737     }
   4738 
   4739     /**
   4740      * This is called during layout when the size of this view has changed. If
   4741      * you were just added to the view hierarchy, you're called with the old
   4742      * values of 0.
   4743      *
   4744      * @param w Current width of this view.
   4745      * @param h Current height of this view.
   4746      * @param oldw Old width of this view.
   4747      * @param oldh Old height of this view.
   4748      */
   4749     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   4750     }
   4751 
   4752     /**
   4753      * Called by draw to draw the child views. This may be overridden
   4754      * by derived classes to gain control just before its children are drawn
   4755      * (but after its own view has been drawn).
   4756      * @param canvas the canvas on which to draw the view
   4757      */
   4758     protected void dispatchDraw(Canvas canvas) {
   4759     }
   4760 
   4761     /**
   4762      * Gets the parent of this view. Note that the parent is a
   4763      * ViewParent and not necessarily a View.
   4764      *
   4765      * @return Parent of this view.
   4766      */
   4767     public final ViewParent getParent() {
   4768         return mParent;
   4769     }
   4770 
   4771     /**
   4772      * Return the scrolled left position of this view. This is the left edge of
   4773      * the displayed part of your view. You do not need to draw any pixels
   4774      * farther left, since those are outside of the frame of your view on
   4775      * screen.
   4776      *
   4777      * @return The left edge of the displayed part of your view, in pixels.
   4778      */
   4779     public final int getScrollX() {
   4780         return mScrollX;
   4781     }
   4782 
   4783     /**
   4784      * Return the scrolled top position of this view. This is the top edge of
   4785      * the displayed part of your view. You do not need to draw any pixels above
   4786      * it, since those are outside of the frame of your view on screen.
   4787      *
   4788      * @return The top edge of the displayed part of your view, in pixels.
   4789      */
   4790     public final int getScrollY() {
   4791         return mScrollY;
   4792     }
   4793 
   4794     /**
   4795      * Return the width of the your view.
   4796      *
   4797      * @return The width of your view, in pixels.
   4798      */
   4799     @ViewDebug.ExportedProperty(category = "layout")
   4800     public final int getWidth() {
   4801         return mRight - mLeft;
   4802     }
   4803 
   4804     /**
   4805      * Return the height of your view.
   4806      *
   4807      * @return The height of your view, in pixels.
   4808      */
   4809     @ViewDebug.ExportedProperty(category = "layout")
   4810     public final int getHeight() {
   4811         return mBottom - mTop;
   4812     }
   4813 
   4814     /**
   4815      * Return the visible drawing bounds of your view. Fills in the output
   4816      * rectangle with the values from getScrollX(), getScrollY(),
   4817      * getWidth(), and getHeight().
   4818      *
   4819      * @param outRect The (scrolled) drawing bounds of the view.
   4820      */
   4821     public void getDrawingRect(Rect outRect) {
   4822         outRect.left = mScrollX;
   4823         outRect.top = mScrollY;
   4824         outRect.right = mScrollX + (mRight - mLeft);
   4825         outRect.bottom = mScrollY + (mBottom - mTop);
   4826     }
   4827 
   4828     /**
   4829      * The width of this view as measured in the most recent call to measure().
   4830      * This should be used during measurement and layout calculations only. Use
   4831      * {@link #getWidth()} to see how wide a view is after layout.
   4832      *
   4833      * @return The measured width of this view.
   4834      */
   4835     public final int getMeasuredWidth() {
   4836         return mMeasuredWidth;
   4837     }
   4838 
   4839     /**
   4840      * The height of this view as measured in the most recent call to measure().
   4841      * This should be used during measurement and layout calculations only. Use
   4842      * {@link #getHeight()} to see how tall a view is after layout.
   4843      *
   4844      * @return The measured height of this view.
   4845      */
   4846     public final int getMeasuredHeight() {
   4847         return mMeasuredHeight;
   4848     }
   4849 
   4850     /**
   4851      * Top position of this view relative to its parent.
   4852      *
   4853      * @return The top of this view, in pixels.
   4854      */
   4855     @ViewDebug.CapturedViewProperty
   4856     public final int getTop() {
   4857         return mTop;
   4858     }
   4859 
   4860     /**
   4861      * Bottom position of this view relative to its parent.
   4862      *
   4863      * @return The bottom of this view, in pixels.
   4864      */
   4865     @ViewDebug.CapturedViewProperty
   4866     public final int getBottom() {
   4867         return mBottom;
   4868     }
   4869 
   4870     /**
   4871      * Left position of this view relative to its parent.
   4872      *
   4873      * @return The left edge of this view, in pixels.
   4874      */
   4875     @ViewDebug.CapturedViewProperty
   4876     public final int getLeft() {
   4877         return mLeft;
   4878     }
   4879 
   4880     /**
   4881      * Right position of this view relative to its parent.
   4882      *
   4883      * @return The right edge of this view, in pixels.
   4884      */
   4885     @ViewDebug.CapturedViewProperty
   4886     public final int getRight() {
   4887         return mRight;
   4888     }
   4889 
   4890     /**
   4891      * Hit rectangle in parent's coordinates
   4892      *
   4893      * @param outRect The hit rectangle of the view.
   4894      */
   4895     public void getHitRect(Rect outRect) {
   4896         outRect.set(mLeft, mTop, mRight, mBottom);
   4897     }
   4898 
   4899     /**
   4900      * When a view has focus and the user navigates away from it, the next view is searched for
   4901      * starting from the rectangle filled in by this method.
   4902      *
   4903      * By default, the rectange is the {@link #getDrawingRect})of the view.  However, if your
   4904      * view maintains some idea of internal selection, such as a cursor, or a selected row
   4905      * or column, you should override this method and fill in a more specific rectangle.
   4906      *
   4907      * @param r The rectangle to fill in, in this view's coordinates.
   4908      */
   4909     public void getFocusedRect(Rect r) {
   4910         getDrawingRect(r);
   4911     }
   4912 
   4913     /**
   4914      * If some part of this view is not clipped by any of its parents, then
   4915      * return that area in r in global (root) coordinates. To convert r to local
   4916      * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x,
   4917      * -globalOffset.y)) If the view is completely clipped or translated out,
   4918      * return false.
   4919      *
   4920      * @param r If true is returned, r holds the global coordinates of the
   4921      *        visible portion of this view.
   4922      * @param globalOffset If true is returned, globalOffset holds the dx,dy
   4923      *        between this view and its root. globalOffet may be null.
   4924      * @return true if r is non-empty (i.e. part of the view is visible at the
   4925      *         root level.
   4926      */
   4927     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
   4928         int width = mRight - mLeft;
   4929         int height = mBottom - mTop;
   4930         if (width > 0 && height > 0) {
   4931             r.set(0, 0, width, height);
   4932             if (globalOffset != null) {
   4933                 globalOffset.set(-mScrollX, -mScrollY);
   4934             }
   4935             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
   4936         }
   4937         return false;
   4938     }
   4939 
   4940     public final boolean getGlobalVisibleRect(Rect r) {
   4941         return getGlobalVisibleRect(r, null);
   4942     }
   4943 
   4944     public final boolean getLocalVisibleRect(Rect r) {
   4945         Point offset = new Point();
   4946         if (getGlobalVisibleRect(r, offset)) {
   4947             r.offset(-offset.x, -offset.y); // make r local
   4948             return true;
   4949         }
   4950         return false;
   4951     }
   4952 
   4953     /**
   4954      * Offset this view's vertical location by the specified number of pixels.
   4955      *
   4956      * @param offset the number of pixels to offset the view by
   4957      */
   4958     public void offsetTopAndBottom(int offset) {
   4959         mTop += offset;
   4960         mBottom += offset;
   4961     }
   4962 
   4963     /**
   4964      * Offset this view's horizontal location by the specified amount of pixels.
   4965      *
   4966      * @param offset the numer of pixels to offset the view by
   4967      */
   4968     public void offsetLeftAndRight(int offset) {
   4969         mLeft += offset;
   4970         mRight += offset;
   4971     }
   4972 
   4973     /**
   4974      * Get the LayoutParams associated with this view. All views should have
   4975      * layout parameters. These supply parameters to the <i>parent</i> of this
   4976      * view specifying how it should be arranged. There are many subclasses of
   4977      * ViewGroup.LayoutParams, and these correspond to the different subclasses
   4978      * of ViewGroup that are responsible for arranging their children.
   4979      * @return The LayoutParams associated with this view
   4980      */
   4981     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
   4982     public ViewGroup.LayoutParams getLayoutParams() {
   4983         return mLayoutParams;
   4984     }
   4985 
   4986     /**
   4987      * Set the layout parameters associated with this view. These supply
   4988      * parameters to the <i>parent</i> of this view specifying how it should be
   4989      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
   4990      * correspond to the different subclasses of ViewGroup that are responsible
   4991      * for arranging their children.
   4992      *
   4993      * @param params the layout parameters for this view
   4994      */
   4995     public void setLayoutParams(ViewGroup.LayoutParams params) {
   4996         if (params == null) {
   4997             throw new NullPointerException("params == null");
   4998         }
   4999         mLayoutParams = params;
   5000         requestLayout();
   5001     }
   5002 
   5003     /**
   5004      * Set the scrolled position of your view. This will cause a call to
   5005      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   5006      * invalidated.
   5007      * @param x the x position to scroll to
   5008      * @param y the y position to scroll to
   5009      */
   5010     public void scrollTo(int x, int y) {
   5011         if (mScrollX != x || mScrollY != y) {
   5012             int oldX = mScrollX;
   5013             int oldY = mScrollY;
   5014             mScrollX = x;
   5015             mScrollY = y;
   5016             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
   5017             if (!awakenScrollBars()) {
   5018                 invalidate();
   5019             }
   5020         }
   5021     }
   5022 
   5023     /**
   5024      * Move the scrolled position of your view. This will cause a call to
   5025      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   5026      * invalidated.
   5027      * @param x the amount of pixels to scroll by horizontally
   5028      * @param y the amount of pixels to scroll by vertically
   5029      */
   5030     public void scrollBy(int x, int y) {
   5031         scrollTo(mScrollX + x, mScrollY + y);
   5032     }
   5033 
   5034     /**
   5035      * <p>Trigger the scrollbars to draw. When invoked this method starts an
   5036      * animation to fade the scrollbars out after a default delay. If a subclass
   5037      * provides animated scrolling, the start delay should equal the duration
   5038      * of the scrolling animation.</p>
   5039      *
   5040      * <p>The animation starts only if at least one of the scrollbars is
   5041      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
   5042      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   5043      * this method returns true, and false otherwise. If the animation is
   5044      * started, this method calls {@link #invalidate()}; in that case the
   5045      * caller should not call {@link #invalidate()}.</p>
   5046      *
   5047      * <p>This method should be invoked every time a subclass directly updates
   5048      * the scroll parameters.</p>
   5049      *
   5050      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
   5051      * and {@link #scrollTo(int, int)}.</p>
   5052      *
   5053      * @return true if the animation is played, false otherwise
   5054      *
   5055      * @see #awakenScrollBars(int)
   5056      * @see #scrollBy(int, int)
   5057      * @see #scrollTo(int, int)
   5058      * @see #isHorizontalScrollBarEnabled()
   5059      * @see #isVerticalScrollBarEnabled()
   5060      * @see #setHorizontalScrollBarEnabled(boolean)
   5061      * @see #setVerticalScrollBarEnabled(boolean)
   5062      */
   5063     protected boolean awakenScrollBars() {
   5064         return mScrollCache != null &&
   5065                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
   5066     }
   5067 
   5068     /**
   5069      * Trigger the scrollbars to draw.
   5070      * This method differs from awakenScrollBars() only in its default duration.
   5071      * initialAwakenScrollBars() will show the scroll bars for longer than
   5072      * usual to give the user more of a chance to notice them.
   5073      *
   5074      * @return true if the animation is played, false otherwise.
   5075      */
   5076     private boolean initialAwakenScrollBars() {
   5077         return mScrollCache != null &&
   5078                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
   5079     }
   5080 
   5081     /**
   5082      * <p>
   5083      * Trigger the scrollbars to draw. When invoked this method starts an
   5084      * animation to fade the scrollbars out after a fixed delay. If a subclass
   5085      * provides animated scrolling, the start delay should equal the duration of
   5086      * the scrolling animation.
   5087      * </p>
   5088      *
   5089      * <p>
   5090      * The animation starts only if at least one of the scrollbars is enabled,
   5091      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   5092      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   5093      * this method returns true, and false otherwise. If the animation is
   5094      * started, this method calls {@link #invalidate()}; in that case the caller
   5095      * should not call {@link #invalidate()}.
   5096      * </p>
   5097      *
   5098      * <p>
   5099      * This method should be invoked everytime a subclass directly updates the
   5100      * scroll parameters.
   5101      * </p>
   5102      *
   5103      * @param startDelay the delay, in milliseconds, after which the animation
   5104      *        should start; when the delay is 0, the animation starts
   5105      *        immediately
   5106      * @return true if the animation is played, false otherwise
   5107      *
   5108      * @see #scrollBy(int, int)
   5109      * @see #scrollTo(int, int)
   5110      * @see #isHorizontalScrollBarEnabled()
   5111      * @see #isVerticalScrollBarEnabled()
   5112      * @see #setHorizontalScrollBarEnabled(boolean)
   5113      * @see #setVerticalScrollBarEnabled(boolean)
   5114      */
   5115     protected boolean awakenScrollBars(int startDelay) {
   5116         return awakenScrollBars(startDelay, true);
   5117     }
   5118 
   5119     /**
   5120      * <p>
   5121      * Trigger the scrollbars to draw. When invoked this method starts an
   5122      * animation to fade the scrollbars out after a fixed delay. If a subclass
   5123      * provides animated scrolling, the start delay should equal the duration of
   5124      * the scrolling animation.
   5125      * </p>
   5126      *
   5127      * <p>
   5128      * The animation starts only if at least one of the scrollbars is enabled,
   5129      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   5130      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   5131      * this method returns true, and false otherwise. If the animation is
   5132      * started, this method calls {@link #invalidate()} if the invalidate parameter
   5133      * is set to true; in that case the caller
   5134      * should not call {@link #invalidate()}.
   5135      * </p>
   5136      *
   5137      * <p>
   5138      * This method should be invoked everytime a subclass directly updates the
   5139      * scroll parameters.
   5140      * </p>
   5141      *
   5142      * @param startDelay the delay, in milliseconds, after which the animation
   5143      *        should start; when the delay is 0, the animation starts
   5144      *        immediately
   5145      *
   5146      * @param invalidate Wheter this method should call invalidate
   5147      *
   5148      * @return true if the animation is played, false otherwise
   5149      *
   5150      * @see #scrollBy(int, int)
   5151      * @see #scrollTo(int, int)
   5152      * @see #isHorizontalScrollBarEnabled()
   5153      * @see #isVerticalScrollBarEnabled()
   5154      * @see #setHorizontalScrollBarEnabled(boolean)
   5155      * @see #setVerticalScrollBarEnabled(boolean)
   5156      */
   5157     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
   5158         final ScrollabilityCache scrollCache = mScrollCache;
   5159 
   5160         if (scrollCache == null || !scrollCache.fadeScrollBars) {
   5161             return false;
   5162         }
   5163 
   5164         if (scrollCache.scrollBar == null) {
   5165             scrollCache.scrollBar = new ScrollBarDrawable();
   5166         }
   5167 
   5168         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
   5169 
   5170             if (invalidate) {
   5171                 // Invalidate to show the scrollbars
   5172                 invalidate();
   5173             }
   5174 
   5175             if (scrollCache.state == ScrollabilityCache.OFF) {
   5176                 // FIXME: this is copied from WindowManagerService.
   5177                 // We should get this value from the system when it
   5178                 // is possible to do so.
   5179                 final int KEY_REPEAT_FIRST_DELAY = 750;
   5180                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
   5181             }
   5182 
   5183             // Tell mScrollCache when we should start fading. This may
   5184             // extend the fade start time if one was already scheduled
   5185             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
   5186             scrollCache.fadeStartTime = fadeStartTime;
   5187             scrollCache.state = ScrollabilityCache.ON;
   5188 
   5189             // Schedule our fader to run, unscheduling any old ones first
   5190             if (mAttachInfo != null) {
   5191                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
   5192                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
   5193             }
   5194 
   5195             return true;
   5196         }
   5197 
   5198         return false;
   5199     }
   5200 
   5201     /**
   5202      * Mark the the area defined by dirty as needing to be drawn. If the view is
   5203      * visible, {@link #onDraw} will be called at some point in the future.
   5204      * This must be called from a UI thread. To call from a non-UI thread, call
   5205      * {@link #postInvalidate()}.
   5206      *
   5207      * WARNING: This method is destructive to dirty.
   5208      * @param dirty the rectangle representing the bounds of the dirty region
   5209      */
   5210     public void invalidate(Rect dirty) {
   5211         if (ViewDebug.TRACE_HIERARCHY) {
   5212             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
   5213         }
   5214 
   5215         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
   5216             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   5217             final ViewParent p = mParent;
   5218             final AttachInfo ai = mAttachInfo;
   5219             if (p != null && ai != null) {
   5220                 final int scrollX = mScrollX;
   5221                 final int scrollY = mScrollY;
   5222                 final Rect r = ai.mTmpInvalRect;
   5223                 r.set(dirty.left - scrollX, dirty.top - scrollY,
   5224                         dirty.right - scrollX, dirty.bottom - scrollY);
   5225                 mParent.invalidateChild(this, r);
   5226             }
   5227         }
   5228     }
   5229 
   5230     /**
   5231      * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn.
   5232      * The coordinates of the dirty rect are relative to the view.
   5233      * If the view is visible, {@link #onDraw} will be called at some point
   5234      * in the future. This must be called from a UI thread. To call
   5235      * from a non-UI thread, call {@link #postInvalidate()}.
   5236      * @param l the left position of the dirty region
   5237      * @param t the top position of the dirty region
   5238      * @param r the right position of the dirty region
   5239      * @param b the bottom position of the dirty region
   5240      */
   5241     public void invalidate(int l, int t, int r, int b) {
   5242         if (ViewDebug.TRACE_HIERARCHY) {
   5243             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
   5244         }
   5245 
   5246         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
   5247             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   5248             final ViewParent p = mParent;
   5249             final AttachInfo ai = mAttachInfo;
   5250             if (p != null && ai != null && l < r && t < b) {
   5251                 final int scrollX = mScrollX;
   5252                 final int scrollY = mScrollY;
   5253                 final Rect tmpr = ai.mTmpInvalRect;
   5254                 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
   5255                 p.invalidateChild(this, tmpr);
   5256             }
   5257         }
   5258     }
   5259 
   5260     /**
   5261      * Invalidate the whole view. If the view is visible, {@link #onDraw} will
   5262      * be called at some point in the future. This must be called from a
   5263      * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
   5264      */
   5265     public void invalidate() {
   5266         if (ViewDebug.TRACE_HIERARCHY) {
   5267             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
   5268         }
   5269 
   5270         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
   5271             mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
   5272             final ViewParent p = mParent;
   5273             final AttachInfo ai = mAttachInfo;
   5274             if (p != null && ai != null) {
   5275                 final Rect r = ai.mTmpInvalRect;
   5276                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
   5277                 // Don't call invalidate -- we don't want to internally scroll
   5278                 // our own bounds
   5279                 p.invalidateChild(this, r);
   5280             }
   5281         }
   5282     }
   5283 
   5284     /**
   5285      * Indicates whether this View is opaque. An opaque View guarantees that it will
   5286      * draw all the pixels overlapping its bounds using a fully opaque color.
   5287      *
   5288      * Subclasses of View should override this method whenever possible to indicate
   5289      * whether an instance is opaque. Opaque Views are treated in a special way by
   5290      * the View hierarchy, possibly allowing it to perform optimizations during
   5291      * invalidate/draw passes.
   5292      *
   5293      * @return True if this View is guaranteed to be fully opaque, false otherwise.
   5294      */
   5295     @ViewDebug.ExportedProperty(category = "drawing")
   5296     public boolean isOpaque() {
   5297         return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK;
   5298     }
   5299 
   5300     private void computeOpaqueFlags() {
   5301         // Opaque if:
   5302         //   - Has a background
   5303         //   - Background is opaque
   5304         //   - Doesn't have scrollbars or scrollbars are inside overlay
   5305 
   5306         if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
   5307             mPrivateFlags |= OPAQUE_BACKGROUND;
   5308         } else {
   5309             mPrivateFlags &= ~OPAQUE_BACKGROUND;
   5310         }
   5311 
   5312         final int flags = mViewFlags;
   5313         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
   5314                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
   5315             mPrivateFlags |= OPAQUE_SCROLLBARS;
   5316         } else {
   5317             mPrivateFlags &= ~OPAQUE_SCROLLBARS;
   5318         }
   5319     }
   5320 
   5321     /**
   5322      * @hide
   5323      */
   5324     protected boolean hasOpaqueScrollbars() {
   5325         return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
   5326     }
   5327 
   5328     /**
   5329      * @return A handler associated with the thread running the View. This
   5330      * handler can be used to pump events in the UI events queue.
   5331      */
   5332     public Handler getHandler() {
   5333         if (mAttachInfo != null) {
   5334             return mAttachInfo.mHandler;
   5335         }
   5336         return null;
   5337     }
   5338 
   5339     /**
   5340      * Causes the Runnable to be added to the message queue.
   5341      * The runnable will be run on the user interface thread.
   5342      *
   5343      * @param action The Runnable that will be executed.
   5344      *
   5345      * @return Returns true if the Runnable was successfully placed in to the
   5346      *         message queue.  Returns false on failure, usually because the
   5347      *         looper processing the message queue is exiting.
   5348      */
   5349     public boolean post(Runnable action) {
   5350         Handler handler;
   5351         if (mAttachInfo != null) {
   5352             handler = mAttachInfo.mHandler;
   5353         } else {
   5354             // Assume that post will succeed later
   5355             ViewRoot.getRunQueue().post(action);
   5356             return true;
   5357         }
   5358 
   5359         return handler.post(action);
   5360     }
   5361 
   5362     /**
   5363      * Causes the Runnable to be added to the message queue, to be run
   5364      * after the specified amount of time elapses.
   5365      * The runnable will be run on the user interface thread.
   5366      *
   5367      * @param action The Runnable that will be executed.
   5368      * @param delayMillis The delay (in milliseconds) until the Runnable
   5369      *        will be executed.
   5370      *
   5371      * @return true if the Runnable was successfully placed in to the
   5372      *         message queue.  Returns false on failure, usually because the
   5373      *         looper processing the message queue is exiting.  Note that a
   5374      *         result of true does not mean the Runnable will be processed --
   5375      *         if the looper is quit before the delivery time of the message
   5376      *         occurs then the message will be dropped.
   5377      */
   5378     public boolean postDelayed(Runnable action, long delayMillis) {
   5379         Handler handler;
   5380         if (mAttachInfo != null) {
   5381             handler = mAttachInfo.mHandler;
   5382         } else {
   5383             // Assume that post will succeed later
   5384             ViewRoot.getRunQueue().postDelayed(action, delayMillis);
   5385             return true;
   5386         }
   5387 
   5388         return handler.postDelayed(action, delayMillis);
   5389     }
   5390 
   5391     /**
   5392      * Removes the specified Runnable from the message queue.
   5393      *
   5394      * @param action The Runnable to remove from the message handling queue
   5395      *
   5396      * @return true if this view could ask the Handler to remove the Runnable,
   5397      *         false otherwise. When the returned value is true, the Runnable
   5398      *         may or may not have been actually removed from the message queue
   5399      *         (for instance, if the Runnable was not in the queue already.)
   5400      */
   5401     public boolean removeCallbacks(Runnable action) {
   5402         Handler handler;
   5403         if (mAttachInfo != null) {
   5404             handler = mAttachInfo.mHandler;
   5405         } else {
   5406             // Assume that post will succeed later
   5407             ViewRoot.getRunQueue().removeCallbacks(action);
   5408             return true;
   5409         }
   5410 
   5411         handler.removeCallbacks(action);
   5412         return true;
   5413     }
   5414 
   5415     /**
   5416      * Cause an invalidate to happen on a subsequent cycle through the event loop.
   5417      * Use this to invalidate the View from a non-UI thread.
   5418      *
   5419      * @see #invalidate()
   5420      */
   5421     public void postInvalidate() {
   5422         postInvalidateDelayed(0);
   5423     }
   5424 
   5425     /**
   5426      * Cause an invalidate of the specified area to happen on a subsequent cycle
   5427      * through the event loop. Use this to invalidate the View from a non-UI thread.
   5428      *
   5429      * @param left The left coordinate of the rectangle to invalidate.
   5430      * @param top The top coordinate of the rectangle to invalidate.
   5431      * @param right The right coordinate of the rectangle to invalidate.
   5432      * @param bottom The bottom coordinate of the rectangle to invalidate.
   5433      *
   5434      * @see #invalidate(int, int, int, int)
   5435      * @see #invalidate(Rect)
   5436      */
   5437     public void postInvalidate(int left, int top, int right, int bottom) {
   5438         postInvalidateDelayed(0, left, top, right, bottom);
   5439     }
   5440 
   5441     /**
   5442      * Cause an invalidate to happen on a subsequent cycle through the event
   5443      * loop. Waits for the specified amount of time.
   5444      *
   5445      * @param delayMilliseconds the duration in milliseconds to delay the
   5446      *         invalidation by
   5447      */
   5448     public void postInvalidateDelayed(long delayMilliseconds) {
   5449         // We try only with the AttachInfo because there's no point in invalidating
   5450         // if we are not attached to our window
   5451         if (mAttachInfo != null) {
   5452             Message msg = Message.obtain();
   5453             msg.what = AttachInfo.INVALIDATE_MSG;
   5454             msg.obj = this;
   5455             mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
   5456         }
   5457     }
   5458 
   5459     /**
   5460      * Cause an invalidate of the specified area to happen on a subsequent cycle
   5461      * through the event loop. Waits for the specified amount of time.
   5462      *
   5463      * @param delayMilliseconds the duration in milliseconds to delay the
   5464      *         invalidation by
   5465      * @param left The left coordinate of the rectangle to invalidate.
   5466      * @param top The top coordinate of the rectangle to invalidate.
   5467      * @param right The right coordinate of the rectangle to invalidate.
   5468      * @param bottom The bottom coordinate of the rectangle to invalidate.
   5469      */
   5470     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
   5471             int right, int bottom) {
   5472 
   5473         // We try only with the AttachInfo because there's no point in invalidating
   5474         // if we are not attached to our window
   5475         if (mAttachInfo != null) {
   5476             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
   5477             info.target = this;
   5478             info.left = left;
   5479             info.top = top;
   5480             info.right = right;
   5481             info.bottom = bottom;
   5482 
   5483             final Message msg = Message.obtain();
   5484             msg.what = AttachInfo.INVALIDATE_RECT_MSG;
   5485             msg.obj = info;
   5486             mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
   5487         }
   5488     }
   5489 
   5490     /**
   5491      * Called by a parent to request that a child update its values for mScrollX
   5492      * and mScrollY if necessary. This will typically be done if the child is
   5493      * animating a scroll using a {@link android.widget.Scroller Scroller}
   5494      * object.
   5495      */
   5496     public void computeScroll() {
   5497     }
   5498 
   5499     /**
   5500      * <p>Indicate whether the horizontal edges are faded when the view is
   5501      * scrolled horizontally.</p>
   5502      *
   5503      * @return true if the horizontal edges should are faded on scroll, false
   5504      *         otherwise
   5505      *
   5506      * @see #setHorizontalFadingEdgeEnabled(boolean)
   5507      * @attr ref android.R.styleable#View_fadingEdge
   5508      */
   5509     public boolean isHorizontalFadingEdgeEnabled() {
   5510         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
   5511     }
   5512 
   5513     /**
   5514      * <p>Define whether the horizontal edges should be faded when this view
   5515      * is scrolled horizontally.</p>
   5516      *
   5517      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
   5518      *                                    be faded when the view is scrolled
   5519      *                                    horizontally
   5520      *
   5521      * @see #isHorizontalFadingEdgeEnabled()
   5522      * @attr ref android.R.styleable#View_fadingEdge
   5523      */
   5524     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
   5525         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
   5526             if (horizontalFadingEdgeEnabled) {
   5527                 initScrollCache();
   5528             }
   5529 
   5530             mViewFlags ^= FADING_EDGE_HORIZONTAL;
   5531         }
   5532     }
   5533 
   5534     /**
   5535      * <p>Indicate whether the vertical edges are faded when the view is
   5536      * scrolled horizontally.</p>
   5537      *
   5538      * @return true if the vertical edges should are faded on scroll, false
   5539      *         otherwise
   5540      *
   5541      * @see #setVerticalFadingEdgeEnabled(boolean)
   5542      * @attr ref android.R.styleable#View_fadingEdge
   5543      */
   5544     public boolean isVerticalFadingEdgeEnabled() {
   5545         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
   5546     }
   5547 
   5548     /**
   5549      * <p>Define whether the vertical edges should be faded when this view
   5550      * is scrolled vertically.</p>
   5551      *
   5552      * @param verticalFadingEdgeEnabled true if the vertical edges should
   5553      *                                  be faded when the view is scrolled
   5554      *                                  vertically
   5555      *
   5556      * @see #isVerticalFadingEdgeEnabled()
   5557      * @attr ref android.R.styleable#View_fadingEdge
   5558      */
   5559     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
   5560         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
   5561             if (verticalFadingEdgeEnabled) {
   5562                 initScrollCache();
   5563             }
   5564 
   5565             mViewFlags ^= FADING_EDGE_VERTICAL;
   5566         }
   5567     }
   5568 
   5569     /**
   5570      * Returns the strength, or intensity, of the top faded edge. The strength is
   5571      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   5572      * returns 0.0 or 1.0 but no value in between.
   5573      *
   5574      * Subclasses should override this method to provide a smoother fade transition
   5575      * when scrolling occurs.
   5576      *
   5577      * @return the intensity of the top fade as a float between 0.0f and 1.0f
   5578      */
   5579     protected float getTopFadingEdgeStrength() {
   5580         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
   5581     }
   5582 
   5583     /**
   5584      * Returns the strength, or intensity, of the bottom faded edge. The strength is
   5585      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   5586      * returns 0.0 or 1.0 but no value in between.
   5587      *
   5588      * Subclasses should override this method to provide a smoother fade transition
   5589      * when scrolling occurs.
   5590      *
   5591      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
   5592      */
   5593     protected float getBottomFadingEdgeStrength() {
   5594         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
   5595                 computeVerticalScrollRange() ? 1.0f : 0.0f;
   5596     }
   5597 
   5598     /**
   5599      * Returns the strength, or intensity, of the left faded edge. The strength is
   5600      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   5601      * returns 0.0 or 1.0 but no value in between.
   5602      *
   5603      * Subclasses should override this method to provide a smoother fade transition
   5604      * when scrolling occurs.
   5605      *
   5606      * @return the intensity of the left fade as a float between 0.0f and 1.0f
   5607      */
   5608     protected float getLeftFadingEdgeStrength() {
   5609         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
   5610     }
   5611 
   5612     /**
   5613      * Returns the strength, or intensity, of the right faded edge. The strength is
   5614      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   5615      * returns 0.0 or 1.0 but no value in between.
   5616      *
   5617      * Subclasses should override this method to provide a smoother fade transition
   5618      * when scrolling occurs.
   5619      *
   5620      * @return the intensity of the right fade as a float between 0.0f and 1.0f
   5621      */
   5622     protected float getRightFadingEdgeStrength() {
   5623         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
   5624                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
   5625     }
   5626 
   5627     /**
   5628      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
   5629      * scrollbar is not drawn by default.</p>
   5630      *
   5631      * @return true if the horizontal scrollbar should be painted, false
   5632      *         otherwise
   5633      *
   5634      * @see #setHorizontalScrollBarEnabled(boolean)
   5635      */
   5636     public boolean isHorizontalScrollBarEnabled() {
   5637         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   5638     }
   5639 
   5640     /**
   5641      * <p>Define whether the horizontal scrollbar should be drawn or not. The
   5642      * scrollbar is not drawn by default.</p>
   5643      *
   5644      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
   5645      *                                   be painted
   5646      *
   5647      * @see #isHorizontalScrollBarEnabled()
   5648      */
   5649     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
   5650         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
   5651             mViewFlags ^= SCROLLBARS_HORIZONTAL;
   5652             computeOpaqueFlags();
   5653             recomputePadding();
   5654         }
   5655     }
   5656 
   5657     /**
   5658      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
   5659      * scrollbar is not drawn by default.</p>
   5660      *
   5661      * @return true if the vertical scrollbar should be painted, false
   5662      *         otherwise
   5663      *
   5664      * @see #setVerticalScrollBarEnabled(boolean)
   5665      */
   5666     public boolean isVerticalScrollBarEnabled() {
   5667         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
   5668     }
   5669 
   5670     /**
   5671      * <p>Define whether the vertical scrollbar should be drawn or not. The
   5672      * scrollbar is not drawn by default.</p>
   5673      *
   5674      * @param verticalScrollBarEnabled true if the vertical scrollbar should
   5675      *                                 be painted
   5676      *
   5677      * @see #isVerticalScrollBarEnabled()
   5678      */
   5679     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
   5680         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
   5681             mViewFlags ^= SCROLLBARS_VERTICAL;
   5682             computeOpaqueFlags();
   5683             recomputePadding();
   5684         }
   5685     }
   5686 
   5687     private void recomputePadding() {
   5688         setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   5689     }
   5690 
   5691     /**
   5692      * Define whether scrollbars will fade when the view is not scrolling.
   5693      *
   5694      * @param fadeScrollbars wheter to enable fading
   5695      *
   5696      */
   5697     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
   5698         initScrollCache();
   5699         final ScrollabilityCache scrollabilityCache = mScrollCache;
   5700         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   5701         if (fadeScrollbars) {
   5702             scrollabilityCache.state = ScrollabilityCache.OFF;
   5703         } else {
   5704             scrollabilityCache.state = ScrollabilityCache.ON;
   5705         }
   5706     }
   5707 
   5708     /**
   5709      *
   5710      * Returns true if scrollbars will fade when this view is not scrolling
   5711      *
   5712      * @return true if scrollbar fading is enabled
   5713      */
   5714     public boolean isScrollbarFadingEnabled() {
   5715         return mScrollCache != null && mScrollCache.fadeScrollBars;
   5716     }
   5717 
   5718     /**
   5719      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
   5720      * inset. When inset, they add to the padding of the view. And the scrollbars
   5721      * can be drawn inside the padding area or on the edge of the view. For example,
   5722      * if a view has a background drawable and you want to draw the scrollbars
   5723      * inside the padding specified by the drawable, you can use
   5724      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
   5725      * appear at the edge of the view, ignoring the padding, then you can use
   5726      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
   5727      * @param style the style of the scrollbars. Should be one of
   5728      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
   5729      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
   5730      * @see #SCROLLBARS_INSIDE_OVERLAY
   5731      * @see #SCROLLBARS_INSIDE_INSET
   5732      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   5733      * @see #SCROLLBARS_OUTSIDE_INSET
   5734      */
   5735     public void setScrollBarStyle(int style) {
   5736         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
   5737             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
   5738             computeOpaqueFlags();
   5739             recomputePadding();
   5740         }
   5741     }
   5742 
   5743     /**
   5744      * <p>Returns the current scrollbar style.</p>
   5745      * @return the current scrollbar style
   5746      * @see #SCROLLBARS_INSIDE_OVERLAY
   5747      * @see #SCROLLBARS_INSIDE_INSET
   5748      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   5749      * @see #SCROLLBARS_OUTSIDE_INSET
   5750      */
   5751     public int getScrollBarStyle() {
   5752         return mViewFlags & SCROLLBARS_STYLE_MASK;
   5753     }
   5754 
   5755     /**
   5756      * <p>Compute the horizontal range that the horizontal scrollbar
   5757      * represents.</p>
   5758      *
   5759      * <p>The range is expressed in arbitrary units that must be the same as the
   5760      * units used by {@link #computeHorizontalScrollExtent()} and
   5761      * {@link #computeHorizontalScrollOffset()}.</p>
   5762      *
   5763      * <p>The default range is the drawing width of this view.</p>
   5764      *
   5765      * @return the total horizontal range represented by the horizontal
   5766      *         scrollbar
   5767      *
   5768      * @see #computeHorizontalScrollExtent()
   5769      * @see #computeHorizontalScrollOffset()
   5770      * @see android.widget.ScrollBarDrawable
   5771      */
   5772     protected int computeHorizontalScrollRange() {
   5773         return getWidth();
   5774     }
   5775 
   5776     /**
   5777      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
   5778      * within the horizontal range. This value is used to compute the position
   5779      * of the thumb within the scrollbar's track.</p>
   5780      *
   5781      * <p>The range is expressed in arbitrary units that must be the same as the
   5782      * units used by {@link #computeHorizontalScrollRange()} and
   5783      * {@link #computeHorizontalScrollExtent()}.</p>
   5784      *
   5785      * <p>The default offset is the scroll offset of this view.</p>
   5786      *
   5787      * @return the horizontal offset of the scrollbar's thumb
   5788      *
   5789      * @see #computeHorizontalScrollRange()
   5790      * @see #computeHorizontalScrollExtent()
   5791      * @see android.widget.ScrollBarDrawable
   5792      */
   5793     protected int computeHorizontalScrollOffset() {
   5794         return mScrollX;
   5795     }
   5796 
   5797     /**
   5798      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
   5799      * within the horizontal range. This value is used to compute the length
   5800      * of the thumb within the scrollbar's track.</p>
   5801      *
   5802      * <p>The range is expressed in arbitrary units that must be the same as the
   5803      * units used by {@link #computeHorizontalScrollRange()} and
   5804      * {@link #computeHorizontalScrollOffset()}.</p>
   5805      *
   5806      * <p>The default extent is the drawing width of this view.</p>
   5807      *
   5808      * @return the horizontal extent of the scrollbar's thumb
   5809      *
   5810      * @see #computeHorizontalScrollRange()
   5811      * @see #computeHorizontalScrollOffset()
   5812      * @see android.widget.ScrollBarDrawable
   5813      */
   5814     protected int computeHorizontalScrollExtent() {
   5815         return getWidth();
   5816     }
   5817 
   5818     /**
   5819      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
   5820      *
   5821      * <p>The range is expressed in arbitrary units that must be the same as the
   5822      * units used by {@link #computeVerticalScrollExtent()} and
   5823      * {@link #computeVerticalScrollOffset()}.</p>
   5824      *
   5825      * @return the total vertical range represented by the vertical scrollbar
   5826      *
   5827      * <p>The default range is the drawing height of this view.</p>
   5828      *
   5829      * @see #computeVerticalScrollExtent()
   5830      * @see #computeVerticalScrollOffset()
   5831      * @see android.widget.ScrollBarDrawable
   5832      */
   5833     protected int computeVerticalScrollRange() {
   5834         return getHeight();
   5835     }
   5836 
   5837     /**
   5838      * <p>Compute the vertical offset of the vertical scrollbar's thumb
   5839      * within the horizontal range. This value is used to compute the position
   5840      * of the thumb within the scrollbar's track.</p>
   5841      *
   5842      * <p>The range is expressed in arbitrary units that must be the same as the
   5843      * units used by {@link #computeVerticalScrollRange()} and
   5844      * {@link #computeVerticalScrollExtent()}.</p>
   5845      *
   5846      * <p>The default offset is the scroll offset of this view.</p>
   5847      *
   5848      * @return the vertical offset of the scrollbar's thumb
   5849      *
   5850      * @see #computeVerticalScrollRange()
   5851      * @see #computeVerticalScrollExtent()
   5852      * @see android.widget.ScrollBarDrawable
   5853      */
   5854     protected int computeVerticalScrollOffset() {
   5855         return mScrollY;
   5856     }
   5857 
   5858     /**
   5859      * <p>Compute the vertical extent of the horizontal scrollbar's thumb
   5860      * within the vertical range. This value is used to compute the length
   5861      * of the thumb within the scrollbar's track.</p>
   5862      *
   5863      * <p>The range is expressed in arbitrary units that must be the same as the
   5864      * units used by {@link #computeVerticalScrollRange()} and
   5865      * {@link #computeVerticalScrollOffset()}.</p>
   5866      *
   5867      * <p>The default extent is the drawing height of this view.</p>
   5868      *
   5869      * @return the vertical extent of the scrollbar's thumb
   5870      *
   5871      * @see #computeVerticalScrollRange()
   5872      * @see #computeVerticalScrollOffset()
   5873      * @see android.widget.ScrollBarDrawable
   5874      */
   5875     protected int computeVerticalScrollExtent() {
   5876         return getHeight();
   5877     }
   5878 
   5879     /**
   5880      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
   5881      * scrollbars are painted only if they have been awakened first.</p>
   5882      *
   5883      * @param canvas the canvas on which to draw the scrollbars
   5884      *
   5885      * @see #awakenScrollBars(int)
   5886      */
   5887     protected final void onDrawScrollBars(Canvas canvas) {
   5888         // scrollbars are drawn only when the animation is running
   5889         final ScrollabilityCache cache = mScrollCache;
   5890         if (cache != null) {
   5891 
   5892             int state = cache.state;
   5893 
   5894             if (state == ScrollabilityCache.OFF) {
   5895                 return;
   5896             }
   5897 
   5898             boolean invalidate = false;
   5899 
   5900             if (state == ScrollabilityCache.FADING) {
   5901                 // We're fading -- get our fade interpolation
   5902                 if (cache.interpolatorValues == null) {
   5903                     cache.interpolatorValues = new float[1];
   5904                 }
   5905 
   5906                 float[] values = cache.interpolatorValues;
   5907 
   5908                 // Stops the animation if we're done
   5909                 if (cache.scrollBarInterpolator.timeToValues(values) ==
   5910                         Interpolator.Result.FREEZE_END) {
   5911                     cache.state = ScrollabilityCache.OFF;
   5912                 } else {
   5913                     cache.scrollBar.setAlpha(Math.round(values[0]));
   5914                 }
   5915 
   5916                 // This will make the scroll bars inval themselves after
   5917                 // drawing. We only want this when we're fading so that
   5918                 // we prevent excessive redraws
   5919                 invalidate = true;
   5920             } else {
   5921                 // We're just on -- but we may have been fading before so
   5922                 // reset alpha
   5923                 cache.scrollBar.setAlpha(255);
   5924             }
   5925 
   5926 
   5927             final int viewFlags = mViewFlags;
   5928 
   5929             final boolean drawHorizontalScrollBar =
   5930                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   5931             final boolean drawVerticalScrollBar =
   5932                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
   5933                 && !isVerticalScrollBarHidden();
   5934 
   5935             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
   5936                 final int width = mRight - mLeft;
   5937                 final int height = mBottom - mTop;
   5938 
   5939                 final ScrollBarDrawable scrollBar = cache.scrollBar;
   5940                 int size = scrollBar.getSize(false);
   5941                 if (size <= 0) {
   5942                     size = cache.scrollBarSize;
   5943                 }
   5944 
   5945                 final int scrollX = mScrollX;
   5946                 final int scrollY = mScrollY;
   5947                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   5948 
   5949                 int left, top, right, bottom;
   5950 
   5951                 if (drawHorizontalScrollBar) {
   5952                     scrollBar.setParameters(computeHorizontalScrollRange(),
   5953                                             computeHorizontalScrollOffset(),
   5954                                             computeHorizontalScrollExtent(), false);
   5955                     final int verticalScrollBarGap = drawVerticalScrollBar ?
   5956                             getVerticalScrollbarWidth() : 0;
   5957                     top = scrollY + height - size - (mUserPaddingBottom & inside);
   5958                     left = scrollX + (mPaddingLeft & inside);
   5959                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
   5960                     bottom = top + size;
   5961                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
   5962                     if (invalidate) {
   5963                         invalidate(left, top, right, bottom);
   5964                     }
   5965                 }
   5966 
   5967                 if (drawVerticalScrollBar) {
   5968                     scrollBar.setParameters(computeVerticalScrollRange(),
   5969                                             computeVerticalScrollOffset(),
   5970                                             computeVerticalScrollExtent(), true);
   5971                     // TODO: Deal with RTL languages to position scrollbar on left
   5972                     left = scrollX + width - size - (mUserPaddingRight & inside);
   5973                     top = scrollY + (mPaddingTop & inside);
   5974                     right = left + size;
   5975                     bottom = scrollY + height - (mUserPaddingBottom & inside);
   5976                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
   5977                     if (invalidate) {
   5978                         invalidate(left, top, right, bottom);
   5979                     }
   5980                 }
   5981             }
   5982         }
   5983     }
   5984 
   5985     /**
   5986      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
   5987      * FastScroller is visible.
   5988      * @return whether to temporarily hide the vertical scrollbar
   5989      * @hide
   5990      */
   5991     protected boolean isVerticalScrollBarHidden() {
   5992         return false;
   5993     }
   5994 
   5995     /**
   5996      * <p>Draw the horizontal scrollbar if
   5997      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
   5998      *
   5999      * @param canvas the canvas on which to draw the scrollbar
   6000      * @param scrollBar the scrollbar's drawable
   6001      *
   6002      * @see #isHorizontalScrollBarEnabled()
   6003      * @see #computeHorizontalScrollRange()
   6004      * @see #computeHorizontalScrollExtent()
   6005      * @see #computeHorizontalScrollOffset()
   6006      * @see android.widget.ScrollBarDrawable
   6007      * @hide
   6008      */
   6009     protected void onDrawHorizontalScrollBar(Canvas canvas,
   6010                                              Drawable scrollBar,
   6011                                              int l, int t, int r, int b) {
   6012         scrollBar.setBounds(l, t, r, b);
   6013         scrollBar.draw(canvas);
   6014     }
   6015 
   6016     /**
   6017      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
   6018      * returns true.</p>
   6019      *
   6020      * @param canvas the canvas on which to draw the scrollbar
   6021      * @param scrollBar the scrollbar's drawable
   6022      *
   6023      * @see #isVerticalScrollBarEnabled()
   6024      * @see #computeVerticalScrollRange()
   6025      * @see #computeVerticalScrollExtent()
   6026      * @see #computeVerticalScrollOffset()
   6027      * @see android.widget.ScrollBarDrawable
   6028      * @hide
   6029      */
   6030     protected void onDrawVerticalScrollBar(Canvas canvas,
   6031                                            Drawable scrollBar,
   6032                                            int l, int t, int r, int b) {
   6033         scrollBar.setBounds(l, t, r, b);
   6034         scrollBar.draw(canvas);
   6035     }
   6036 
   6037     /**
   6038      * Implement this to do your drawing.
   6039      *
   6040      * @param canvas the canvas on which the background will be drawn
   6041      */
   6042     protected void onDraw(Canvas canvas) {
   6043     }
   6044 
   6045     /*
   6046      * Caller is responsible for calling requestLayout if necessary.
   6047      * (This allows addViewInLayout to not request a new layout.)
   6048      */
   6049     void assignParent(ViewParent parent) {
   6050         if (mParent == null) {
   6051             mParent = parent;
   6052         } else if (parent == null) {
   6053             mParent = null;
   6054         } else {
   6055             throw new RuntimeException("view " + this + " being added, but"
   6056                     + " it already has a parent");
   6057         }
   6058     }
   6059 
   6060     /**
   6061      * This is called when the view is attached to a window.  At this point it
   6062      * has a Surface and will start drawing.  Note that this function is
   6063      * guaranteed to be called before {@link #onDraw}, however it may be called
   6064      * any time before the first onDraw -- including before or after
   6065      * {@link #onMeasure}.
   6066      *
   6067      * @see #onDetachedFromWindow()
   6068      */
   6069     protected void onAttachedToWindow() {
   6070         if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
   6071             mParent.requestTransparentRegion(this);
   6072         }
   6073         if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
   6074             initialAwakenScrollBars();
   6075             mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
   6076         }
   6077     }
   6078 
   6079     /**
   6080      * This is called when the view is detached from a window.  At this point it
   6081      * no longer has a surface for drawing.
   6082      *
   6083      * @see #onAttachedToWindow()
   6084      */
   6085     protected void onDetachedFromWindow() {
   6086         mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
   6087         removeUnsetPressCallback();
   6088         removeLongPressCallback();
   6089         destroyDrawingCache();
   6090     }
   6091 
   6092     /**
   6093      * @return The number of times this view has been attached to a window
   6094      */
   6095     protected int getWindowAttachCount() {
   6096         return mWindowAttachCount;
   6097     }
   6098 
   6099     /**
   6100      * Retrieve a unique token identifying the window this view is attached to.
   6101      * @return Return the window's token for use in
   6102      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
   6103      */
   6104     public IBinder getWindowToken() {
   6105         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
   6106     }
   6107 
   6108     /**
   6109      * Retrieve a unique token identifying the top-level "real" window of
   6110      * the window that this view is attached to.  That is, this is like
   6111      * {@link #getWindowToken}, except if the window this view in is a panel
   6112      * window (attached to another containing window), then the token of
   6113      * the containing window is returned instead.
   6114      *
   6115      * @return Returns the associated window token, either
   6116      * {@link #getWindowToken()} or the containing window's token.
   6117      */
   6118     public IBinder getApplicationWindowToken() {
   6119         AttachInfo ai = mAttachInfo;
   6120         if (ai != null) {
   6121             IBinder appWindowToken = ai.mPanelParentWindowToken;
   6122             if (appWindowToken == null) {
   6123                 appWindowToken = ai.mWindowToken;
   6124             }
   6125             return appWindowToken;
   6126         }
   6127         return null;
   6128     }
   6129 
   6130     /**
   6131      * Retrieve private session object this view hierarchy is using to
   6132      * communicate with the window manager.
   6133      * @return the session object to communicate with the window manager
   6134      */
   6135     /*package*/ IWindowSession getWindowSession() {
   6136         return mAttachInfo != null ? mAttachInfo.mSession : null;
   6137     }
   6138 
   6139     /**
   6140      * @param info the {@link android.view.View.AttachInfo} to associated with
   6141      *        this view
   6142      */
   6143     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
   6144         //System.out.println("Attached! " + this);
   6145         mAttachInfo = info;
   6146         mWindowAttachCount++;
   6147         if (mFloatingTreeObserver != null) {
   6148             info.mTreeObserver.merge(mFloatingTreeObserver);
   6149             mFloatingTreeObserver = null;
   6150         }
   6151         if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
   6152             mAttachInfo.mScrollContainers.add(this);
   6153             mPrivateFlags |= SCROLL_CONTAINER_ADDED;
   6154         }
   6155         performCollectViewAttributes(visibility);
   6156         onAttachedToWindow();
   6157         int vis = info.mWindowVisibility;
   6158         if (vis != GONE) {
   6159             onWindowVisibilityChanged(vis);
   6160         }
   6161     }
   6162 
   6163     void dispatchDetachedFromWindow() {
   6164         //System.out.println("Detached! " + this);
   6165         AttachInfo info = mAttachInfo;
   6166         if (info != null) {
   6167             int vis = info.mWindowVisibility;
   6168             if (vis != GONE) {
   6169                 onWindowVisibilityChanged(GONE);
   6170             }
   6171         }
   6172 
   6173         onDetachedFromWindow();
   6174         if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
   6175             mAttachInfo.mScrollContainers.remove(this);
   6176             mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
   6177         }
   6178         mAttachInfo = null;
   6179     }
   6180 
   6181     /**
   6182      * Store this view hierarchy's frozen state into the given container.
   6183      *
   6184      * @param container The SparseArray in which to save the view's state.
   6185      *
   6186      * @see #restoreHierarchyState
   6187      * @see #dispatchSaveInstanceState
   6188      * @see #onSaveInstanceState
   6189      */
   6190     public void saveHierarchyState(SparseArray<Parcelable> container) {
   6191         dispatchSaveInstanceState(container);
   6192     }
   6193 
   6194     /**
   6195      * Called by {@link #saveHierarchyState} to store the state for this view and its children.
   6196      * May be overridden to modify how freezing happens to a view's children; for example, some
   6197      * views may want to not store state for their children.
   6198      *
   6199      * @param container The SparseArray in which to save the view's state.
   6200      *
   6201      * @see #dispatchRestoreInstanceState
   6202      * @see #saveHierarchyState
   6203      * @see #onSaveInstanceState
   6204      */
   6205     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
   6206         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
   6207             mPrivateFlags &= ~SAVE_STATE_CALLED;
   6208             Parcelable state = onSaveInstanceState();
   6209             if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
   6210                 throw new IllegalStateException(
   6211                         "Derived class did not call super.onSaveInstanceState()");
   6212             }
   6213             if (state != null) {
   6214                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
   6215                 // + ": " + state);
   6216                 container.put(mID, state);
   6217             }
   6218         }
   6219     }
   6220 
   6221     /**
   6222      * Hook allowing a view to generate a representation of its internal state
   6223      * that can later be used to create a new instance with that same state.
   6224      * This state should only contain information that is not persistent or can
   6225      * not be reconstructed later. For example, you will never store your
   6226      * current position on screen because that will be computed again when a
   6227      * new instance of the view is placed in its view hierarchy.
   6228      * <p>
   6229      * Some examples of things you may store here: the current cursor position
   6230      * in a text view (but usually not the text itself since that is stored in a
   6231      * content provider or other persistent storage), the currently selected
   6232      * item in a list view.
   6233      *
   6234      * @return Returns a Parcelable object containing the view's current dynamic
   6235      *         state, or null if there is nothing interesting to save. The
   6236      *         default implementation returns null.
   6237      * @see #onRestoreInstanceState
   6238      * @see #saveHierarchyState
   6239      * @see #dispatchSaveInstanceState
   6240      * @see #setSaveEnabled(boolean)
   6241      */
   6242     protected Parcelable onSaveInstanceState() {
   6243         mPrivateFlags |= SAVE_STATE_CALLED;
   6244         return BaseSavedState.EMPTY_STATE;
   6245     }
   6246 
   6247     /**
   6248      * Restore this view hierarchy's frozen state from the given container.
   6249      *
   6250      * @param container The SparseArray which holds previously frozen states.
   6251      *
   6252      * @see #saveHierarchyState
   6253      * @see #dispatchRestoreInstanceState
   6254      * @see #onRestoreInstanceState
   6255      */
   6256     public void restoreHierarchyState(SparseArray<Parcelable> container) {
   6257         dispatchRestoreInstanceState(container);
   6258     }
   6259 
   6260     /**
   6261      * Called by {@link #restoreHierarchyState} to retrieve the state for this view and its
   6262      * children. May be overridden to modify how restoreing happens to a view's children; for
   6263      * example, some views may want to not store state for their children.
   6264      *
   6265      * @param container The SparseArray which holds previously saved state.
   6266      *
   6267      * @see #dispatchSaveInstanceState
   6268      * @see #restoreHierarchyState
   6269      * @see #onRestoreInstanceState
   6270      */
   6271     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
   6272         if (mID != NO_ID) {
   6273             Parcelable state = container.get(mID);
   6274             if (state != null) {
   6275                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
   6276                 // + ": " + state);
   6277                 mPrivateFlags &= ~SAVE_STATE_CALLED;
   6278                 onRestoreInstanceState(state);
   6279                 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
   6280                     throw new IllegalStateException(
   6281                             "Derived class did not call super.onRestoreInstanceState()");
   6282                 }
   6283             }
   6284         }
   6285     }
   6286 
   6287     /**
   6288      * Hook allowing a view to re-apply a representation of its internal state that had previously
   6289      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
   6290      * null state.
   6291      *
   6292      * @param state The frozen state that had previously been returned by
   6293      *        {@link #onSaveInstanceState}.
   6294      *
   6295      * @see #onSaveInstanceState
   6296      * @see #restoreHierarchyState
   6297      * @see #dispatchRestoreInstanceState
   6298      */
   6299     protected void onRestoreInstanceState(Parcelable state) {
   6300         mPrivateFlags |= SAVE_STATE_CALLED;
   6301         if (state != BaseSavedState.EMPTY_STATE && state != null) {
   6302             throw new IllegalArgumentException("Wrong state class, expecting View State but "
   6303                     + "received " + state.getClass().toString() + " instead. This usually happens "
   6304                     + "when two views of different type have the same id in the same hierarchy. "
   6305                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
   6306                     + "other views do not use the same id.");
   6307         }
   6308     }
   6309 
   6310     /**
   6311      * <p>Return the time at which the drawing of the view hierarchy started.</p>
   6312      *
   6313      * @return the drawing start time in milliseconds
   6314      */
   6315     public long getDrawingTime() {
   6316         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
   6317     }
   6318 
   6319     /**
   6320      * <p>Enables or disables the duplication of the parent's state into this view. When
   6321      * duplication is enabled, this view gets its drawable state from its parent rather
   6322      * than from its own internal properties.</p>
   6323      *
   6324      * <p>Note: in the current implementation, setting this property to true after the
   6325      * view was added to a ViewGroup might have no effect at all. This property should
   6326      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
   6327      *
   6328      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
   6329      * property is enabled, an exception will be thrown.</p>
   6330      *
   6331      * @param enabled True to enable duplication of the parent's drawable state, false
   6332      *                to disable it.
   6333      *
   6334      * @see #getDrawableState()
   6335      * @see #isDuplicateParentStateEnabled()
   6336      */
   6337     public void setDuplicateParentStateEnabled(boolean enabled) {
   6338         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
   6339     }
   6340 
   6341     /**
   6342      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
   6343      *
   6344      * @return True if this view's drawable state is duplicated from the parent,
   6345      *         false otherwise
   6346      *
   6347      * @see #getDrawableState()
   6348      * @see #setDuplicateParentStateEnabled(boolean)
   6349      */
   6350     public boolean isDuplicateParentStateEnabled() {
   6351         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
   6352     }
   6353 
   6354     /**
   6355      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
   6356      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
   6357      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
   6358      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
   6359      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
   6360      * null.</p>
   6361      *
   6362      * @param enabled true to enable the drawing cache, false otherwise
   6363      *
   6364      * @see #isDrawingCacheEnabled()
   6365      * @see #getDrawingCache()
   6366      * @see #buildDrawingCache()
   6367      */
   6368     public void setDrawingCacheEnabled(boolean enabled) {
   6369         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
   6370     }
   6371 
   6372     /**
   6373      * <p>Indicates whether the drawing cache is enabled for this view.</p>
   6374      *
   6375      * @return true if the drawing cache is enabled
   6376      *
   6377      * @see #setDrawingCacheEnabled(boolean)
   6378      * @see #getDrawingCache()
   6379      */
   6380     @ViewDebug.ExportedProperty(category = "drawing")
   6381     public boolean isDrawingCacheEnabled() {
   6382         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
   6383     }
   6384 
   6385     /**
   6386      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
   6387      *
   6388      * @return A non-scaled bitmap representing this view or null if cache is disabled.
   6389      *
   6390      * @see #getDrawingCache(boolean)
   6391      */
   6392     public Bitmap getDrawingCache() {
   6393         return getDrawingCache(false);
   6394     }
   6395 
   6396     /**
   6397      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
   6398      * is null when caching is disabled. If caching is enabled and the cache is not ready,
   6399      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
   6400      * draw from the cache when the cache is enabled. To benefit from the cache, you must
   6401      * request the drawing cache by calling this method and draw it on screen if the
   6402      * returned bitmap is not null.</p>
   6403      *
   6404      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   6405      * this method will create a bitmap of the same size as this view. Because this bitmap
   6406      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   6407      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   6408      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   6409      * size than the view. This implies that your application must be able to handle this
   6410      * size.</p>
   6411      *
   6412      * @param autoScale Indicates whether the generated bitmap should be scaled based on
   6413      *        the current density of the screen when the application is in compatibility
   6414      *        mode.
   6415      *
   6416      * @return A bitmap representing this view or null if cache is disabled.
   6417      *
   6418      * @see #setDrawingCacheEnabled(boolean)
   6419      * @see #isDrawingCacheEnabled()
   6420      * @see #buildDrawingCache(boolean)
   6421      * @see #destroyDrawingCache()
   6422      */
   6423     public Bitmap getDrawingCache(boolean autoScale) {
   6424         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
   6425             return null;
   6426         }
   6427         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
   6428             buildDrawingCache(autoScale);
   6429         }
   6430         return autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
   6431                 (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
   6432     }
   6433 
   6434     /**
   6435      * <p>Frees the resources used by the drawing cache. If you call
   6436      * {@link #buildDrawingCache()} manually without calling
   6437      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   6438      * should cleanup the cache with this method afterwards.</p>
   6439      *
   6440      * @see #setDrawingCacheEnabled(boolean)
   6441      * @see #buildDrawingCache()
   6442      * @see #getDrawingCache()
   6443      */
   6444     public void destroyDrawingCache() {
   6445         if (mDrawingCache != null) {
   6446             final Bitmap bitmap = mDrawingCache.get();
   6447             if (bitmap != null) bitmap.recycle();
   6448             mDrawingCache = null;
   6449         }
   6450         if (mUnscaledDrawingCache != null) {
   6451             final Bitmap bitmap = mUnscaledDrawingCache.get();
   6452             if (bitmap != null) bitmap.recycle();
   6453             mUnscaledDrawingCache = null;
   6454         }
   6455     }
   6456 
   6457     /**
   6458      * Setting a solid background color for the drawing cache's bitmaps will improve
   6459      * perfromance and memory usage. Note, though that this should only be used if this
   6460      * view will always be drawn on top of a solid color.
   6461      *
   6462      * @param color The background color to use for the drawing cache's bitmap
   6463      *
   6464      * @see #setDrawingCacheEnabled(boolean)
   6465      * @see #buildDrawingCache()
   6466      * @see #getDrawingCache()
   6467      */
   6468     public void setDrawingCacheBackgroundColor(int color) {
   6469         if (color != mDrawingCacheBackgroundColor) {
   6470             mDrawingCacheBackgroundColor = color;
   6471             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   6472         }
   6473     }
   6474 
   6475     /**
   6476      * @see #setDrawingCacheBackgroundColor(int)
   6477      *
   6478      * @return The background color to used for the drawing cache's bitmap
   6479      */
   6480     public int getDrawingCacheBackgroundColor() {
   6481         return mDrawingCacheBackgroundColor;
   6482     }
   6483 
   6484     /**
   6485      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
   6486      *
   6487      * @see #buildDrawingCache(boolean)
   6488      */
   6489     public void buildDrawingCache() {
   6490         buildDrawingCache(false);
   6491     }
   6492 
   6493     /**
   6494      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
   6495      *
   6496      * <p>If you call {@link #buildDrawingCache()} manually without calling
   6497      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   6498      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
   6499      *
   6500      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   6501      * this method will create a bitmap of the same size as this view. Because this bitmap
   6502      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   6503      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   6504      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   6505      * size than the view. This implies that your application must be able to handle this
   6506      * size.</p>
   6507      *
   6508      * @see #getDrawingCache()
   6509      * @see #destroyDrawingCache()
   6510      */
   6511     public void buildDrawingCache(boolean autoScale) {
   6512         if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
   6513                 (mDrawingCache == null || mDrawingCache.get() == null) :
   6514                 (mUnscaledDrawingCache == null || mUnscaledDrawingCache.get() == null))) {
   6515 
   6516             if (ViewDebug.TRACE_HIERARCHY) {
   6517                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
   6518             }
   6519             if (Config.DEBUG && ViewDebug.profileDrawing) {
   6520                 EventLog.writeEvent(60002, hashCode());
   6521             }
   6522 
   6523             int width = mRight - mLeft;
   6524             int height = mBottom - mTop;
   6525 
   6526             final AttachInfo attachInfo = mAttachInfo;
   6527             final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
   6528 
   6529             if (autoScale && scalingRequired) {
   6530                 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
   6531                 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
   6532             }
   6533 
   6534             final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
   6535             final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
   6536             final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
   6537 
   6538             if (width <= 0 || height <= 0 ||
   6539                      // Projected bitmap size in bytes
   6540                     (width * height * (opaque && !use32BitCache ? 2 : 4) >
   6541                             ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
   6542                 destroyDrawingCache();
   6543                 return;
   6544             }
   6545 
   6546             boolean clear = true;
   6547             Bitmap bitmap = autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
   6548                     (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
   6549 
   6550             if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
   6551                 Bitmap.Config quality;
   6552                 if (!opaque) {
   6553                     switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
   6554                         case DRAWING_CACHE_QUALITY_AUTO:
   6555                             quality = Bitmap.Config.ARGB_8888;
   6556                             break;
   6557                         case DRAWING_CACHE_QUALITY_LOW:
   6558                             quality = Bitmap.Config.ARGB_4444;
   6559                             break;
   6560                         case DRAWING_CACHE_QUALITY_HIGH:
   6561                             quality = Bitmap.Config.ARGB_8888;
   6562                             break;
   6563                         default:
   6564                             quality = Bitmap.Config.ARGB_8888;
   6565                             break;
   6566                     }
   6567                 } else {
   6568                     // Optimization for translucent windows
   6569                     // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
   6570                     quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
   6571                 }
   6572 
   6573                 // Try to cleanup memory
   6574                 if (bitmap != null) bitmap.recycle();
   6575 
   6576                 try {
   6577                     bitmap = Bitmap.createBitmap(width, height, quality);
   6578                     bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
   6579                     if (autoScale) {
   6580                         mDrawingCache = new SoftReference<Bitmap>(bitmap);
   6581                     } else {
   6582                         mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap);
   6583                     }
   6584                     if (opaque && use32BitCache) bitmap.setHasAlpha(false);
   6585                 } catch (OutOfMemoryError e) {
   6586                     // If there is not enough memory to create the bitmap cache, just
   6587                     // ignore the issue as bitmap caches are not required to draw the
   6588                     // view hierarchy
   6589                     if (autoScale) {
   6590                         mDrawingCache = null;
   6591                     } else {
   6592                         mUnscaledDrawingCache = null;
   6593                     }
   6594                     return;
   6595                 }
   6596 
   6597                 clear = drawingCacheBackgroundColor != 0;
   6598             }
   6599 
   6600             Canvas canvas;
   6601             if (attachInfo != null) {
   6602                 canvas = attachInfo.mCanvas;
   6603                 if (canvas == null) {
   6604                     canvas = new Canvas();
   6605                 }
   6606                 canvas.setBitmap(bitmap);
   6607                 // Temporarily clobber the cached Canvas in case one of our children
   6608                 // is also using a drawing cache. Without this, the children would
   6609                 // steal the canvas by attaching their own bitmap to it and bad, bad
   6610                 // thing would happen (invisible views, corrupted drawings, etc.)
   6611                 attachInfo.mCanvas = null;
   6612             } else {
   6613                 // This case should hopefully never or seldom happen
   6614                 canvas = new Canvas(bitmap);
   6615             }
   6616 
   6617             if (clear) {
   6618                 bitmap.eraseColor(drawingCacheBackgroundColor);
   6619             }
   6620 
   6621             computeScroll();
   6622             final int restoreCount = canvas.save();
   6623 
   6624             if (autoScale && scalingRequired) {
   6625                 final float scale = attachInfo.mApplicationScale;
   6626                 canvas.scale(scale, scale);
   6627             }
   6628 
   6629             canvas.translate(-mScrollX, -mScrollY);
   6630 
   6631             mPrivateFlags |= DRAWN;
   6632             mPrivateFlags |= DRAWING_CACHE_VALID;
   6633 
   6634             // Fast path for layouts with no backgrounds
   6635             if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
   6636                 if (ViewDebug.TRACE_HIERARCHY) {
   6637                     ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
   6638                 }
   6639                 mPrivateFlags &= ~DIRTY_MASK;
   6640                 dispatchDraw(canvas);
   6641             } else {
   6642                 draw(canvas);
   6643             }
   6644 
   6645             canvas.restoreToCount(restoreCount);
   6646 
   6647             if (attachInfo != null) {
   6648                 // Restore the cached Canvas for our siblings
   6649                 attachInfo.mCanvas = canvas;
   6650             }
   6651         }
   6652     }
   6653 
   6654     /**
   6655      * Create a snapshot of the view into a bitmap.  We should probably make
   6656      * some form of this public, but should think about the API.
   6657      */
   6658     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
   6659         int width = mRight - mLeft;
   6660         int height = mBottom - mTop;
   6661 
   6662         final AttachInfo attachInfo = mAttachInfo;
   6663         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
   6664         width = (int) ((width * scale) + 0.5f);
   6665         height = (int) ((height * scale) + 0.5f);
   6666 
   6667         Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
   6668         if (bitmap == null) {
   6669             throw new OutOfMemoryError();
   6670         }
   6671 
   6672         bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
   6673 
   6674         Canvas canvas;
   6675         if (attachInfo != null) {
   6676             canvas = attachInfo.mCanvas;
   6677             if (canvas == null) {
   6678                 canvas = new Canvas();
   6679             }
   6680             canvas.setBitmap(bitmap);
   6681             // Temporarily clobber the cached Canvas in case one of our children
   6682             // is also using a drawing cache. Without this, the children would
   6683             // steal the canvas by attaching their own bitmap to it and bad, bad
   6684             // things would happen (invisible views, corrupted drawings, etc.)
   6685             attachInfo.mCanvas = null;
   6686         } else {
   6687             // This case should hopefully never or seldom happen
   6688             canvas = new Canvas(bitmap);
   6689         }
   6690 
   6691         if ((backgroundColor & 0xff000000) != 0) {
   6692             bitmap.eraseColor(backgroundColor);
   6693         }
   6694 
   6695         computeScroll();
   6696         final int restoreCount = canvas.save();
   6697         canvas.scale(scale, scale);
   6698         canvas.translate(-mScrollX, -mScrollY);
   6699 
   6700         // Temporarily remove the dirty mask
   6701         int flags = mPrivateFlags;
   6702         mPrivateFlags &= ~DIRTY_MASK;
   6703 
   6704         // Fast path for layouts with no backgrounds
   6705         if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
   6706             dispatchDraw(canvas);
   6707         } else {
   6708             draw(canvas);
   6709         }
   6710 
   6711         mPrivateFlags = flags;
   6712 
   6713         canvas.restoreToCount(restoreCount);
   6714 
   6715         if (attachInfo != null) {
   6716             // Restore the cached Canvas for our siblings
   6717             attachInfo.mCanvas = canvas;
   6718         }
   6719 
   6720         return bitmap;
   6721     }
   6722 
   6723     /**
   6724      * Indicates whether this View is currently in edit mode. A View is usually
   6725      * in edit mode when displayed within a developer tool. For instance, if
   6726      * this View is being drawn by a visual user interface builder, this method
   6727      * should return true.
   6728      *
   6729      * Subclasses should check the return value of this method to provide
   6730      * different behaviors if their normal behavior might interfere with the
   6731      * host environment. For instance: the class spawns a thread in its
   6732      * constructor, the drawing code relies on device-specific features, etc.
   6733      *
   6734      * This method is usually checked in the drawing code of custom widgets.
   6735      *
   6736      * @return True if this View is in edit mode, false otherwise.
   6737      */
   6738     public boolean isInEditMode() {
   6739         return false;
   6740     }
   6741 
   6742     /**
   6743      * If the View draws content inside its padding and enables fading edges,
   6744      * it needs to support padding offsets. Padding offsets are added to the
   6745      * fading edges to extend the length of the fade so that it covers pixels
   6746      * drawn inside the padding.
   6747      *
   6748      * Subclasses of this class should override this method if they need
   6749      * to draw content inside the padding.
   6750      *
   6751      * @return True if padding offset must be applied, false otherwise.
   6752      *
   6753      * @see #getLeftPaddingOffset()
   6754      * @see #getRightPaddingOffset()
   6755      * @see #getTopPaddingOffset()
   6756      * @see #getBottomPaddingOffset()
   6757      *
   6758      * @since CURRENT
   6759      */
   6760     protected boolean isPaddingOffsetRequired() {
   6761         return false;
   6762     }
   6763 
   6764     /**
   6765      * Amount by which to extend the left fading region. Called only when
   6766      * {@link #isPaddingOffsetRequired()} returns true.
   6767      *
   6768      * @return The left padding offset in pixels.
   6769      *
   6770      * @see #isPaddingOffsetRequired()
   6771      *
   6772      * @since CURRENT
   6773      */
   6774     protected int getLeftPaddingOffset() {
   6775         return 0;
   6776     }
   6777 
   6778     /**
   6779      * Amount by which to extend the right fading region. Called only when
   6780      * {@link #isPaddingOffsetRequired()} returns true.
   6781      *
   6782      * @return The right padding offset in pixels.
   6783      *
   6784      * @see #isPaddingOffsetRequired()
   6785      *
   6786      * @since CURRENT
   6787      */
   6788     protected int getRightPaddingOffset() {
   6789         return 0;
   6790     }
   6791 
   6792     /**
   6793      * Amount by which to extend the top fading region. Called only when
   6794      * {@link #isPaddingOffsetRequired()} returns true.
   6795      *
   6796      * @return The top padding offset in pixels.
   6797      *
   6798      * @see #isPaddingOffsetRequired()
   6799      *
   6800      * @since CURRENT
   6801      */
   6802     protected int getTopPaddingOffset() {
   6803         return 0;
   6804     }
   6805 
   6806     /**
   6807      * Amount by which to extend the bottom fading region. Called only when
   6808      * {@link #isPaddingOffsetRequired()} returns true.
   6809      *
   6810      * @return The bottom padding offset in pixels.
   6811      *
   6812      * @see #isPaddingOffsetRequired()
   6813      *
   6814      * @since CURRENT
   6815      */
   6816     protected int getBottomPaddingOffset() {
   6817         return 0;
   6818     }
   6819 
   6820     /**
   6821      * Manually render this view (and all of its children) to the given Canvas.
   6822      * The view must have already done a full layout before this function is
   6823      * called.  When implementing a view, do not override this method; instead,
   6824      * you should implement {@link #onDraw}.
   6825      *
   6826      * @param canvas The Canvas to which the View is rendered.
   6827      */
   6828     public void draw(Canvas canvas) {
   6829         if (ViewDebug.TRACE_HIERARCHY) {
   6830             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
   6831         }
   6832 
   6833         final int privateFlags = mPrivateFlags;
   6834         final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
   6835                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
   6836         mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
   6837 
   6838         /*
   6839          * Draw traversal performs several drawing steps which must be executed
   6840          * in the appropriate order:
   6841          *
   6842          *      1. Draw the background
   6843          *      2. If necessary, save the canvas' layers to prepare for fading
   6844          *      3. Draw view's content
   6845          *      4. Draw children
   6846          *      5. If necessary, draw the fading edges and restore layers
   6847          *      6. Draw decorations (scrollbars for instance)
   6848          */
   6849 
   6850         // Step 1, draw the background, if needed
   6851         int saveCount;
   6852 
   6853         if (!dirtyOpaque) {
   6854             final Drawable background = mBGDrawable;
   6855             if (background != null) {
   6856                 final int scrollX = mScrollX;
   6857                 final int scrollY = mScrollY;
   6858 
   6859                 if (mBackgroundSizeChanged) {
   6860                     background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
   6861                     mBackgroundSizeChanged = false;
   6862                 }
   6863 
   6864                 if ((scrollX | scrollY) == 0) {
   6865                     background.draw(canvas);
   6866                 } else {
   6867                     canvas.translate(scrollX, scrollY);
   6868                     background.draw(canvas);
   6869                     canvas.translate(-scrollX, -scrollY);
   6870                 }
   6871             }
   6872         }
   6873 
   6874         // skip step 2 & 5 if possible (common case)
   6875         final int viewFlags = mViewFlags;
   6876         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
   6877         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
   6878         if (!verticalEdges && !horizontalEdges) {
   6879             // Step 3, draw the content
   6880             if (!dirtyOpaque) onDraw(canvas);
   6881 
   6882             // Step 4, draw the children
   6883             dispatchDraw(canvas);
   6884 
   6885             // Step 6, draw decorations (scrollbars)
   6886             onDrawScrollBars(canvas);
   6887 
   6888             // we're done...
   6889             return;
   6890         }
   6891 
   6892         /*
   6893          * Here we do the full fledged routine...
   6894          * (this is an uncommon case where speed matters less,
   6895          * this is why we repeat some of the tests that have been
   6896          * done above)
   6897          */
   6898 
   6899         boolean drawTop = false;
   6900         boolean drawBottom = false;
   6901         boolean drawLeft = false;
   6902         boolean drawRight = false;
   6903 
   6904         float topFadeStrength = 0.0f;
   6905         float bottomFadeStrength = 0.0f;
   6906         float leftFadeStrength = 0.0f;
   6907         float rightFadeStrength = 0.0f;
   6908 
   6909         // Step 2, save the canvas' layers
   6910         int paddingLeft = mPaddingLeft;
   6911         int paddingTop = mPaddingTop;
   6912 
   6913         final boolean offsetRequired = isPaddingOffsetRequired();
   6914         if (offsetRequired) {
   6915             paddingLeft += getLeftPaddingOffset();
   6916             paddingTop += getTopPaddingOffset();
   6917         }
   6918 
   6919         int left = mScrollX + paddingLeft;
   6920         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
   6921         int top = mScrollY + paddingTop;
   6922         int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop;
   6923 
   6924         if (offsetRequired) {
   6925             right += getRightPaddingOffset();
   6926             bottom += getBottomPaddingOffset();
   6927         }
   6928 
   6929         final ScrollabilityCache scrollabilityCache = mScrollCache;
   6930         int length = scrollabilityCache.fadingEdgeLength;
   6931 
   6932         // clip the fade length if top and bottom fades overlap
   6933         // overlapping fades produce odd-looking artifacts
   6934         if (verticalEdges && (top + length > bottom - length)) {
   6935             length = (bottom - top) / 2;
   6936         }
   6937 
   6938         // also clip horizontal fades if necessary
   6939         if (horizontalEdges && (left + length > right - length)) {
   6940             length = (right - left) / 2;
   6941         }
   6942 
   6943         if (verticalEdges) {
   6944             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
   6945             drawTop = topFadeStrength >= 0.0f;
   6946             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
   6947             drawBottom = bottomFadeStrength >= 0.0f;
   6948         }
   6949 
   6950         if (horizontalEdges) {
   6951             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
   6952             drawLeft = leftFadeStrength >= 0.0f;
   6953             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
   6954             drawRight = rightFadeStrength >= 0.0f;
   6955         }
   6956 
   6957         saveCount = canvas.getSaveCount();
   6958 
   6959         int solidColor = getSolidColor();
   6960         if (solidColor == 0) {
   6961             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
   6962 
   6963             if (drawTop) {
   6964                 canvas.saveLayer(left, top, right, top + length, null, flags);
   6965             }
   6966 
   6967             if (drawBottom) {
   6968                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
   6969             }
   6970 
   6971             if (drawLeft) {
   6972                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
   6973             }
   6974 
   6975             if (drawRight) {
   6976                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
   6977             }
   6978         } else {
   6979             scrollabilityCache.setFadeColor(solidColor);
   6980         }
   6981 
   6982         // Step 3, draw the content
   6983         if (!dirtyOpaque) onDraw(canvas);
   6984 
   6985         // Step 4, draw the children
   6986         dispatchDraw(canvas);
   6987 
   6988         // Step 5, draw the fade effect and restore layers
   6989         final Paint p = scrollabilityCache.paint;
   6990         final Matrix matrix = scrollabilityCache.matrix;
   6991         final Shader fade = scrollabilityCache.shader;
   6992         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
   6993 
   6994         if (drawTop) {
   6995             matrix.setScale(1, fadeHeight * topFadeStrength);
   6996             matrix.postTranslate(left, top);
   6997             fade.setLocalMatrix(matrix);
   6998             canvas.drawRect(left, top, right, top + length, p);
   6999         }
   7000 
   7001         if (drawBottom) {
   7002             matrix.setScale(1, fadeHeight * bottomFadeStrength);
   7003             matrix.postRotate(180);
   7004             matrix.postTranslate(left, bottom);
   7005             fade.setLocalMatrix(matrix);
   7006             canvas.drawRect(left, bottom - length, right, bottom, p);
   7007         }
   7008 
   7009         if (drawLeft) {
   7010             matrix.setScale(1, fadeHeight * leftFadeStrength);
   7011             matrix.postRotate(-90);
   7012             matrix.postTranslate(left, top);
   7013             fade.setLocalMatrix(matrix);
   7014             canvas.drawRect(left, top, left + length, bottom, p);
   7015         }
   7016 
   7017         if (drawRight) {
   7018             matrix.setScale(1, fadeHeight * rightFadeStrength);
   7019             matrix.postRotate(90);
   7020             matrix.postTranslate(right, top);
   7021             fade.setLocalMatrix(matrix);
   7022             canvas.drawRect(right - length, top, right, bottom, p);
   7023         }
   7024 
   7025         canvas.restoreToCount(saveCount);
   7026 
   7027         // Step 6, draw decorations (scrollbars)
   7028         onDrawScrollBars(canvas);
   7029     }
   7030 
   7031     /**
   7032      * Override this if your view is known to always be drawn on top of a solid color background,
   7033      * and needs to draw fading edges. Returning a non-zero color enables the view system to
   7034      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
   7035      * should be set to 0xFF.
   7036      *
   7037      * @see #setVerticalFadingEdgeEnabled
   7038      * @see #setHorizontalFadingEdgeEnabled
   7039      *
   7040      * @return The known solid color background for this view, or 0 if the color may vary
   7041      */
   7042     public int getSolidColor() {
   7043         return 0;
   7044     }
   7045 
   7046     /**
   7047      * Build a human readable string representation of the specified view flags.
   7048      *
   7049      * @param flags the view flags to convert to a string
   7050      * @return a String representing the supplied flags
   7051      */
   7052     private static String printFlags(int flags) {
   7053         String output = "";
   7054         int numFlags = 0;
   7055         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
   7056             output += "TAKES_FOCUS";
   7057             numFlags++;
   7058         }
   7059 
   7060         switch (flags & VISIBILITY_MASK) {
   7061         case INVISIBLE:
   7062             if (numFlags > 0) {
   7063                 output += " ";
   7064             }
   7065             output += "INVISIBLE";
   7066             // USELESS HERE numFlags++;
   7067             break;
   7068         case GONE:
   7069             if (numFlags > 0) {
   7070                 output += " ";
   7071             }
   7072             output += "GONE";
   7073             // USELESS HERE numFlags++;
   7074             break;
   7075         default:
   7076             break;
   7077         }
   7078         return output;
   7079     }
   7080 
   7081     /**
   7082      * Build a human readable string representation of the specified private
   7083      * view flags.
   7084      *
   7085      * @param privateFlags the private view flags to convert to a string
   7086      * @return a String representing the supplied flags
   7087      */
   7088     private static String printPrivateFlags(int privateFlags) {
   7089         String output = "";
   7090         int numFlags = 0;
   7091 
   7092         if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
   7093             output += "WANTS_FOCUS";
   7094             numFlags++;
   7095         }
   7096 
   7097         if ((privateFlags & FOCUSED) == FOCUSED) {
   7098             if (numFlags > 0) {
   7099                 output += " ";
   7100             }
   7101             output += "FOCUSED";
   7102             numFlags++;
   7103         }
   7104 
   7105         if ((privateFlags & SELECTED) == SELECTED) {
   7106             if (numFlags > 0) {
   7107                 output += " ";
   7108             }
   7109             output += "SELECTED";
   7110             numFlags++;
   7111         }
   7112 
   7113         if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
   7114             if (numFlags > 0) {
   7115                 output += " ";
   7116             }
   7117             output += "IS_ROOT_NAMESPACE";
   7118             numFlags++;
   7119         }
   7120 
   7121         if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
   7122             if (numFlags > 0) {
   7123                 output += " ";
   7124             }
   7125             output += "HAS_BOUNDS";
   7126             numFlags++;
   7127         }
   7128 
   7129         if ((privateFlags & DRAWN) == DRAWN) {
   7130             if (numFlags > 0) {
   7131                 output += " ";
   7132             }
   7133             output += "DRAWN";
   7134             // USELESS HERE numFlags++;
   7135         }
   7136         return output;
   7137     }
   7138 
   7139     /**
   7140      * <p>Indicates whether or not this view's layout will be requested during
   7141      * the next hierarchy layout pass.</p>
   7142      *
   7143      * @return true if the layout will be forced during next layout pass
   7144      */
   7145     public boolean isLayoutRequested() {
   7146         return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
   7147     }
   7148 
   7149     /**
   7150      * Assign a size and position to a view and all of its
   7151      * descendants
   7152      *
   7153      * <p>This is the second phase of the layout mechanism.
   7154      * (The first is measuring). In this phase, each parent calls
   7155      * layout on all of its children to position them.
   7156      * This is typically done using the child measurements
   7157      * that were stored in the measure pass().
   7158      *
   7159      * Derived classes with children should override
   7160      * onLayout. In that method, they should
   7161      * call layout on each of their their children.
   7162      *
   7163      * @param l Left position, relative to parent
   7164      * @param t Top position, relative to parent
   7165      * @param r Right position, relative to parent
   7166      * @param b Bottom position, relative to parent
   7167      */
   7168     public final void layout(int l, int t, int r, int b) {
   7169         boolean changed = setFrame(l, t, r, b);
   7170         if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
   7171             if (ViewDebug.TRACE_HIERARCHY) {
   7172                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
   7173             }
   7174 
   7175             onLayout(changed, l, t, r, b);
   7176             mPrivateFlags &= ~LAYOUT_REQUIRED;
   7177         }
   7178         mPrivateFlags &= ~FORCE_LAYOUT;
   7179     }
   7180 
   7181     /**
   7182      * Called from layout when this view should
   7183      * assign a size and position to each of its children.
   7184      *
   7185      * Derived classes with children should override
   7186      * this method and call layout on each of
   7187      * their their children.
   7188      * @param changed This is a new size or position for this view
   7189      * @param left Left position, relative to parent
   7190      * @param top Top position, relative to parent
   7191      * @param right Right position, relative to parent
   7192      * @param bottom Bottom position, relative to parent
   7193      */
   7194     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   7195     }
   7196 
   7197     /**
   7198      * Assign a size and position to this view.
   7199      *
   7200      * This is called from layout.
   7201      *
   7202      * @param left Left position, relative to parent
   7203      * @param top Top position, relative to parent
   7204      * @param right Right position, relative to parent
   7205      * @param bottom Bottom position, relative to parent
   7206      * @return true if the new size and position are different than the
   7207      *         previous ones
   7208      * {@hide}
   7209      */
   7210     protected boolean setFrame(int left, int top, int right, int bottom) {
   7211         boolean changed = false;
   7212 
   7213         if (DBG) {
   7214             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
   7215                     + right + "," + bottom + ")");
   7216         }
   7217 
   7218         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
   7219             changed = true;
   7220 
   7221             // Remember our drawn bit
   7222             int drawn = mPrivateFlags & DRAWN;
   7223 
   7224             // Invalidate our old position
   7225             invalidate();
   7226 
   7227 
   7228             int oldWidth = mRight - mLeft;
   7229             int oldHeight = mBottom - mTop;
   7230 
   7231             mLeft = left;
   7232             mTop = top;
   7233             mRight = right;
   7234             mBottom = bottom;
   7235 
   7236             mPrivateFlags |= HAS_BOUNDS;
   7237 
   7238             int newWidth = right - left;
   7239             int newHeight = bottom - top;
   7240 
   7241             if (newWidth != oldWidth || newHeight != oldHeight) {
   7242                 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
   7243             }
   7244 
   7245             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
   7246                 // If we are visible, force the DRAWN bit to on so that
   7247                 // this invalidate will go through (at least to our parent).
   7248                 // This is because someone may have invalidated this view
   7249                 // before this call to setFrame came in, therby clearing
   7250                 // the DRAWN bit.
   7251                 mPrivateFlags |= DRAWN;
   7252                 invalidate();
   7253             }
   7254 
   7255             // Reset drawn bit to original value (invalidate turns it off)
   7256             mPrivateFlags |= drawn;
   7257 
   7258             mBackgroundSizeChanged = true;
   7259         }
   7260         return changed;
   7261     }
   7262 
   7263     /**
   7264      * Finalize inflating a view from XML.  This is called as the last phase
   7265      * of inflation, after all child views have been added.
   7266      *
   7267      * <p>Even if the subclass overrides onFinishInflate, they should always be
   7268      * sure to call the super method, so that we get called.
   7269      */
   7270     protected void onFinishInflate() {
   7271     }
   7272 
   7273     /**
   7274      * Returns the resources associated with this view.
   7275      *
   7276      * @return Resources object.
   7277      */
   7278     public Resources getResources() {
   7279         return mResources;
   7280     }
   7281 
   7282     /**
   7283      * Invalidates the specified Drawable.
   7284      *
   7285      * @param drawable the drawable to invalidate
   7286      */
   7287     public void invalidateDrawable(Drawable drawable) {
   7288         if (verifyDrawable(drawable)) {
   7289             final Rect dirty = drawable.getBounds();
   7290             final int scrollX = mScrollX;
   7291             final int scrollY = mScrollY;
   7292 
   7293             invalidate(dirty.left + scrollX, dirty.top + scrollY,
   7294                     dirty.right + scrollX, dirty.bottom + scrollY);
   7295         }
   7296     }
   7297 
   7298     /**
   7299      * Schedules an action on a drawable to occur at a specified time.
   7300      *
   7301      * @param who the recipient of the action
   7302      * @param what the action to run on the drawable
   7303      * @param when the time at which the action must occur. Uses the
   7304      *        {@link SystemClock#uptimeMillis} timebase.
   7305      */
   7306     public void scheduleDrawable(Drawable who, Runnable what, long when) {
   7307         if (verifyDrawable(who) && what != null && mAttachInfo != null) {
   7308             mAttachInfo.mHandler.postAtTime(what, who, when);
   7309         }
   7310     }
   7311 
   7312     /**
   7313      * Cancels a scheduled action on a drawable.
   7314      *
   7315      * @param who the recipient of the action
   7316      * @param what the action to cancel
   7317      */
   7318     public void unscheduleDrawable(Drawable who, Runnable what) {
   7319         if (verifyDrawable(who) && what != null && mAttachInfo != null) {
   7320             mAttachInfo.mHandler.removeCallbacks(what, who);
   7321         }
   7322     }
   7323 
   7324     /**
   7325      * Unschedule any events associated with the given Drawable.  This can be
   7326      * used when selecting a new Drawable into a view, so that the previous
   7327      * one is completely unscheduled.
   7328      *
   7329      * @param who The Drawable to unschedule.
   7330      *
   7331      * @see #drawableStateChanged
   7332      */
   7333     public void unscheduleDrawable(Drawable who) {
   7334         if (mAttachInfo != null) {
   7335             mAttachInfo.mHandler.removeCallbacksAndMessages(who);
   7336         }
   7337     }
   7338 
   7339     /**
   7340      * If your view subclass is displaying its own Drawable objects, it should
   7341      * override this function and return true for any Drawable it is
   7342      * displaying.  This allows animations for those drawables to be
   7343      * scheduled.
   7344      *
   7345      * <p>Be sure to call through to the super class when overriding this
   7346      * function.
   7347      *
   7348      * @param who The Drawable to verify.  Return true if it is one you are
   7349      *            displaying, else return the result of calling through to the
   7350      *            super class.
   7351      *
   7352      * @return boolean If true than the Drawable is being displayed in the
   7353      *         view; else false and it is not allowed to animate.
   7354      *
   7355      * @see #unscheduleDrawable
   7356      * @see #drawableStateChanged
   7357      */
   7358     protected boolean verifyDrawable(Drawable who) {
   7359         return who == mBGDrawable;
   7360     }
   7361 
   7362     /**
   7363      * This function is called whenever the state of the view changes in such
   7364      * a way that it impacts the state of drawables being shown.
   7365      *
   7366      * <p>Be sure to call through to the superclass when overriding this
   7367      * function.
   7368      *
   7369      * @see Drawable#setState
   7370      */
   7371     protected void drawableStateChanged() {
   7372         Drawable d = mBGDrawable;
   7373         if (d != null && d.isStateful()) {
   7374             d.setState(getDrawableState());
   7375         }
   7376     }
   7377 
   7378     /**
   7379      * Call this to force a view to update its drawable state. This will cause
   7380      * drawableStateChanged to be called on this view. Views that are interested
   7381      * in the new state should call getDrawableState.
   7382      *
   7383      * @see #drawableStateChanged
   7384      * @see #getDrawableState
   7385      */
   7386     public void refreshDrawableState() {
   7387         mPrivateFlags |= DRAWABLE_STATE_DIRTY;
   7388         drawableStateChanged();
   7389 
   7390         ViewParent parent = mParent;
   7391         if (parent != null) {
   7392             parent.childDrawableStateChanged(this);
   7393         }
   7394     }
   7395 
   7396     /**
   7397      * Return an array of resource IDs of the drawable states representing the
   7398      * current state of the view.
   7399      *
   7400      * @return The current drawable state
   7401      *
   7402      * @see Drawable#setState
   7403      * @see #drawableStateChanged
   7404      * @see #onCreateDrawableState
   7405      */
   7406     public final int[] getDrawableState() {
   7407         if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
   7408             return mDrawableState;
   7409         } else {
   7410             mDrawableState = onCreateDrawableState(0);
   7411             mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
   7412             return mDrawableState;
   7413         }
   7414     }
   7415 
   7416     /**
   7417      * Generate the new {@link android.graphics.drawable.Drawable} state for
   7418      * this view. This is called by the view
   7419      * system when the cached Drawable state is determined to be invalid.  To
   7420      * retrieve the current state, you should use {@link #getDrawableState}.
   7421      *
   7422      * @param extraSpace if non-zero, this is the number of extra entries you
   7423      * would like in the returned array in which you can place your own
   7424      * states.
   7425      *
   7426      * @return Returns an array holding the current {@link Drawable} state of
   7427      * the view.
   7428      *
   7429      * @see #mergeDrawableStates
   7430      */
   7431     protected int[] onCreateDrawableState(int extraSpace) {
   7432         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
   7433                 mParent instanceof View) {
   7434             return ((View) mParent).onCreateDrawableState(extraSpace);
   7435         }
   7436 
   7437         int[] drawableState;
   7438 
   7439         int privateFlags = mPrivateFlags;
   7440 
   7441         int viewStateIndex = (((privateFlags & PRESSED) != 0) ? 1 : 0);
   7442 
   7443         viewStateIndex = (viewStateIndex << 1)
   7444                 + (((mViewFlags & ENABLED_MASK) == ENABLED) ? 1 : 0);
   7445 
   7446         viewStateIndex = (viewStateIndex << 1) + (isFocused() ? 1 : 0);
   7447 
   7448         viewStateIndex = (viewStateIndex << 1)
   7449                 + (((privateFlags & SELECTED) != 0) ? 1 : 0);
   7450 
   7451         final boolean hasWindowFocus = hasWindowFocus();
   7452         viewStateIndex = (viewStateIndex << 1) + (hasWindowFocus ? 1 : 0);
   7453 
   7454         drawableState = VIEW_STATE_SETS[viewStateIndex];
   7455 
   7456         //noinspection ConstantIfStatement
   7457         if (false) {
   7458             Log.i("View", "drawableStateIndex=" + viewStateIndex);
   7459             Log.i("View", toString()
   7460                     + " pressed=" + ((privateFlags & PRESSED) != 0)
   7461                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
   7462                     + " fo=" + hasFocus()
   7463                     + " sl=" + ((privateFlags & SELECTED) != 0)
   7464                     + " wf=" + hasWindowFocus
   7465                     + ": " + Arrays.toString(drawableState));
   7466         }
   7467 
   7468         if (extraSpace == 0) {
   7469             return drawableState;
   7470         }
   7471 
   7472         final int[] fullState;
   7473         if (drawableState != null) {
   7474             fullState = new int[drawableState.length + extraSpace];
   7475             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
   7476         } else {
   7477             fullState = new int[extraSpace];
   7478         }
   7479 
   7480         return fullState;
   7481     }
   7482 
   7483     /**
   7484      * Merge your own state values in <var>additionalState</var> into the base
   7485      * state values <var>baseState</var> that were returned by
   7486      * {@link #onCreateDrawableState}.
   7487      *
   7488      * @param baseState The base state values returned by
   7489      * {@link #onCreateDrawableState}, which will be modified to also hold your
   7490      * own additional state values.
   7491      *
   7492      * @param additionalState The additional state values you would like
   7493      * added to <var>baseState</var>; this array is not modified.
   7494      *
   7495      * @return As a convenience, the <var>baseState</var> array you originally
   7496      * passed into the function is returned.
   7497      *
   7498      * @see #onCreateDrawableState
   7499      */
   7500     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
   7501         final int N = baseState.length;
   7502         int i = N - 1;
   7503         while (i >= 0 && baseState[i] == 0) {
   7504             i--;
   7505         }
   7506         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
   7507         return baseState;
   7508     }
   7509 
   7510     /**
   7511      * Sets the background color for this view.
   7512      * @param color the color of the background
   7513      */
   7514     @RemotableViewMethod
   7515     public void setBackgroundColor(int color) {
   7516         setBackgroundDrawable(new ColorDrawable(color));
   7517     }
   7518 
   7519     /**
   7520      * Set the background to a given resource. The resource should refer to
   7521      * a Drawable object or 0 to remove the background.
   7522      * @param resid The identifier of the resource.
   7523      * @attr ref android.R.styleable#View_background
   7524      */
   7525     @RemotableViewMethod
   7526     public void setBackgroundResource(int resid) {
   7527         if (resid != 0 && resid == mBackgroundResource) {
   7528             return;
   7529         }
   7530 
   7531         Drawable d= null;
   7532         if (resid != 0) {
   7533             d = mResources.getDrawable(resid);
   7534         }
   7535         setBackgroundDrawable(d);
   7536 
   7537         mBackgroundResource = resid;
   7538     }
   7539 
   7540     /**
   7541      * Set the background to a given Drawable, or remove the background. If the
   7542      * background has padding, this View's padding is set to the background's
   7543      * padding. However, when a background is removed, this View's padding isn't
   7544      * touched. If setting the padding is desired, please use
   7545      * {@link #setPadding(int, int, int, int)}.
   7546      *
   7547      * @param d The Drawable to use as the background, or null to remove the
   7548      *        background
   7549      */
   7550     public void setBackgroundDrawable(Drawable d) {
   7551         boolean requestLayout = false;
   7552 
   7553         mBackgroundResource = 0;
   7554 
   7555         /*
   7556          * Regardless of whether we're setting a new background or not, we want
   7557          * to clear the previous drawable.
   7558          */
   7559         if (mBGDrawable != null) {
   7560             mBGDrawable.setCallback(null);
   7561             unscheduleDrawable(mBGDrawable);
   7562         }
   7563 
   7564         if (d != null) {
   7565             Rect padding = sThreadLocal.get();
   7566             if (padding == null) {
   7567                 padding = new Rect();
   7568                 sThreadLocal.set(padding);
   7569             }
   7570             if (d.getPadding(padding)) {
   7571                 setPadding(padding.left, padding.top, padding.right, padding.bottom);
   7572             }
   7573 
   7574             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
   7575             // if it has a different minimum size, we should layout again
   7576             if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
   7577                     mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
   7578                 requestLayout = true;
   7579             }
   7580 
   7581             d.setCallback(this);
   7582             if (d.isStateful()) {
   7583                 d.setState(getDrawableState());
   7584             }
   7585             d.setVisible(getVisibility() == VISIBLE, false);
   7586             mBGDrawable = d;
   7587 
   7588             if ((mPrivateFlags & SKIP_DRAW) != 0) {
   7589                 mPrivateFlags &= ~SKIP_DRAW;
   7590                 mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
   7591                 requestLayout = true;
   7592             }
   7593         } else {
   7594             /* Remove the background */
   7595             mBGDrawable = null;
   7596 
   7597             if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
   7598                 /*
   7599                  * This view ONLY drew the background before and we're removing
   7600                  * the background, so now it won't draw anything
   7601                  * (hence we SKIP_DRAW)
   7602                  */
   7603                 mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
   7604                 mPrivateFlags |= SKIP_DRAW;
   7605             }
   7606 
   7607             /*
   7608              * When the background is set, we try to apply its padding to this
   7609              * View. When the background is removed, we don't touch this View's
   7610              * padding. This is noted in the Javadocs. Hence, we don't need to
   7611              * requestLayout(), the invalidate() below is sufficient.
   7612              */
   7613 
   7614             // The old background's minimum size could have affected this
   7615             // View's layout, so let's requestLayout
   7616             requestLayout = true;
   7617         }
   7618 
   7619         computeOpaqueFlags();
   7620 
   7621         if (requestLayout) {
   7622             requestLayout();
   7623         }
   7624 
   7625         mBackgroundSizeChanged = true;
   7626         invalidate();
   7627     }
   7628 
   7629     /**
   7630      * Gets the background drawable
   7631      * @return The drawable used as the background for this view, if any.
   7632      */
   7633     public Drawable getBackground() {
   7634         return mBGDrawable;
   7635     }
   7636 
   7637     /**
   7638      * Sets the padding. The view may add on the space required to display
   7639      * the scrollbars, depending on the style and visibility of the scrollbars.
   7640      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
   7641      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
   7642      * from the values set in this call.
   7643      *
   7644      * @attr ref android.R.styleable#View_padding
   7645      * @attr ref android.R.styleable#View_paddingBottom
   7646      * @attr ref android.R.styleable#View_paddingLeft
   7647      * @attr ref android.R.styleable#View_paddingRight
   7648      * @attr ref android.R.styleable#View_paddingTop
   7649      * @param left the left padding in pixels
   7650      * @param top the top padding in pixels
   7651      * @param right the right padding in pixels
   7652      * @param bottom the bottom padding in pixels
   7653      */
   7654     public void setPadding(int left, int top, int right, int bottom) {
   7655         boolean changed = false;
   7656 
   7657         mUserPaddingRight = right;
   7658         mUserPaddingBottom = bottom;
   7659 
   7660         final int viewFlags = mViewFlags;
   7661 
   7662         // Common case is there are no scroll bars.
   7663         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
   7664             // TODO: Deal with RTL languages to adjust left padding instead of right.
   7665             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
   7666                 right += (viewFlags & SCROLLBARS_INSET_MASK) == 0
   7667                         ? 0 : getVerticalScrollbarWidth();
   7668             }
   7669             if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) {
   7670                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
   7671                         ? 0 : getHorizontalScrollbarHeight();
   7672             }
   7673         }
   7674 
   7675         if (mPaddingLeft != left) {
   7676             changed = true;
   7677             mPaddingLeft = left;
   7678         }
   7679         if (mPaddingTop != top) {
   7680             changed = true;
   7681             mPaddingTop = top;
   7682         }
   7683         if (mPaddingRight != right) {
   7684             changed = true;
   7685             mPaddingRight = right;
   7686         }
   7687         if (mPaddingBottom != bottom) {
   7688             changed = true;
   7689             mPaddingBottom = bottom;
   7690         }
   7691 
   7692         if (changed) {
   7693             requestLayout();
   7694         }
   7695     }
   7696 
   7697     /**
   7698      * Returns the top padding of this view.
   7699      *
   7700      * @return the top padding in pixels
   7701      */
   7702     public int getPaddingTop() {
   7703         return mPaddingTop;
   7704     }
   7705 
   7706     /**
   7707      * Returns the bottom padding of this view. If there are inset and enabled
   7708      * scrollbars, this value may include the space required to display the
   7709      * scrollbars as well.
   7710      *
   7711      * @return the bottom padding in pixels
   7712      */
   7713     public int getPaddingBottom() {
   7714         return mPaddingBottom;
   7715     }
   7716 
   7717     /**
   7718      * Returns the left padding of this view. If there are inset and enabled
   7719      * scrollbars, this value may include the space required to display the
   7720      * scrollbars as well.
   7721      *
   7722      * @return the left padding in pixels
   7723      */
   7724     public int getPaddingLeft() {
   7725         return mPaddingLeft;
   7726     }
   7727 
   7728     /**
   7729      * Returns the right padding of this view. If there are inset and enabled
   7730      * scrollbars, this value may include the space required to display the
   7731      * scrollbars as well.
   7732      *
   7733      * @return the right padding in pixels
   7734      */
   7735     public int getPaddingRight() {
   7736         return mPaddingRight;
   7737     }
   7738 
   7739     /**
   7740      * Changes the selection state of this view. A view can be selected or not.
   7741      * Note that selection is not the same as focus. Views are typically
   7742      * selected in the context of an AdapterView like ListView or GridView;
   7743      * the selected view is the view that is highlighted.
   7744      *
   7745      * @param selected true if the view must be selected, false otherwise
   7746      */
   7747     public void setSelected(boolean selected) {
   7748         if (((mPrivateFlags & SELECTED) != 0) != selected) {
   7749             mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
   7750             if (!selected) resetPressedState();
   7751             invalidate();
   7752             refreshDrawableState();
   7753             dispatchSetSelected(selected);
   7754         }
   7755     }
   7756 
   7757     /**
   7758      * Dispatch setSelected to all of this View's children.
   7759      *
   7760      * @see #setSelected(boolean)
   7761      *
   7762      * @param selected The new selected state
   7763      */
   7764     protected void dispatchSetSelected(boolean selected) {
   7765     }
   7766 
   7767     /**
   7768      * Indicates the selection state of this view.
   7769      *
   7770      * @return true if the view is selected, false otherwise
   7771      */
   7772     @ViewDebug.ExportedProperty
   7773     public boolean isSelected() {
   7774         return (mPrivateFlags & SELECTED) != 0;
   7775     }
   7776 
   7777     /**
   7778      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
   7779      * observer can be used to get notifications when global events, like
   7780      * layout, happen.
   7781      *
   7782      * The returned ViewTreeObserver observer is not guaranteed to remain
   7783      * valid for the lifetime of this View. If the caller of this method keeps
   7784      * a long-lived reference to ViewTreeObserver, it should always check for
   7785      * the return value of {@link ViewTreeObserver#isAlive()}.
   7786      *
   7787      * @return The ViewTreeObserver for this view's hierarchy.
   7788      */
   7789     public ViewTreeObserver getViewTreeObserver() {
   7790         if (mAttachInfo != null) {
   7791             return mAttachInfo.mTreeObserver;
   7792         }
   7793         if (mFloatingTreeObserver == null) {
   7794             mFloatingTreeObserver = new ViewTreeObserver();
   7795         }
   7796         return mFloatingTreeObserver;
   7797     }
   7798 
   7799     /**
   7800      * <p>Finds the topmost view in the current view hierarchy.</p>
   7801      *
   7802      * @return the topmost view containing this view
   7803      */
   7804     public View getRootView() {
   7805         if (mAttachInfo != null) {
   7806             final View v = mAttachInfo.mRootView;
   7807             if (v != null) {
   7808                 return v;
   7809             }
   7810         }
   7811 
   7812         View parent = this;
   7813 
   7814         while (parent.mParent != null && parent.mParent instanceof View) {
   7815             parent = (View) parent.mParent;
   7816         }
   7817 
   7818         return parent;
   7819     }
   7820 
   7821     /**
   7822      * <p>Computes the coordinates of this view on the screen. The argument
   7823      * must be an array of two integers. After the method returns, the array
   7824      * contains the x and y location in that order.</p>
   7825      *
   7826      * @param location an array of two integers in which to hold the coordinates
   7827      */
   7828     public void getLocationOnScreen(int[] location) {
   7829         getLocationInWindow(location);
   7830 
   7831         final AttachInfo info = mAttachInfo;
   7832         if (info != null) {
   7833             location[0] += info.mWindowLeft;
   7834             location[1] += info.mWindowTop;
   7835         }
   7836     }
   7837 
   7838     /**
   7839      * <p>Computes the coordinates of this view in its window. The argument
   7840      * must be an array of two integers. After the method returns, the array
   7841      * contains the x and y location in that order.</p>
   7842      *
   7843      * @param location an array of two integers in which to hold the coordinates
   7844      */
   7845     public void getLocationInWindow(int[] location) {
   7846         if (location == null || location.length < 2) {
   7847             throw new IllegalArgumentException("location must be an array of "
   7848                     + "two integers");
   7849         }
   7850 
   7851         location[0] = mLeft;
   7852         location[1] = mTop;
   7853 
   7854         ViewParent viewParent = mParent;
   7855         while (viewParent instanceof View) {
   7856             final View view = (View)viewParent;
   7857             location[0] += view.mLeft - view.mScrollX;
   7858             location[1] += view.mTop - view.mScrollY;
   7859             viewParent = view.mParent;
   7860         }
   7861 
   7862         if (viewParent instanceof ViewRoot) {
   7863             // *cough*
   7864             final ViewRoot vr = (ViewRoot)viewParent;
   7865             location[1] -= vr.mCurScrollY;
   7866         }
   7867     }
   7868 
   7869     /**
   7870      * {@hide}
   7871      * @param id the id of the view to be found
   7872      * @return the view of the specified id, null if cannot be found
   7873      */
   7874     protected View findViewTraversal(int id) {
   7875         if (id == mID) {
   7876             return this;
   7877         }
   7878         return null;
   7879     }
   7880 
   7881     /**
   7882      * {@hide}
   7883      * @param tag the tag of the view to be found
   7884      * @return the view of specified tag, null if cannot be found
   7885      */
   7886     protected View findViewWithTagTraversal(Object tag) {
   7887         if (tag != null && tag.equals(mTag)) {
   7888             return this;
   7889         }
   7890         return null;
   7891     }
   7892 
   7893     /**
   7894      * Look for a child view with the given id.  If this view has the given
   7895      * id, return this view.
   7896      *
   7897      * @param id The id to search for.
   7898      * @return The view that has the given id in the hierarchy or null
   7899      */
   7900     public final View findViewById(int id) {
   7901         if (id < 0) {
   7902             return null;
   7903         }
   7904         return findViewTraversal(id);
   7905     }
   7906 
   7907     /**
   7908      * Look for a child view with the given tag.  If this view has the given
   7909      * tag, return this view.
   7910      *
   7911      * @param tag The tag to search for, using "tag.equals(getTag())".
   7912      * @return The View that has the given tag in the hierarchy or null
   7913      */
   7914     public final View findViewWithTag(Object tag) {
   7915         if (tag == null) {
   7916             return null;
   7917         }
   7918         return findViewWithTagTraversal(tag);
   7919     }
   7920 
   7921     /**
   7922      * Sets the identifier for this view. The identifier does not have to be
   7923      * unique in this view's hierarchy. The identifier should be a positive
   7924      * number.
   7925      *
   7926      * @see #NO_ID
   7927      * @see #getId
   7928      * @see #findViewById
   7929      *
   7930      * @param id a number used to identify the view
   7931      *
   7932      * @attr ref android.R.styleable#View_id
   7933      */
   7934     public void setId(int id) {
   7935         mID = id;
   7936     }
   7937 
   7938     /**
   7939      * {@hide}
   7940      *
   7941      * @param isRoot true if the view belongs to the root namespace, false
   7942      *        otherwise
   7943      */
   7944     public void setIsRootNamespace(boolean isRoot) {
   7945         if (isRoot) {
   7946             mPrivateFlags |= IS_ROOT_NAMESPACE;
   7947         } else {
   7948             mPrivateFlags &= ~IS_ROOT_NAMESPACE;
   7949         }
   7950     }
   7951 
   7952     /**
   7953      * {@hide}
   7954      *
   7955      * @return true if the view belongs to the root namespace, false otherwise
   7956      */
   7957     public boolean isRootNamespace() {
   7958         return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
   7959     }
   7960 
   7961     /**
   7962      * Returns this view's identifier.
   7963      *
   7964      * @return a positive integer used to identify the view or {@link #NO_ID}
   7965      *         if the view has no ID
   7966      *
   7967      * @see #setId
   7968      * @see #findViewById
   7969      * @attr ref android.R.styleable#View_id
   7970      */
   7971     @ViewDebug.CapturedViewProperty
   7972     public int getId() {
   7973         return mID;
   7974     }
   7975 
   7976     /**
   7977      * Returns this view's tag.
   7978      *
   7979      * @return the Object stored in this view as a tag
   7980      *
   7981      * @see #setTag(Object)
   7982      * @see #getTag(int)
   7983      */
   7984     @ViewDebug.ExportedProperty
   7985     public Object getTag() {
   7986         return mTag;
   7987     }
   7988 
   7989     /**
   7990      * Sets the tag associated with this view. A tag can be used to mark
   7991      * a view in its hierarchy and does not have to be unique within the
   7992      * hierarchy. Tags can also be used to store data within a view without
   7993      * resorting to another data structure.
   7994      *
   7995      * @param tag an Object to tag the view with
   7996      *
   7997      * @see #getTag()
   7998      * @see #setTag(int, Object)
   7999      */
   8000     public void setTag(final Object tag) {
   8001         mTag = tag;
   8002     }
   8003 
   8004     /**
   8005      * Returns the tag associated with this view and the specified key.
   8006      *
   8007      * @param key The key identifying the tag
   8008      *
   8009      * @return the Object stored in this view as a tag
   8010      *
   8011      * @see #setTag(int, Object)
   8012      * @see #getTag()
   8013      */
   8014     public Object getTag(int key) {
   8015         SparseArray<Object> tags = null;
   8016         synchronized (sTagsLock) {
   8017             if (sTags != null) {
   8018                 tags = sTags.get(this);
   8019             }
   8020         }
   8021 
   8022         if (tags != null) return tags.get(key);
   8023         return null;
   8024     }
   8025 
   8026     /**
   8027      * Sets a tag associated with this view and a key. A tag can be used
   8028      * to mark a view in its hierarchy and does not have to be unique within
   8029      * the hierarchy. Tags can also be used to store data within a view
   8030      * without resorting to another data structure.
   8031      *
   8032      * The specified key should be an id declared in the resources of the
   8033      * application to ensure it is unique (see the <a
   8034      * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
   8035      * Keys identified as belonging to
   8036      * the Android framework or not associated with any package will cause
   8037      * an {@link IllegalArgumentException} to be thrown.
   8038      *
   8039      * @param key The key identifying the tag
   8040      * @param tag An Object to tag the view with
   8041      *
   8042      * @throws IllegalArgumentException If they specified key is not valid
   8043      *
   8044      * @see #setTag(Object)
   8045      * @see #getTag(int)
   8046      */
   8047     public void setTag(int key, final Object tag) {
   8048         // If the package id is 0x00 or 0x01, it's either an undefined package
   8049         // or a framework id
   8050         if ((key >>> 24) < 2) {
   8051             throw new IllegalArgumentException("The key must be an application-specific "
   8052                     + "resource id.");
   8053         }
   8054 
   8055         setTagInternal(this, key, tag);
   8056     }
   8057 
   8058     /**
   8059      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
   8060      * framework id.
   8061      *
   8062      * @hide
   8063      */
   8064     public void setTagInternal(int key, Object tag) {
   8065         if ((key >>> 24) != 0x1) {
   8066             throw new IllegalArgumentException("The key must be a framework-specific "
   8067                     + "resource id.");
   8068         }
   8069 
   8070         setTagInternal(this, key, tag);
   8071     }
   8072 
   8073     private static void setTagInternal(View view, int key, Object tag) {
   8074         SparseArray<Object> tags = null;
   8075         synchronized (sTagsLock) {
   8076             if (sTags == null) {
   8077                 sTags = new WeakHashMap<View, SparseArray<Object>>();
   8078             } else {
   8079                 tags = sTags.get(view);
   8080             }
   8081         }
   8082 
   8083         if (tags == null) {
   8084             tags = new SparseArray<Object>(2);
   8085             synchronized (sTagsLock) {
   8086                 sTags.put(view, tags);
   8087             }
   8088         }
   8089 
   8090         tags.put(key, tag);
   8091     }
   8092 
   8093     /**
   8094      * @param consistency The type of consistency. See ViewDebug for more information.
   8095      *
   8096      * @hide
   8097      */
   8098     protected boolean dispatchConsistencyCheck(int consistency) {
   8099         return onConsistencyCheck(consistency);
   8100     }
   8101 
   8102     /**
   8103      * Method that subclasses should implement to check their consistency. The type of
   8104      * consistency check is indicated by the bit field passed as a parameter.
   8105      *
   8106      * @param consistency The type of consistency. See ViewDebug for more information.
   8107      *
   8108      * @throws IllegalStateException if the view is in an inconsistent state.
   8109      *
   8110      * @hide
   8111      */
   8112     protected boolean onConsistencyCheck(int consistency) {
   8113         boolean result = true;
   8114 
   8115         final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
   8116         final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
   8117 
   8118         if (checkLayout) {
   8119             if (getParent() == null) {
   8120                 result = false;
   8121                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
   8122                         "View " + this + " does not have a parent.");
   8123             }
   8124 
   8125             if (mAttachInfo == null) {
   8126                 result = false;
   8127                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
   8128                         "View " + this + " is not attached to a window.");
   8129             }
   8130         }
   8131 
   8132         if (checkDrawing) {
   8133             // Do not check the DIRTY/DRAWN flags because views can call invalidate()
   8134             // from their draw() method
   8135 
   8136             if ((mPrivateFlags & DRAWN) != DRAWN &&
   8137                     (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
   8138                 result = false;
   8139                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
   8140                         "View " + this + " was invalidated but its drawing cache is valid.");
   8141             }
   8142         }
   8143 
   8144         return result;
   8145     }
   8146 
   8147     /**
   8148      * Prints information about this view in the log output, with the tag
   8149      * {@link #VIEW_LOG_TAG}.
   8150      *
   8151      * @hide
   8152      */
   8153     public void debug() {
   8154         debug(0);
   8155     }
   8156 
   8157     /**
   8158      * Prints information about this view in the log output, with the tag
   8159      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
   8160      * indentation defined by the <code>depth</code>.
   8161      *
   8162      * @param depth the indentation level
   8163      *
   8164      * @hide
   8165      */
   8166     protected void debug(int depth) {
   8167         String output = debugIndent(depth - 1);
   8168 
   8169         output += "+ " + this;
   8170         int id = getId();
   8171         if (id != -1) {
   8172             output += " (id=" + id + ")";
   8173         }
   8174         Object tag = getTag();
   8175         if (tag != null) {
   8176             output += " (tag=" + tag + ")";
   8177         }
   8178         Log.d(VIEW_LOG_TAG, output);
   8179 
   8180         if ((mPrivateFlags & FOCUSED) != 0) {
   8181             output = debugIndent(depth) + " FOCUSED";
   8182             Log.d(VIEW_LOG_TAG, output);
   8183         }
   8184 
   8185         output = debugIndent(depth);
   8186         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
   8187                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
   8188                 + "} ";
   8189         Log.d(VIEW_LOG_TAG, output);
   8190 
   8191         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
   8192                 || mPaddingBottom != 0) {
   8193             output = debugIndent(depth);
   8194             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
   8195                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
   8196             Log.d(VIEW_LOG_TAG, output);
   8197         }
   8198 
   8199         output = debugIndent(depth);
   8200         output += "mMeasureWidth=" + mMeasuredWidth +
   8201                 " mMeasureHeight=" + mMeasuredHeight;
   8202         Log.d(VIEW_LOG_TAG, output);
   8203 
   8204         output = debugIndent(depth);
   8205         if (mLayoutParams == null) {
   8206             output += "BAD! no layout params";
   8207         } else {
   8208             output = mLayoutParams.debug(output);
   8209         }
   8210         Log.d(VIEW_LOG_TAG, output);
   8211 
   8212         output = debugIndent(depth);
   8213         output += "flags={";
   8214         output += View.printFlags(mViewFlags);
   8215         output += "}";
   8216         Log.d(VIEW_LOG_TAG, output);
   8217 
   8218         output = debugIndent(depth);
   8219         output += "privateFlags={";
   8220         output += View.printPrivateFlags(mPrivateFlags);
   8221         output += "}";
   8222         Log.d(VIEW_LOG_TAG, output);
   8223     }
   8224 
   8225     /**
   8226      * Creates an string of whitespaces used for indentation.
   8227      *
   8228      * @param depth the indentation level
   8229      * @return a String containing (depth * 2 + 3) * 2 white spaces
   8230      *
   8231      * @hide
   8232      */
   8233     protected static String debugIndent(int depth) {
   8234         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
   8235         for (int i = 0; i < (depth * 2) + 3; i++) {
   8236             spaces.append(' ').append(' ');
   8237         }
   8238         return spaces.toString();
   8239     }
   8240 
   8241     /**
   8242      * <p>Return the offset of the widget's text baseline from the widget's top
   8243      * boundary. If this widget does not support baseline alignment, this
   8244      * method returns -1. </p>
   8245      *
   8246      * @return the offset of the baseline within the widget's bounds or -1
   8247      *         if baseline alignment is not supported
   8248      */
   8249     @ViewDebug.ExportedProperty(category = "layout")
   8250     public int getBaseline() {
   8251         return -1;
   8252     }
   8253 
   8254     /**
   8255      * Call this when something has changed which has invalidated the
   8256      * layout of this view. This will schedule a layout pass of the view
   8257      * tree.
   8258      */
   8259     public void requestLayout() {
   8260         if (ViewDebug.TRACE_HIERARCHY) {
   8261             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
   8262         }
   8263 
   8264         mPrivateFlags |= FORCE_LAYOUT;
   8265 
   8266         if (mParent != null && !mParent.isLayoutRequested()) {
   8267             mParent.requestLayout();
   8268         }
   8269     }
   8270 
   8271     /**
   8272      * Forces this view to be laid out during the next layout pass.
   8273      * This method does not call requestLayout() or forceLayout()
   8274      * on the parent.
   8275      */
   8276     public void forceLayout() {
   8277         mPrivateFlags |= FORCE_LAYOUT;
   8278     }
   8279 
   8280     /**
   8281      * <p>
   8282      * This is called to find out how big a view should be. The parent
   8283      * supplies constraint information in the width and height parameters.
   8284      * </p>
   8285      *
   8286      * <p>
   8287      * The actual mesurement work of a view is performed in
   8288      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
   8289      * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
   8290      * </p>
   8291      *
   8292      *
   8293      * @param widthMeasureSpec Horizontal space requirements as imposed by the
   8294      *        parent
   8295      * @param heightMeasureSpec Vertical space requirements as imposed by the
   8296      *        parent
   8297      *
   8298      * @see #onMeasure(int, int)
   8299      */
   8300     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
   8301         if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
   8302                 widthMeasureSpec != mOldWidthMeasureSpec ||
   8303                 heightMeasureSpec != mOldHeightMeasureSpec) {
   8304 
   8305             // first clears the measured dimension flag
   8306             mPrivateFlags &= ~MEASURED_DIMENSION_SET;
   8307 
   8308             if (ViewDebug.TRACE_HIERARCHY) {
   8309                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
   8310             }
   8311 
   8312             // measure ourselves, this should set the measured dimension flag back
   8313             onMeasure(widthMeasureSpec, heightMeasureSpec);
   8314 
   8315             // flag not set, setMeasuredDimension() was not invoked, we raise
   8316             // an exception to warn the developer
   8317             if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
   8318                 throw new IllegalStateException("onMeasure() did not set the"
   8319                         + " measured dimension by calling"
   8320                         + " setMeasuredDimension()");
   8321             }
   8322 
   8323             mPrivateFlags |= LAYOUT_REQUIRED;
   8324         }
   8325 
   8326         mOldWidthMeasureSpec = widthMeasureSpec;
   8327         mOldHeightMeasureSpec = heightMeasureSpec;
   8328     }
   8329 
   8330     /**
   8331      * <p>
   8332      * Measure the view and its content to determine the measured width and the
   8333      * measured height. This method is invoked by {@link #measure(int, int)} and
   8334      * should be overriden by subclasses to provide accurate and efficient
   8335      * measurement of their contents.
   8336      * </p>
   8337      *
   8338      * <p>
   8339      * <strong>CONTRACT:</strong> When overriding this method, you
   8340      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
   8341      * measured width and height of this view. Failure to do so will trigger an
   8342      * <code>IllegalStateException</code>, thrown by
   8343      * {@link #measure(int, int)}. Calling the superclass'
   8344      * {@link #onMeasure(int, int)} is a valid use.
   8345      * </p>
   8346      *
   8347      * <p>
   8348      * The base class implementation of measure defaults to the background size,
   8349      * unless a larger size is allowed by the MeasureSpec. Subclasses should
   8350      * override {@link #onMeasure(int, int)} to provide better measurements of
   8351      * their content.
   8352      * </p>
   8353      *
   8354      * <p>
   8355      * If this method is overridden, it is the subclass's responsibility to make
   8356      * sure the measured height and width are at least the view's minimum height
   8357      * and width ({@link #getSuggestedMinimumHeight()} and
   8358      * {@link #getSuggestedMinimumWidth()}).
   8359      * </p>
   8360      *
   8361      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
   8362      *                         The requirements are encoded with
   8363      *                         {@link android.view.View.MeasureSpec}.
   8364      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
   8365      *                         The requirements are encoded with
   8366      *                         {@link android.view.View.MeasureSpec}.
   8367      *
   8368      * @see #getMeasuredWidth()
   8369      * @see #getMeasuredHeight()
   8370      * @see #setMeasuredDimension(int, int)
   8371      * @see #getSuggestedMinimumHeight()
   8372      * @see #getSuggestedMinimumWidth()
   8373      * @see android.view.View.MeasureSpec#getMode(int)
   8374      * @see android.view.View.MeasureSpec#getSize(int)
   8375      */
   8376     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   8377         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
   8378                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
   8379     }
   8380 
   8381     /**
   8382      * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
   8383      * measured width and measured height. Failing to do so will trigger an
   8384      * exception at measurement time.</p>
   8385      *
   8386      * @param measuredWidth the measured width of this view
   8387      * @param measuredHeight the measured height of this view
   8388      */
   8389     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
   8390         mMeasuredWidth = measuredWidth;
   8391         mMeasuredHeight = measuredHeight;
   8392 
   8393         mPrivateFlags |= MEASURED_DIMENSION_SET;
   8394     }
   8395 
   8396     /**
   8397      * Utility to reconcile a desired size with constraints imposed by a MeasureSpec.
   8398      * Will take the desired size, unless a different size is imposed by the constraints.
   8399      *
   8400      * @param size How big the view wants to be
   8401      * @param measureSpec Constraints imposed by the parent
   8402      * @return The size this view should be.
   8403      */
   8404     public static int resolveSize(int size, int measureSpec) {
   8405         int result = size;
   8406         int specMode = MeasureSpec.getMode(measureSpec);
   8407         int specSize =  MeasureSpec.getSize(measureSpec);
   8408         switch (specMode) {
   8409         case MeasureSpec.UNSPECIFIED:
   8410             result = size;
   8411             break;
   8412         case MeasureSpec.AT_MOST:
   8413             result = Math.min(size, specSize);
   8414             break;
   8415         case MeasureSpec.EXACTLY:
   8416             result = specSize;
   8417             break;
   8418         }
   8419         return result;
   8420     }
   8421 
   8422     /**
   8423      * Utility to return a default size. Uses the supplied size if the
   8424      * MeasureSpec imposed no contraints. Will get larger if allowed
   8425      * by the MeasureSpec.
   8426      *
   8427      * @param size Default size for this view
   8428      * @param measureSpec Constraints imposed by the parent
   8429      * @return The size this view should be.
   8430      */
   8431     public static int getDefaultSize(int size, int measureSpec) {
   8432         int result = size;
   8433         int specMode = MeasureSpec.getMode(measureSpec);
   8434         int specSize =  MeasureSpec.getSize(measureSpec);
   8435 
   8436         switch (specMode) {
   8437         case MeasureSpec.UNSPECIFIED:
   8438             result = size;
   8439             break;
   8440         case MeasureSpec.AT_MOST:
   8441         case MeasureSpec.EXACTLY:
   8442             result = specSize;
   8443             break;
   8444         }
   8445         return result;
   8446     }
   8447 
   8448     /**
   8449      * Returns the suggested minimum height that the view should use. This
   8450      * returns the maximum of the view's minimum height
   8451      * and the background's minimum height
   8452      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
   8453      * <p>
   8454      * When being used in {@link #onMeasure(int, int)}, the caller should still
   8455      * ensure the returned height is within the requirements of the parent.
   8456      *
   8457      * @return The suggested minimum height of the view.
   8458      */
   8459     protected int getSuggestedMinimumHeight() {
   8460         int suggestedMinHeight = mMinHeight;
   8461 
   8462         if (mBGDrawable != null) {
   8463             final int bgMinHeight = mBGDrawable.getMinimumHeight();
   8464             if (suggestedMinHeight < bgMinHeight) {
   8465                 suggestedMinHeight = bgMinHeight;
   8466             }
   8467         }
   8468 
   8469         return suggestedMinHeight;
   8470     }
   8471 
   8472     /**
   8473      * Returns the suggested minimum width that the view should use. This
   8474      * returns the maximum of the view's minimum width)
   8475      * and the background's minimum width
   8476      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
   8477      * <p>
   8478      * When being used in {@link #onMeasure(int, int)}, the caller should still
   8479      * ensure the returned width is within the requirements of the parent.
   8480      *
   8481      * @return The suggested minimum width of the view.
   8482      */
   8483     protected int getSuggestedMinimumWidth() {
   8484         int suggestedMinWidth = mMinWidth;
   8485 
   8486         if (mBGDrawable != null) {
   8487             final int bgMinWidth = mBGDrawable.getMinimumWidth();
   8488             if (suggestedMinWidth < bgMinWidth) {
   8489                 suggestedMinWidth = bgMinWidth;
   8490             }
   8491         }
   8492 
   8493         return suggestedMinWidth;
   8494     }
   8495 
   8496     /**
   8497      * Sets the minimum height of the view. It is not guaranteed the view will
   8498      * be able to achieve this minimum height (for example, if its parent layout
   8499      * constrains it with less available height).
   8500      *
   8501      * @param minHeight The minimum height the view will try to be.
   8502      */
   8503     public void setMinimumHeight(int minHeight) {
   8504         mMinHeight = minHeight;
   8505     }
   8506 
   8507     /**
   8508      * Sets the minimum width of the view. It is not guaranteed the view will
   8509      * be able to achieve this minimum width (for example, if its parent layout
   8510      * constrains it with less available width).
   8511      *
   8512      * @param minWidth The minimum width the view will try to be.
   8513      */
   8514     public void setMinimumWidth(int minWidth) {
   8515         mMinWidth = minWidth;
   8516     }
   8517 
   8518     /**
   8519      * Get the animation currently associated with this view.
   8520      *
   8521      * @return The animation that is currently playing or
   8522      *         scheduled to play for this view.
   8523      */
   8524     public Animation getAnimation() {
   8525         return mCurrentAnimation;
   8526     }
   8527 
   8528     /**
   8529      * Start the specified animation now.
   8530      *
   8531      * @param animation the animation to start now
   8532      */
   8533     public void startAnimation(Animation animation) {
   8534         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
   8535         setAnimation(animation);
   8536         invalidate();
   8537     }
   8538 
   8539     /**
   8540      * Cancels any animations for this view.
   8541      */
   8542     public void clearAnimation() {
   8543         if (mCurrentAnimation != null) {
   8544             mCurrentAnimation.detach();
   8545         }
   8546         mCurrentAnimation = null;
   8547     }
   8548 
   8549     /**
   8550      * Sets the next animation to play for this view.
   8551      * If you want the animation to play immediately, use
   8552      * startAnimation. This method provides allows fine-grained
   8553      * control over the start time and invalidation, but you
   8554      * must make sure that 1) the animation has a start time set, and
   8555      * 2) the view will be invalidated when the animation is supposed to
   8556      * start.
   8557      *
   8558      * @param animation The next animation, or null.
   8559      */
   8560     public void setAnimation(Animation animation) {
   8561         mCurrentAnimation = animation;
   8562         if (animation != null) {
   8563             animation.reset();
   8564         }
   8565     }
   8566 
   8567     /**
   8568      * Invoked by a parent ViewGroup to notify the start of the animation
   8569      * currently associated with this view. If you override this method,
   8570      * always call super.onAnimationStart();
   8571      *
   8572      * @see #setAnimation(android.view.animation.Animation)
   8573      * @see #getAnimation()
   8574      */
   8575     protected void onAnimationStart() {
   8576         mPrivateFlags |= ANIMATION_STARTED;
   8577     }
   8578 
   8579     /**
   8580      * Invoked by a parent ViewGroup to notify the end of the animation
   8581      * currently associated with this view. If you override this method,
   8582      * always call super.onAnimationEnd();
   8583      *
   8584      * @see #setAnimation(android.view.animation.Animation)
   8585      * @see #getAnimation()
   8586      */
   8587     protected void onAnimationEnd() {
   8588         mPrivateFlags &= ~ANIMATION_STARTED;
   8589     }
   8590 
   8591     /**
   8592      * Invoked if there is a Transform that involves alpha. Subclass that can
   8593      * draw themselves with the specified alpha should return true, and then
   8594      * respect that alpha when their onDraw() is called. If this returns false
   8595      * then the view may be redirected to draw into an offscreen buffer to
   8596      * fulfill the request, which will look fine, but may be slower than if the
   8597      * subclass handles it internally. The default implementation returns false.
   8598      *
   8599      * @param alpha The alpha (0..255) to apply to the view's drawing
   8600      * @return true if the view can draw with the specified alpha.
   8601      */
   8602     protected boolean onSetAlpha(int alpha) {
   8603         return false;
   8604     }
   8605 
   8606     /**
   8607      * This is used by the RootView to perform an optimization when
   8608      * the view hierarchy contains one or several SurfaceView.
   8609      * SurfaceView is always considered transparent, but its children are not,
   8610      * therefore all View objects remove themselves from the global transparent
   8611      * region (passed as a parameter to this function).
   8612      *
   8613      * @param region The transparent region for this ViewRoot (window).
   8614      *
   8615      * @return Returns true if the effective visibility of the view at this
   8616      * point is opaque, regardless of the transparent region; returns false
   8617      * if it is possible for underlying windows to be seen behind the view.
   8618      *
   8619      * {@hide}
   8620      */
   8621     public boolean gatherTransparentRegion(Region region) {
   8622         final AttachInfo attachInfo = mAttachInfo;
   8623         if (region != null && attachInfo != null) {
   8624             final int pflags = mPrivateFlags;
   8625             if ((pflags & SKIP_DRAW) == 0) {
   8626                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
   8627                 // remove it from the transparent region.
   8628                 final int[] location = attachInfo.mTransparentLocation;
   8629                 getLocationInWindow(location);
   8630                 region.op(location[0], location[1], location[0] + mRight - mLeft,
   8631                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
   8632             } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
   8633                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
   8634                 // exists, so we remove the background drawable's non-transparent
   8635                 // parts from this transparent region.
   8636                 applyDrawableToTransparentRegion(mBGDrawable, region);
   8637             }
   8638         }
   8639         return true;
   8640     }
   8641 
   8642     /**
   8643      * Play a sound effect for this view.
   8644      *
   8645      * <p>The framework will play sound effects for some built in actions, such as
   8646      * clicking, but you may wish to play these effects in your widget,
   8647      * for instance, for internal navigation.
   8648      *
   8649      * <p>The sound effect will only be played if sound effects are enabled by the user, and
   8650      * {@link #isSoundEffectsEnabled()} is true.
   8651      *
   8652      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
   8653      */
   8654     public void playSoundEffect(int soundConstant) {
   8655         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
   8656             return;
   8657         }
   8658         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
   8659     }
   8660 
   8661     /**
   8662      * BZZZTT!!1!
   8663      *
   8664      * <p>Provide haptic feedback to the user for this view.
   8665      *
   8666      * <p>The framework will provide haptic feedback for some built in actions,
   8667      * such as long presses, but you may wish to provide feedback for your
   8668      * own widget.
   8669      *
   8670      * <p>The feedback will only be performed if
   8671      * {@link #isHapticFeedbackEnabled()} is true.
   8672      *
   8673      * @param feedbackConstant One of the constants defined in
   8674      * {@link HapticFeedbackConstants}
   8675      */
   8676     public boolean performHapticFeedback(int feedbackConstant) {
   8677         return performHapticFeedback(feedbackConstant, 0);
   8678     }
   8679 
   8680     /**
   8681      * BZZZTT!!1!
   8682      *
   8683      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
   8684      *
   8685      * @param feedbackConstant One of the constants defined in
   8686      * {@link HapticFeedbackConstants}
   8687      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
   8688      */
   8689     public boolean performHapticFeedback(int feedbackConstant, int flags) {
   8690         if (mAttachInfo == null) {
   8691             return false;
   8692         }
   8693         if ((flags&HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
   8694                 && !isHapticFeedbackEnabled()) {
   8695             return false;
   8696         }
   8697         return mAttachInfo.mRootCallbacks.performHapticFeedback(
   8698                 feedbackConstant,
   8699                 (flags&HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
   8700     }
   8701 
   8702     /**
   8703      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
   8704      * it is ever exposed at all.
   8705      * @hide
   8706      */
   8707     public void onCloseSystemDialogs(String reason) {
   8708     }
   8709 
   8710     /**
   8711      * Given a Drawable whose bounds have been set to draw into this view,
   8712      * update a Region being computed for {@link #gatherTransparentRegion} so
   8713      * that any non-transparent parts of the Drawable are removed from the
   8714      * given transparent region.
   8715      *
   8716      * @param dr The Drawable whose transparency is to be applied to the region.
   8717      * @param region A Region holding the current transparency information,
   8718      * where any parts of the region that are set are considered to be
   8719      * transparent.  On return, this region will be modified to have the
   8720      * transparency information reduced by the corresponding parts of the
   8721      * Drawable that are not transparent.
   8722      * {@hide}
   8723      */
   8724     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
   8725         if (DBG) {
   8726             Log.i("View", "Getting transparent region for: " + this);
   8727         }
   8728         final Region r = dr.getTransparentRegion();
   8729         final Rect db = dr.getBounds();
   8730         final AttachInfo attachInfo = mAttachInfo;
   8731         if (r != null && attachInfo != null) {
   8732             final int w = getRight()-getLeft();
   8733             final int h = getBottom()-getTop();
   8734             if (db.left > 0) {
   8735                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
   8736                 r.op(0, 0, db.left, h, Region.Op.UNION);
   8737             }
   8738             if (db.right < w) {
   8739                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
   8740                 r.op(db.right, 0, w, h, Region.Op.UNION);
   8741             }
   8742             if (db.top > 0) {
   8743                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
   8744                 r.op(0, 0, w, db.top, Region.Op.UNION);
   8745             }
   8746             if (db.bottom < h) {
   8747                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
   8748                 r.op(0, db.bottom, w, h, Region.Op.UNION);
   8749             }
   8750             final int[] location = attachInfo.mTransparentLocation;
   8751             getLocationInWindow(location);
   8752             r.translate(location[0], location[1]);
   8753             region.op(r, Region.Op.INTERSECT);
   8754         } else {
   8755             region.op(db, Region.Op.DIFFERENCE);
   8756         }
   8757     }
   8758 
   8759     private void postCheckForLongClick(int delayOffset) {
   8760         mHasPerformedLongPress = false;
   8761 
   8762         if (mPendingCheckForLongPress == null) {
   8763             mPendingCheckForLongPress = new CheckForLongPress();
   8764         }
   8765         mPendingCheckForLongPress.rememberWindowAttachCount();
   8766         postDelayed(mPendingCheckForLongPress,
   8767                 ViewConfiguration.getLongPressTimeout() - delayOffset);
   8768     }
   8769 
   8770     private static int[] stateSetUnion(final int[] stateSet1,
   8771                                        final int[] stateSet2) {
   8772         final int stateSet1Length = stateSet1.length;
   8773         final int stateSet2Length = stateSet2.length;
   8774         final int[] newSet = new int[stateSet1Length + stateSet2Length];
   8775         int k = 0;
   8776         int i = 0;
   8777         int j = 0;
   8778         // This is a merge of the two input state sets and assumes that the
   8779         // input sets are sorted by the order imposed by ViewDrawableStates.
   8780         for (int viewState : R.styleable.ViewDrawableStates) {
   8781             if (i < stateSet1Length && stateSet1[i] == viewState) {
   8782                 newSet[k++] = viewState;
   8783                 i++;
   8784             } else if (j < stateSet2Length && stateSet2[j] == viewState) {
   8785                 newSet[k++] = viewState;
   8786                 j++;
   8787             }
   8788             if (k > 1) {
   8789                 assert(newSet[k - 1] > newSet[k - 2]);
   8790             }
   8791         }
   8792         return newSet;
   8793     }
   8794 
   8795     /**
   8796      * Inflate a view from an XML resource.  This convenience method wraps the {@link
   8797      * LayoutInflater} class, which provides a full range of options for view inflation.
   8798      *
   8799      * @param context The Context object for your activity or application.
   8800      * @param resource The resource ID to inflate
   8801      * @param root A view group that will be the parent.  Used to properly inflate the
   8802      * layout_* parameters.
   8803      * @see LayoutInflater
   8804      */
   8805     public static View inflate(Context context, int resource, ViewGroup root) {
   8806         LayoutInflater factory = LayoutInflater.from(context);
   8807         return factory.inflate(resource, root);
   8808     }
   8809 
   8810     /**
   8811      * Scroll the view with standard behavior for scrolling beyond the normal
   8812      * content boundaries. Views that call this method should override
   8813      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
   8814      * results of an over-scroll operation.
   8815      *
   8816      * Views can use this method to handle any touch or fling-based scrolling.
   8817      *
   8818      * @param deltaX Change in X in pixels
   8819      * @param deltaY Change in Y in pixels
   8820      * @param scrollX Current X scroll value in pixels before applying deltaX
   8821      * @param scrollY Current Y scroll value in pixels before applying deltaY
   8822      * @param scrollRangeX Maximum content scroll range along the X axis
   8823      * @param scrollRangeY Maximum content scroll range along the Y axis
   8824      * @param maxOverScrollX Number of pixels to overscroll by in either direction
   8825      *          along the X axis.
   8826      * @param maxOverScrollY Number of pixels to overscroll by in either direction
   8827      *          along the Y axis.
   8828      * @param isTouchEvent true if this scroll operation is the result of a touch event.
   8829      * @return true if scrolling was clamped to an over-scroll boundary along either
   8830      *          axis, false otherwise.
   8831      */
   8832     protected boolean overScrollBy(int deltaX, int deltaY,
   8833             int scrollX, int scrollY,
   8834             int scrollRangeX, int scrollRangeY,
   8835             int maxOverScrollX, int maxOverScrollY,
   8836             boolean isTouchEvent) {
   8837         final int overScrollMode = mOverScrollMode;
   8838         final boolean canScrollHorizontal =
   8839                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
   8840         final boolean canScrollVertical =
   8841                 computeVerticalScrollRange() > computeVerticalScrollExtent();
   8842         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
   8843                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
   8844         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
   8845                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
   8846 
   8847         int newScrollX = scrollX + deltaX;
   8848         if (!overScrollHorizontal) {
   8849             maxOverScrollX = 0;
   8850         }
   8851 
   8852         int newScrollY = scrollY + deltaY;
   8853         if (!overScrollVertical) {
   8854             maxOverScrollY = 0;
   8855         }
   8856 
   8857         // Clamp values if at the limits and record
   8858         final int left = -maxOverScrollX;
   8859         final int right = maxOverScrollX + scrollRangeX;
   8860         final int top = -maxOverScrollY;
   8861         final int bottom = maxOverScrollY + scrollRangeY;
   8862 
   8863         boolean clampedX = false;
   8864         if (newScrollX > right) {
   8865             newScrollX = right;
   8866             clampedX = true;
   8867         } else if (newScrollX < left) {
   8868             newScrollX = left;
   8869             clampedX = true;
   8870         }
   8871 
   8872         boolean clampedY = false;
   8873         if (newScrollY > bottom) {
   8874             newScrollY = bottom;
   8875             clampedY = true;
   8876         } else if (newScrollY < top) {
   8877             newScrollY = top;
   8878             clampedY = true;
   8879         }
   8880 
   8881         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
   8882 
   8883         return clampedX || clampedY;
   8884     }
   8885 
   8886     /**
   8887      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
   8888      * respond to the results of an over-scroll operation.
   8889      *
   8890      * @param scrollX New X scroll value in pixels
   8891      * @param scrollY New Y scroll value in pixels
   8892      * @param clampedX True if scrollX was clamped to an over-scroll boundary
   8893      * @param clampedY True if scrollY was clamped to an over-scroll boundary
   8894      */
   8895     protected void onOverScrolled(int scrollX, int scrollY,
   8896             boolean clampedX, boolean clampedY) {
   8897         // Intentionally empty.
   8898     }
   8899 
   8900     /**
   8901      * Returns the over-scroll mode for this view. The result will be
   8902      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   8903      * (allow over-scrolling only if the view content is larger than the container),
   8904      * or {@link #OVER_SCROLL_NEVER}.
   8905      *
   8906      * @return This view's over-scroll mode.
   8907      */
   8908     public int getOverScrollMode() {
   8909         return mOverScrollMode;
   8910     }
   8911 
   8912     /**
   8913      * Set the over-scroll mode for this view. Valid over-scroll modes are
   8914      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   8915      * (allow over-scrolling only if the view content is larger than the container),
   8916      * or {@link #OVER_SCROLL_NEVER}.
   8917      *
   8918      * Setting the over-scroll mode of a view will have an effect only if the
   8919      * view is capable of scrolling.
   8920      *
   8921      * @param overScrollMode The new over-scroll mode for this view.
   8922      */
   8923     public void setOverScrollMode(int overScrollMode) {
   8924         if (overScrollMode != OVER_SCROLL_ALWAYS &&
   8925                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
   8926                 overScrollMode != OVER_SCROLL_NEVER) {
   8927             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
   8928         }
   8929         mOverScrollMode = overScrollMode;
   8930     }
   8931 
   8932     /**
   8933      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
   8934      * Each MeasureSpec represents a requirement for either the width or the height.
   8935      * A MeasureSpec is comprised of a size and a mode. There are three possible
   8936      * modes:
   8937      * <dl>
   8938      * <dt>UNSPECIFIED</dt>
   8939      * <dd>
   8940      * The parent has not imposed any constraint on the child. It can be whatever size
   8941      * it wants.
   8942      * </dd>
   8943      *
   8944      * <dt>EXACTLY</dt>
   8945      * <dd>
   8946      * The parent has determined an exact size for the child. The child is going to be
   8947      * given those bounds regardless of how big it wants to be.
   8948      * </dd>
   8949      *
   8950      * <dt>AT_MOST</dt>
   8951      * <dd>
   8952      * The child can be as large as it wants up to the specified size.
   8953      * </dd>
   8954      * </dl>
   8955      *
   8956      * MeasureSpecs are implemented as ints to reduce object allocation. This class
   8957      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
   8958      */
   8959     public static class MeasureSpec {
   8960         private static final int MODE_SHIFT = 30;
   8961         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
   8962 
   8963         /**
   8964          * Measure specification mode: The parent has not imposed any constraint
   8965          * on the child. It can be whatever size it wants.
   8966          */
   8967         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
   8968 
   8969         /**
   8970          * Measure specification mode: The parent has determined an exact size
   8971          * for the child. The child is going to be given those bounds regardless
   8972          * of how big it wants to be.
   8973          */
   8974         public static final int EXACTLY     = 1 << MODE_SHIFT;
   8975 
   8976         /**
   8977          * Measure specification mode: The child can be as large as it wants up
   8978          * to the specified size.
   8979          */
   8980         public static final int AT_MOST     = 2 << MODE_SHIFT;
   8981 
   8982         /**
   8983          * Creates a measure specification based on the supplied size and mode.
   8984          *
   8985          * The mode must always be one of the following:
   8986          * <ul>
   8987          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
   8988          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
   8989          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
   8990          * </ul>
   8991          *
   8992          * @param size the size of the measure specification
   8993          * @param mode the mode of the measure specification
   8994          * @return the measure specification based on size and mode
   8995          */
   8996         public static int makeMeasureSpec(int size, int mode) {
   8997             return size + mode;
   8998         }
   8999 
   9000         /**
   9001          * Extracts the mode from the supplied measure specification.
   9002          *
   9003          * @param measureSpec the measure specification to extract the mode from
   9004          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
   9005          *         {@link android.view.View.MeasureSpec#AT_MOST} or
   9006          *         {@link android.view.View.MeasureSpec#EXACTLY}
   9007          */
   9008         public static int getMode(int measureSpec) {
   9009             return (measureSpec & MODE_MASK);
   9010         }
   9011 
   9012         /**
   9013          * Extracts the size from the supplied measure specification.
   9014          *
   9015          * @param measureSpec the measure specification to extract the size from
   9016          * @return the size in pixels defined in the supplied measure specification
   9017          */
   9018         public static int getSize(int measureSpec) {
   9019             return (measureSpec & ~MODE_MASK);
   9020         }
   9021 
   9022         /**
   9023          * Returns a String representation of the specified measure
   9024          * specification.
   9025          *
   9026          * @param measureSpec the measure specification to convert to a String
   9027          * @return a String with the following format: "MeasureSpec: MODE SIZE"
   9028          */
   9029         public static String toString(int measureSpec) {
   9030             int mode = getMode(measureSpec);
   9031             int size = getSize(measureSpec);
   9032 
   9033             StringBuilder sb = new StringBuilder("MeasureSpec: ");
   9034 
   9035             if (mode == UNSPECIFIED)
   9036                 sb.append("UNSPECIFIED ");
   9037             else if (mode == EXACTLY)
   9038                 sb.append("EXACTLY ");
   9039             else if (mode == AT_MOST)
   9040                 sb.append("AT_MOST ");
   9041             else
   9042                 sb.append(mode).append(" ");
   9043 
   9044             sb.append(size);
   9045             return sb.toString();
   9046         }
   9047     }
   9048 
   9049     class CheckForLongPress implements Runnable {
   9050 
   9051         private int mOriginalWindowAttachCount;
   9052 
   9053         public void run() {
   9054             if (isPressed() && (mParent != null)
   9055                     && mOriginalWindowAttachCount == mWindowAttachCount) {
   9056                 if (performLongClick()) {
   9057                     mHasPerformedLongPress = true;
   9058                 }
   9059             }
   9060         }
   9061 
   9062         public void rememberWindowAttachCount() {
   9063             mOriginalWindowAttachCount = mWindowAttachCount;
   9064         }
   9065     }
   9066 
   9067     private final class CheckForTap implements Runnable {
   9068         public void run() {
   9069             mPrivateFlags &= ~PREPRESSED;
   9070             mPrivateFlags |= PRESSED;
   9071             refreshDrawableState();
   9072             if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
   9073                 postCheckForLongClick(ViewConfiguration.getTapTimeout());
   9074             }
   9075         }
   9076     }
   9077 
   9078     private final class PerformClick implements Runnable {
   9079         public void run() {
   9080             performClick();
   9081         }
   9082     }
   9083 
   9084     /**
   9085      * Interface definition for a callback to be invoked when a key event is
   9086      * dispatched to this view. The callback will be invoked before the key
   9087      * event is given to the view.
   9088      */
   9089     public interface OnKeyListener {
   9090         /**
   9091          * Called when a key is dispatched to a view. This allows listeners to
   9092          * get a chance to respond before the target view.
   9093          *
   9094          * @param v The view the key has been dispatched to.
   9095          * @param keyCode The code for the physical key that was pressed
   9096          * @param event The KeyEvent object containing full information about
   9097          *        the event.
   9098          * @return True if the listener has consumed the event, false otherwise.
   9099          */
   9100         boolean onKey(View v, int keyCode, KeyEvent event);
   9101     }
   9102 
   9103     /**
   9104      * Interface definition for a callback to be invoked when a touch event is
   9105      * dispatched to this view. The callback will be invoked before the touch
   9106      * event is given to the view.
   9107      */
   9108     public interface OnTouchListener {
   9109         /**
   9110          * Called when a touch event is dispatched to a view. This allows listeners to
   9111          * get a chance to respond before the target view.
   9112          *
   9113          * @param v The view the touch event has been dispatched to.
   9114          * @param event The MotionEvent object containing full information about
   9115          *        the event.
   9116          * @return True if the listener has consumed the event, false otherwise.
   9117          */
   9118         boolean onTouch(View v, MotionEvent event);
   9119     }
   9120 
   9121     /**
   9122      * Interface definition for a callback to be invoked when a view has been clicked and held.
   9123      */
   9124     public interface OnLongClickListener {
   9125         /**
   9126          * Called when a view has been clicked and held.
   9127          *
   9128          * @param v The view that was clicked and held.
   9129          *
   9130          * return True if the callback consumed the long click, false otherwise
   9131          */
   9132         boolean onLongClick(View v);
   9133     }
   9134 
   9135     /**
   9136      * Interface definition for a callback to be invoked when the focus state of
   9137      * a view changed.
   9138      */
   9139     public interface OnFocusChangeListener {
   9140         /**
   9141          * Called when the focus state of a view has changed.
   9142          *
   9143          * @param v The view whose state has changed.
   9144          * @param hasFocus The new focus state of v.
   9145          */
   9146         void onFocusChange(View v, boolean hasFocus);
   9147     }
   9148 
   9149     /**
   9150      * Interface definition for a callback to be invoked when a view is clicked.
   9151      */
   9152     public interface OnClickListener {
   9153         /**
   9154          * Called when a view has been clicked.
   9155          *
   9156          * @param v The view that was clicked.
   9157          */
   9158         void onClick(View v);
   9159     }
   9160 
   9161     /**
   9162      * Interface definition for a callback to be invoked when the context menu
   9163      * for this view is being built.
   9164      */
   9165     public interface OnCreateContextMenuListener {
   9166         /**
   9167          * Called when the context menu for this view is being built. It is not
   9168          * safe to hold onto the menu after this method returns.
   9169          *
   9170          * @param menu The context menu that is being built
   9171          * @param v The view for which the context menu is being built
   9172          * @param menuInfo Extra information about the item for which the
   9173          *            context menu should be shown. This information will vary
   9174          *            depending on the class of v.
   9175          */
   9176         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
   9177     }
   9178 
   9179     private final class UnsetPressedState implements Runnable {
   9180         public void run() {
   9181             setPressed(false);
   9182         }
   9183     }
   9184 
   9185     /**
   9186      * Base class for derived classes that want to save and restore their own
   9187      * state in {@link android.view.View#onSaveInstanceState()}.
   9188      */
   9189     public static class BaseSavedState extends AbsSavedState {
   9190         /**
   9191          * Constructor used when reading from a parcel. Reads the state of the superclass.
   9192          *
   9193          * @param source
   9194          */
   9195         public BaseSavedState(Parcel source) {
   9196             super(source);
   9197         }
   9198 
   9199         /**
   9200          * Constructor called by derived classes when creating their SavedState objects
   9201          *
   9202          * @param superState The state of the superclass of this view
   9203          */
   9204         public BaseSavedState(Parcelable superState) {
   9205             super(superState);
   9206         }
   9207 
   9208         public static final Parcelable.Creator<BaseSavedState> CREATOR =
   9209                 new Parcelable.Creator<BaseSavedState>() {
   9210             public BaseSavedState createFromParcel(Parcel in) {
   9211                 return new BaseSavedState(in);
   9212             }
   9213 
   9214             public BaseSavedState[] newArray(int size) {
   9215                 return new BaseSavedState[size];
   9216             }
   9217         };
   9218     }
   9219 
   9220     /**
   9221      * A set of information given to a view when it is attached to its parent
   9222      * window.
   9223      */
   9224     static class AttachInfo {
   9225         interface Callbacks {
   9226             void playSoundEffect(int effectId);
   9227             boolean performHapticFeedback(int effectId, boolean always);
   9228         }
   9229 
   9230         /**
   9231          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
   9232          * to a Handler. This class contains the target (View) to invalidate and
   9233          * the coordinates of the dirty rectangle.
   9234          *
   9235          * For performance purposes, this class also implements a pool of up to
   9236          * POOL_LIMIT objects that get reused. This reduces memory allocations
   9237          * whenever possible.
   9238          */
   9239         static class InvalidateInfo implements Poolable<InvalidateInfo> {
   9240             private static final int POOL_LIMIT = 10;
   9241             private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
   9242                     Pools.finitePool(new PoolableManager<InvalidateInfo>() {
   9243                         public InvalidateInfo newInstance() {
   9244                             return new InvalidateInfo();
   9245                         }
   9246 
   9247                         public void onAcquired(InvalidateInfo element) {
   9248                         }
   9249 
   9250                         public void onReleased(InvalidateInfo element) {
   9251                         }
   9252                     }, POOL_LIMIT)
   9253             );
   9254 
   9255             private InvalidateInfo mNext;
   9256 
   9257             View target;
   9258 
   9259             int left;
   9260             int top;
   9261             int right;
   9262             int bottom;
   9263 
   9264             public void setNextPoolable(InvalidateInfo element) {
   9265                 mNext = element;
   9266             }
   9267 
   9268             public InvalidateInfo getNextPoolable() {
   9269                 return mNext;
   9270             }
   9271 
   9272             static InvalidateInfo acquire() {
   9273                 return sPool.acquire();
   9274             }
   9275 
   9276             void release() {
   9277                 sPool.release(this);
   9278             }
   9279         }
   9280 
   9281         final IWindowSession mSession;
   9282 
   9283         final IWindow mWindow;
   9284 
   9285         final IBinder mWindowToken;
   9286 
   9287         final Callbacks mRootCallbacks;
   9288 
   9289         /**
   9290          * The top view of the hierarchy.
   9291          */
   9292         View mRootView;
   9293 
   9294         IBinder mPanelParentWindowToken;
   9295         Surface mSurface;
   9296 
   9297         /**
   9298          * Scale factor used by the compatibility mode
   9299          */
   9300         float mApplicationScale;
   9301 
   9302         /**
   9303          * Indicates whether the application is in compatibility mode
   9304          */
   9305         boolean mScalingRequired;
   9306 
   9307         /**
   9308          * Left position of this view's window
   9309          */
   9310         int mWindowLeft;
   9311 
   9312         /**
   9313          * Top position of this view's window
   9314          */
   9315         int mWindowTop;
   9316 
   9317         /**
   9318          * Indicates whether views need to use 32-bit drawing caches
   9319          */
   9320         boolean mUse32BitDrawingCache;
   9321 
   9322         /**
   9323          * For windows that are full-screen but using insets to layout inside
   9324          * of the screen decorations, these are the current insets for the
   9325          * content of the window.
   9326          */
   9327         final Rect mContentInsets = new Rect();
   9328 
   9329         /**
   9330          * For windows that are full-screen but using insets to layout inside
   9331          * of the screen decorations, these are the current insets for the
   9332          * actual visible parts of the window.
   9333          */
   9334         final Rect mVisibleInsets = new Rect();
   9335 
   9336         /**
   9337          * The internal insets given by this window.  This value is
   9338          * supplied by the client (through
   9339          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
   9340          * be given to the window manager when changed to be used in laying
   9341          * out windows behind it.
   9342          */
   9343         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
   9344                 = new ViewTreeObserver.InternalInsetsInfo();
   9345 
   9346         /**
   9347          * All views in the window's hierarchy that serve as scroll containers,
   9348          * used to determine if the window can be resized or must be panned
   9349          * to adjust for a soft input area.
   9350          */
   9351         final ArrayList<View> mScrollContainers = new ArrayList<View>();
   9352 
   9353         final KeyEvent.DispatcherState mKeyDispatchState
   9354                 = new KeyEvent.DispatcherState();
   9355 
   9356         /**
   9357          * Indicates whether the view's window currently has the focus.
   9358          */
   9359         boolean mHasWindowFocus;
   9360 
   9361         /**
   9362          * The current visibility of the window.
   9363          */
   9364         int mWindowVisibility;
   9365 
   9366         /**
   9367          * Indicates the time at which drawing started to occur.
   9368          */
   9369         long mDrawingTime;
   9370 
   9371         /**
   9372          * Indicates whether or not ignoring the DIRTY_MASK flags.
   9373          */
   9374         boolean mIgnoreDirtyState;
   9375 
   9376         /**
   9377          * Indicates whether the view's window is currently in touch mode.
   9378          */
   9379         boolean mInTouchMode;
   9380 
   9381         /**
   9382          * Indicates that ViewRoot should trigger a global layout change
   9383          * the next time it performs a traversal
   9384          */
   9385         boolean mRecomputeGlobalAttributes;
   9386 
   9387         /**
   9388          * Set during a traveral if any views want to keep the screen on.
   9389          */
   9390         boolean mKeepScreenOn;
   9391 
   9392         /**
   9393          * Set if the visibility of any views has changed.
   9394          */
   9395         boolean mViewVisibilityChanged;
   9396 
   9397         /**
   9398          * Set to true if a view has been scrolled.
   9399          */
   9400         boolean mViewScrollChanged;
   9401 
   9402         /**
   9403          * Global to the view hierarchy used as a temporary for dealing with
   9404          * x/y points in the transparent region computations.
   9405          */
   9406         final int[] mTransparentLocation = new int[2];
   9407 
   9408         /**
   9409          * Global to the view hierarchy used as a temporary for dealing with
   9410          * x/y points in the ViewGroup.invalidateChild implementation.
   9411          */
   9412         final int[] mInvalidateChildLocation = new int[2];
   9413 
   9414         /**
   9415          * The view tree observer used to dispatch global events like
   9416          * layout, pre-draw, touch mode change, etc.
   9417          */
   9418         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
   9419 
   9420         /**
   9421          * A Canvas used by the view hierarchy to perform bitmap caching.
   9422          */
   9423         Canvas mCanvas;
   9424 
   9425         /**
   9426          * A Handler supplied by a view's {@link android.view.ViewRoot}. This
   9427          * handler can be used to pump events in the UI events queue.
   9428          */
   9429         final Handler mHandler;
   9430 
   9431         /**
   9432          * Identifier for messages requesting the view to be invalidated.
   9433          * Such messages should be sent to {@link #mHandler}.
   9434          */
   9435         static final int INVALIDATE_MSG = 0x1;
   9436 
   9437         /**
   9438          * Identifier for messages requesting the view to invalidate a region.
   9439          * Such messages should be sent to {@link #mHandler}.
   9440          */
   9441         static final int INVALIDATE_RECT_MSG = 0x2;
   9442 
   9443         /**
   9444          * Temporary for use in computing invalidate rectangles while
   9445          * calling up the hierarchy.
   9446          */
   9447         final Rect mTmpInvalRect = new Rect();
   9448 
   9449         /**
   9450          * Temporary list for use in collecting focusable descendents of a view.
   9451          */
   9452         final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
   9453 
   9454         /**
   9455          * Creates a new set of attachment information with the specified
   9456          * events handler and thread.
   9457          *
   9458          * @param handler the events handler the view must use
   9459          */
   9460         AttachInfo(IWindowSession session, IWindow window,
   9461                 Handler handler, Callbacks effectPlayer) {
   9462             mSession = session;
   9463             mWindow = window;
   9464             mWindowToken = window.asBinder();
   9465             mHandler = handler;
   9466             mRootCallbacks = effectPlayer;
   9467         }
   9468     }
   9469 
   9470     /**
   9471      * <p>ScrollabilityCache holds various fields used by a View when scrolling
   9472      * is supported. This avoids keeping too many unused fields in most
   9473      * instances of View.</p>
   9474      */
   9475     private static class ScrollabilityCache implements Runnable {
   9476 
   9477         /**
   9478          * Scrollbars are not visible
   9479          */
   9480         public static final int OFF = 0;
   9481 
   9482         /**
   9483          * Scrollbars are visible
   9484          */
   9485         public static final int ON = 1;
   9486 
   9487         /**
   9488          * Scrollbars are fading away
   9489          */
   9490         public static final int FADING = 2;
   9491 
   9492         public boolean fadeScrollBars;
   9493 
   9494         public int fadingEdgeLength;
   9495         public int scrollBarDefaultDelayBeforeFade;
   9496         public int scrollBarFadeDuration;
   9497 
   9498         public int scrollBarSize;
   9499         public ScrollBarDrawable scrollBar;
   9500         public float[] interpolatorValues;
   9501         public View host;
   9502 
   9503         public final Paint paint;
   9504         public final Matrix matrix;
   9505         public Shader shader;
   9506 
   9507         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
   9508 
   9509         private final float[] mOpaque = {255.0f};
   9510         private final float[] mTransparent = {0.0f};
   9511 
   9512         /**
   9513          * When fading should start. This time moves into the future every time
   9514          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
   9515          */
   9516         public long fadeStartTime;
   9517 
   9518 
   9519         /**
   9520          * The current state of the scrollbars: ON, OFF, or FADING
   9521          */
   9522         public int state = OFF;
   9523 
   9524         private int mLastColor;
   9525 
   9526         public ScrollabilityCache(ViewConfiguration configuration, View host) {
   9527             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
   9528             scrollBarSize = configuration.getScaledScrollBarSize();
   9529             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
   9530             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
   9531 
   9532             paint = new Paint();
   9533             matrix = new Matrix();
   9534             // use use a height of 1, and then wack the matrix each time we
   9535             // actually use it.
   9536             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   9537 
   9538             paint.setShader(shader);
   9539             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   9540             this.host = host;
   9541         }
   9542 
   9543         public void setFadeColor(int color) {
   9544             if (color != 0 && color != mLastColor) {
   9545                 mLastColor = color;
   9546                 color |= 0xFF000000;
   9547 
   9548                 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
   9549                         color & 0x00FFFFFF, Shader.TileMode.CLAMP);
   9550 
   9551                 paint.setShader(shader);
   9552                 // Restore the default transfer mode (src_over)
   9553                 paint.setXfermode(null);
   9554             }
   9555         }
   9556 
   9557         public void run() {
   9558             long now = AnimationUtils.currentAnimationTimeMillis();
   9559             if (now >= fadeStartTime) {
   9560 
   9561                 // the animation fades the scrollbars out by changing
   9562                 // the opacity (alpha) from fully opaque to fully
   9563                 // transparent
   9564                 int nextFrame = (int) now;
   9565                 int framesCount = 0;
   9566 
   9567                 Interpolator interpolator = scrollBarInterpolator;
   9568 
   9569                 // Start opaque
   9570                 interpolator.setKeyFrame(framesCount++, nextFrame, mOpaque);
   9571 
   9572                 // End transparent
   9573                 nextFrame += scrollBarFadeDuration;
   9574                 interpolator.setKeyFrame(framesCount, nextFrame, mTransparent);
   9575 
   9576                 state = FADING;
   9577 
   9578                 // Kick off the fade animation
   9579                 host.invalidate();
   9580             }
   9581         }
   9582 
   9583     }
   9584 }
   9585