Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.content.ClipData;
     20 import android.content.Context;
     21 import android.content.res.Configuration;
     22 import android.content.res.Resources;
     23 import android.content.res.TypedArray;
     24 import android.graphics.Bitmap;
     25 import android.graphics.Camera;
     26 import android.graphics.Canvas;
     27 import android.graphics.Interpolator;
     28 import android.graphics.LinearGradient;
     29 import android.graphics.Matrix;
     30 import android.graphics.Paint;
     31 import android.graphics.PixelFormat;
     32 import android.graphics.Point;
     33 import android.graphics.PorterDuff;
     34 import android.graphics.PorterDuffXfermode;
     35 import android.graphics.Rect;
     36 import android.graphics.RectF;
     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.text.TextUtils;
     49 import android.util.AttributeSet;
     50 import android.util.FloatProperty;
     51 import android.util.LocaleUtil;
     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.Property;
     58 import android.util.SparseArray;
     59 import android.util.TypedValue;
     60 import android.view.ContextMenu.ContextMenuInfo;
     61 import android.view.accessibility.AccessibilityEvent;
     62 import android.view.accessibility.AccessibilityEventSource;
     63 import android.view.accessibility.AccessibilityManager;
     64 import android.view.accessibility.AccessibilityNodeInfo;
     65 import android.view.animation.Animation;
     66 import android.view.animation.AnimationUtils;
     67 import android.view.inputmethod.EditorInfo;
     68 import android.view.inputmethod.InputConnection;
     69 import android.view.inputmethod.InputMethodManager;
     70 import android.widget.ScrollBarDrawable;
     71 
     72 import static android.os.Build.VERSION_CODES.*;
     73 
     74 import com.android.internal.R;
     75 import com.android.internal.util.Predicate;
     76 import com.android.internal.view.menu.MenuBuilder;
     77 
     78 import java.lang.ref.WeakReference;
     79 import java.lang.reflect.InvocationTargetException;
     80 import java.lang.reflect.Method;
     81 import java.util.ArrayList;
     82 import java.util.Arrays;
     83 import java.util.Locale;
     84 import java.util.concurrent.CopyOnWriteArrayList;
     85 
     86 /**
     87  * <p>
     88  * This class represents the basic building block for user interface components. A View
     89  * occupies a rectangular area on the screen and is responsible for drawing and
     90  * event handling. View is the base class for <em>widgets</em>, which are
     91  * used to create interactive UI components (buttons, text fields, etc.). The
     92  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
     93  * are invisible containers that hold other Views (or other ViewGroups) and define
     94  * their layout properties.
     95  * </p>
     96  *
     97  * <div class="special reference">
     98  * <h3>Developer Guides</h3>
     99  * <p>For information about using this class to develop your application's user interface,
    100  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
    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(android.view.View.OnFocusChangeListener)}.
    128  * Other view subclasses offer more specialized listeners. For example, a Button
    129  * exposes a listener to notify clients when the button is clicked.</li>
    130  * <li><strong>Set visibility:</strong> You can hide or show views using
    131  * {@link #setVisibility(int)}.</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(int, int)}</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(boolean, int, int, int, int)}</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(int, int, int, int)}</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(android.graphics.Canvas)}</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(int, KeyEvent)}</code></td>
    199  *         <td>Called when a new key event occurs.
    200  *         </td>
    201  *     </tr>
    202  *     <tr>
    203  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
    204  *         <td>Called when a key up event occurs.
    205  *         </td>
    206  *     </tr>
    207  *     <tr>
    208  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
    209  *         <td>Called when a trackball motion event occurs.
    210  *         </td>
    211  *     </tr>
    212  *     <tr>
    213  *         <td><code>{@link #onTouchEvent(MotionEvent)}</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(boolean, int, android.graphics.Rect)}</code></td>
    221  *         <td>Called when the view gains or loses focus.
    222  *         </td>
    223  *     </tr>
    224  *
    225  *     <tr>
    226  *         <td><code>{@link #onWindowFocusChanged(boolean)}</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(int)}</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
    264  *     android:id="@+id/my_button"
    265  *     android:layout_width="wrap_content"
    266  *     android:layout_height="wrap_content"
    267  *     android:text="@string/my_button_text"/&gt;
    268  * </pre></li>
    269  * <li>From the onCreate method of an Activity, find the Button
    270  * <pre class="prettyprint">
    271  *      Button myButton = (Button) findViewById(R.id.my_button);
    272  * </pre></li>
    273  * </ul>
    274  * <p>
    275  * View IDs need not be unique throughout the tree, but it is good practice to
    276  * ensure that they are at least unique within the part of the tree you are
    277  * searching.
    278  * </p>
    279  *
    280  * <a name="Position"></a>
    281  * <h3>Position</h3>
    282  * <p>
    283  * The geometry of a view is that of a rectangle. A view has a location,
    284  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
    285  * two dimensions, expressed as a width and a height. The unit for location
    286  * and dimensions is the pixel.
    287  * </p>
    288  *
    289  * <p>
    290  * It is possible to retrieve the location of a view by invoking the methods
    291  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
    292  * coordinate of the rectangle representing the view. The latter returns the
    293  * top, or Y, coordinate of the rectangle representing the view. These methods
    294  * both return the location of the view relative to its parent. For instance,
    295  * when getLeft() returns 20, that means the view is located 20 pixels to the
    296  * right of the left edge of its direct parent.
    297  * </p>
    298  *
    299  * <p>
    300  * In addition, several convenience methods are offered to avoid unnecessary
    301  * computations, namely {@link #getRight()} and {@link #getBottom()}.
    302  * These methods return the coordinates of the right and bottom edges of the
    303  * rectangle representing the view. For instance, calling {@link #getRight()}
    304  * is similar to the following computation: <code>getLeft() + getWidth()</code>
    305  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
    306  * </p>
    307  *
    308  * <a name="SizePaddingMargins"></a>
    309  * <h3>Size, padding and margins</h3>
    310  * <p>
    311  * The size of a view is expressed with a width and a height. A view actually
    312  * possess two pairs of width and height values.
    313  * </p>
    314  *
    315  * <p>
    316  * The first pair is known as <em>measured width</em> and
    317  * <em>measured height</em>. These dimensions define how big a view wants to be
    318  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
    319  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
    320  * and {@link #getMeasuredHeight()}.
    321  * </p>
    322  *
    323  * <p>
    324  * The second pair is simply known as <em>width</em> and <em>height</em>, or
    325  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
    326  * dimensions define the actual size of the view on screen, at drawing time and
    327  * after layout. These values may, but do not have to, be different from the
    328  * measured width and height. The width and height can be obtained by calling
    329  * {@link #getWidth()} and {@link #getHeight()}.
    330  * </p>
    331  *
    332  * <p>
    333  * To measure its dimensions, a view takes into account its padding. The padding
    334  * is expressed in pixels for the left, top, right and bottom parts of the view.
    335  * Padding can be used to offset the content of the view by a specific amount of
    336  * pixels. For instance, a left padding of 2 will push the view's content by
    337  * 2 pixels to the right of the left edge. Padding can be set using the
    338  * {@link #setPadding(int, int, int, int)} method and queried by calling
    339  * {@link #getPaddingLeft()}, {@link #getPaddingTop()},
    340  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}.
    341  * </p>
    342  *
    343  * <p>
    344  * Even though a view can define a padding, it does not provide any support for
    345  * margins. However, view groups provide such a support. Refer to
    346  * {@link android.view.ViewGroup} and
    347  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
    348  * </p>
    349  *
    350  * <a name="Layout"></a>
    351  * <h3>Layout</h3>
    352  * <p>
    353  * Layout is a two pass process: a measure pass and a layout pass. The measuring
    354  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
    355  * of the view tree. Each view pushes dimension specifications down the tree
    356  * during the recursion. At the end of the measure pass, every view has stored
    357  * its measurements. The second pass happens in
    358  * {@link #layout(int,int,int,int)} and is also top-down. During
    359  * this pass each parent is responsible for positioning all of its children
    360  * using the sizes computed in the measure pass.
    361  * </p>
    362  *
    363  * <p>
    364  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
    365  * {@link #getMeasuredHeight()} values must be set, along with those for all of
    366  * that view's descendants. A view's measured width and measured height values
    367  * must respect the constraints imposed by the view's parents. This guarantees
    368  * that at the end of the measure pass, all parents accept all of their
    369  * children's measurements. A parent view may call measure() more than once on
    370  * its children. For example, the parent may measure each child once with
    371  * unspecified dimensions to find out how big they want to be, then call
    372  * measure() on them again with actual numbers if the sum of all the children's
    373  * unconstrained sizes is too big or too small.
    374  * </p>
    375  *
    376  * <p>
    377  * The measure pass uses two classes to communicate dimensions. The
    378  * {@link MeasureSpec} class is used by views to tell their parents how they
    379  * want to be measured and positioned. The base LayoutParams class just
    380  * describes how big the view wants to be for both width and height. For each
    381  * dimension, it can specify one of:
    382  * <ul>
    383  * <li> an exact number
    384  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
    385  * (minus padding)
    386  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
    387  * enclose its content (plus padding).
    388  * </ul>
    389  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
    390  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
    391  * an X and Y value.
    392  * </p>
    393  *
    394  * <p>
    395  * MeasureSpecs are used to push requirements down the tree from parent to
    396  * child. A MeasureSpec can be in one of three modes:
    397  * <ul>
    398  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
    399  * of a child view. For example, a LinearLayout may call measure() on its child
    400  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
    401  * tall the child view wants to be given a width of 240 pixels.
    402  * <li>EXACTLY: This is used by the parent to impose an exact size on the
    403  * child. The child must use this size, and guarantee that all of its
    404  * descendants will fit within this size.
    405  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
    406  * child. The child must gurantee that it and all of its descendants will fit
    407  * within this size.
    408  * </ul>
    409  * </p>
    410  *
    411  * <p>
    412  * To intiate a layout, call {@link #requestLayout}. This method is typically
    413  * called by a view on itself when it believes that is can no longer fit within
    414  * its current bounds.
    415  * </p>
    416  *
    417  * <a name="Drawing"></a>
    418  * <h3>Drawing</h3>
    419  * <p>
    420  * Drawing is handled by walking the tree and rendering each view that
    421  * intersects the invalid region. Because the tree is traversed in-order,
    422  * this means that parents will draw before (i.e., behind) their children, with
    423  * siblings drawn in the order they appear in the tree.
    424  * If you set a background drawable for a View, then the View will draw it for you
    425  * before calling back to its <code>onDraw()</code> method.
    426  * </p>
    427  *
    428  * <p>
    429  * Note that the framework will not draw views that are not in the invalid region.
    430  * </p>
    431  *
    432  * <p>
    433  * To force a view to draw, call {@link #invalidate()}.
    434  * </p>
    435  *
    436  * <a name="EventHandlingThreading"></a>
    437  * <h3>Event Handling and Threading</h3>
    438  * <p>
    439  * The basic cycle of a view is as follows:
    440  * <ol>
    441  * <li>An event comes in and is dispatched to the appropriate view. The view
    442  * handles the event and notifies any listeners.</li>
    443  * <li>If in the course of processing the event, the view's bounds may need
    444  * to be changed, the view will call {@link #requestLayout()}.</li>
    445  * <li>Similarly, if in the course of processing the event the view's appearance
    446  * may need to be changed, the view will call {@link #invalidate()}.</li>
    447  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
    448  * the framework will take care of measuring, laying out, and drawing the tree
    449  * as appropriate.</li>
    450  * </ol>
    451  * </p>
    452  *
    453  * <p><em>Note: The entire view tree is single threaded. You must always be on
    454  * the UI thread when calling any method on any view.</em>
    455  * If you are doing work on other threads and want to update the state of a view
    456  * from that thread, you should use a {@link Handler}.
    457  * </p>
    458  *
    459  * <a name="FocusHandling"></a>
    460  * <h3>Focus Handling</h3>
    461  * <p>
    462  * The framework will handle routine focus movement in response to user input.
    463  * This includes changing the focus as views are removed or hidden, or as new
    464  * views become available. Views indicate their willingness to take focus
    465  * through the {@link #isFocusable} method. To change whether a view can take
    466  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
    467  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
    468  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
    469  * </p>
    470  * <p>
    471  * Focus movement is based on an algorithm which finds the nearest neighbor in a
    472  * given direction. In rare cases, the default algorithm may not match the
    473  * intended behavior of the developer. In these situations, you can provide
    474  * explicit overrides by using these XML attributes in the layout file:
    475  * <pre>
    476  * nextFocusDown
    477  * nextFocusLeft
    478  * nextFocusRight
    479  * nextFocusUp
    480  * </pre>
    481  * </p>
    482  *
    483  *
    484  * <p>
    485  * To get a particular view to take focus, call {@link #requestFocus()}.
    486  * </p>
    487  *
    488  * <a name="TouchMode"></a>
    489  * <h3>Touch Mode</h3>
    490  * <p>
    491  * When a user is navigating a user interface via directional keys such as a D-pad, it is
    492  * necessary to give focus to actionable items such as buttons so the user can see
    493  * what will take input.  If the device has touch capabilities, however, and the user
    494  * begins interacting with the interface by touching it, it is no longer necessary to
    495  * always highlight, or give focus to, a particular view.  This motivates a mode
    496  * for interaction named 'touch mode'.
    497  * </p>
    498  * <p>
    499  * For a touch capable device, once the user touches the screen, the device
    500  * will enter touch mode.  From this point onward, only views for which
    501  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
    502  * Other views that are touchable, like buttons, will not take focus when touched; they will
    503  * only fire the on click listeners.
    504  * </p>
    505  * <p>
    506  * Any time a user hits a directional key, such as a D-pad direction, the view device will
    507  * exit touch mode, and find a view to take focus, so that the user may resume interacting
    508  * with the user interface without touching the screen again.
    509  * </p>
    510  * <p>
    511  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
    512  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
    513  * </p>
    514  *
    515  * <a name="Scrolling"></a>
    516  * <h3>Scrolling</h3>
    517  * <p>
    518  * The framework provides basic support for views that wish to internally
    519  * scroll their content. This includes keeping track of the X and Y scroll
    520  * offset as well as mechanisms for drawing scrollbars. See
    521  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
    522  * {@link #awakenScrollBars()} for more details.
    523  * </p>
    524  *
    525  * <a name="Tags"></a>
    526  * <h3>Tags</h3>
    527  * <p>
    528  * Unlike IDs, tags are not used to identify views. Tags are essentially an
    529  * extra piece of information that can be associated with a view. They are most
    530  * often used as a convenience to store data related to views in the views
    531  * themselves rather than by putting them in a separate structure.
    532  * </p>
    533  *
    534  * <a name="Animation"></a>
    535  * <h3>Animation</h3>
    536  * <p>
    537  * You can attach an {@link Animation} object to a view using
    538  * {@link #setAnimation(Animation)} or
    539  * {@link #startAnimation(Animation)}. The animation can alter the scale,
    540  * rotation, translation and alpha of a view over time. If the animation is
    541  * attached to a view that has children, the animation will affect the entire
    542  * subtree rooted by that node. When an animation is started, the framework will
    543  * take care of redrawing the appropriate views until the animation completes.
    544  * </p>
    545  * <p>
    546  * Starting with Android 3.0, the preferred way of animating views is to use the
    547  * {@link android.animation} package APIs.
    548  * </p>
    549  *
    550  * <a name="Security"></a>
    551  * <h3>Security</h3>
    552  * <p>
    553  * Sometimes it is essential that an application be able to verify that an action
    554  * is being performed with the full knowledge and consent of the user, such as
    555  * granting a permission request, making a purchase or clicking on an advertisement.
    556  * Unfortunately, a malicious application could try to spoof the user into
    557  * performing these actions, unaware, by concealing the intended purpose of the view.
    558  * As a remedy, the framework offers a touch filtering mechanism that can be used to
    559  * improve the security of views that provide access to sensitive functionality.
    560  * </p><p>
    561  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
    562  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
    563  * will discard touches that are received whenever the view's window is obscured by
    564  * another visible window.  As a result, the view will not receive touches whenever a
    565  * toast, dialog or other window appears above the view's window.
    566  * </p><p>
    567  * For more fine-grained control over security, consider overriding the
    568  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
    569  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
    570  * </p>
    571  *
    572  * @attr ref android.R.styleable#View_alpha
    573  * @attr ref android.R.styleable#View_background
    574  * @attr ref android.R.styleable#View_clickable
    575  * @attr ref android.R.styleable#View_contentDescription
    576  * @attr ref android.R.styleable#View_drawingCacheQuality
    577  * @attr ref android.R.styleable#View_duplicateParentState
    578  * @attr ref android.R.styleable#View_id
    579  * @attr ref android.R.styleable#View_requiresFadingEdge
    580  * @attr ref android.R.styleable#View_fadingEdgeLength
    581  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
    582  * @attr ref android.R.styleable#View_fitsSystemWindows
    583  * @attr ref android.R.styleable#View_isScrollContainer
    584  * @attr ref android.R.styleable#View_focusable
    585  * @attr ref android.R.styleable#View_focusableInTouchMode
    586  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
    587  * @attr ref android.R.styleable#View_keepScreenOn
    588  * @attr ref android.R.styleable#View_layerType
    589  * @attr ref android.R.styleable#View_longClickable
    590  * @attr ref android.R.styleable#View_minHeight
    591  * @attr ref android.R.styleable#View_minWidth
    592  * @attr ref android.R.styleable#View_nextFocusDown
    593  * @attr ref android.R.styleable#View_nextFocusLeft
    594  * @attr ref android.R.styleable#View_nextFocusRight
    595  * @attr ref android.R.styleable#View_nextFocusUp
    596  * @attr ref android.R.styleable#View_onClick
    597  * @attr ref android.R.styleable#View_padding
    598  * @attr ref android.R.styleable#View_paddingBottom
    599  * @attr ref android.R.styleable#View_paddingLeft
    600  * @attr ref android.R.styleable#View_paddingRight
    601  * @attr ref android.R.styleable#View_paddingTop
    602  * @attr ref android.R.styleable#View_saveEnabled
    603  * @attr ref android.R.styleable#View_rotation
    604  * @attr ref android.R.styleable#View_rotationX
    605  * @attr ref android.R.styleable#View_rotationY
    606  * @attr ref android.R.styleable#View_scaleX
    607  * @attr ref android.R.styleable#View_scaleY
    608  * @attr ref android.R.styleable#View_scrollX
    609  * @attr ref android.R.styleable#View_scrollY
    610  * @attr ref android.R.styleable#View_scrollbarSize
    611  * @attr ref android.R.styleable#View_scrollbarStyle
    612  * @attr ref android.R.styleable#View_scrollbars
    613  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
    614  * @attr ref android.R.styleable#View_scrollbarFadeDuration
    615  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
    616  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
    617  * @attr ref android.R.styleable#View_scrollbarThumbVertical
    618  * @attr ref android.R.styleable#View_scrollbarTrackVertical
    619  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
    620  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
    621  * @attr ref android.R.styleable#View_soundEffectsEnabled
    622  * @attr ref android.R.styleable#View_tag
    623  * @attr ref android.R.styleable#View_transformPivotX
    624  * @attr ref android.R.styleable#View_transformPivotY
    625  * @attr ref android.R.styleable#View_translationX
    626  * @attr ref android.R.styleable#View_translationY
    627  * @attr ref android.R.styleable#View_visibility
    628  *
    629  * @see android.view.ViewGroup
    630  */
    631 public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,
    632         AccessibilityEventSource {
    633     private static final boolean DBG = false;
    634 
    635     /**
    636      * The logging tag used by this class with android.util.Log.
    637      */
    638     protected static final String VIEW_LOG_TAG = "View";
    639 
    640     /**
    641      * Used to mark a View that has no ID.
    642      */
    643     public static final int NO_ID = -1;
    644 
    645     /**
    646      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
    647      * calling setFlags.
    648      */
    649     private static final int NOT_FOCUSABLE = 0x00000000;
    650 
    651     /**
    652      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
    653      * setFlags.
    654      */
    655     private static final int FOCUSABLE = 0x00000001;
    656 
    657     /**
    658      * Mask for use with setFlags indicating bits used for focus.
    659      */
    660     private static final int FOCUSABLE_MASK = 0x00000001;
    661 
    662     /**
    663      * This view will adjust its padding to fit sytem windows (e.g. status bar)
    664      */
    665     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
    666 
    667     /**
    668      * This view is visible.
    669      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    670      * android:visibility}.
    671      */
    672     public static final int VISIBLE = 0x00000000;
    673 
    674     /**
    675      * This view is invisible, but it still takes up space for layout purposes.
    676      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    677      * android:visibility}.
    678      */
    679     public static final int INVISIBLE = 0x00000004;
    680 
    681     /**
    682      * This view is invisible, and it doesn't take any space for layout
    683      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    684      * android:visibility}.
    685      */
    686     public static final int GONE = 0x00000008;
    687 
    688     /**
    689      * Mask for use with setFlags indicating bits used for visibility.
    690      * {@hide}
    691      */
    692     static final int VISIBILITY_MASK = 0x0000000C;
    693 
    694     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
    695 
    696     /**
    697      * This view is enabled. Intrepretation varies by subclass.
    698      * Use with ENABLED_MASK when calling setFlags.
    699      * {@hide}
    700      */
    701     static final int ENABLED = 0x00000000;
    702 
    703     /**
    704      * This view is disabled. Intrepretation varies by subclass.
    705      * Use with ENABLED_MASK when calling setFlags.
    706      * {@hide}
    707      */
    708     static final int DISABLED = 0x00000020;
    709 
    710    /**
    711     * Mask for use with setFlags indicating bits used for indicating whether
    712     * this view is enabled
    713     * {@hide}
    714     */
    715     static final int ENABLED_MASK = 0x00000020;
    716 
    717     /**
    718      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
    719      * called and further optimizations will be performed. It is okay to have
    720      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
    721      * {@hide}
    722      */
    723     static final int WILL_NOT_DRAW = 0x00000080;
    724 
    725     /**
    726      * Mask for use with setFlags indicating bits used for indicating whether
    727      * this view is will draw
    728      * {@hide}
    729      */
    730     static final int DRAW_MASK = 0x00000080;
    731 
    732     /**
    733      * <p>This view doesn't show scrollbars.</p>
    734      * {@hide}
    735      */
    736     static final int SCROLLBARS_NONE = 0x00000000;
    737 
    738     /**
    739      * <p>This view shows horizontal scrollbars.</p>
    740      * {@hide}
    741      */
    742     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
    743 
    744     /**
    745      * <p>This view shows vertical scrollbars.</p>
    746      * {@hide}
    747      */
    748     static final int SCROLLBARS_VERTICAL = 0x00000200;
    749 
    750     /**
    751      * <p>Mask for use with setFlags indicating bits used for indicating which
    752      * scrollbars are enabled.</p>
    753      * {@hide}
    754      */
    755     static final int SCROLLBARS_MASK = 0x00000300;
    756 
    757     /**
    758      * Indicates that the view should filter touches when its window is obscured.
    759      * Refer to the class comments for more information about this security feature.
    760      * {@hide}
    761      */
    762     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
    763 
    764     // note flag value 0x00000800 is now available for next flags...
    765 
    766     /**
    767      * <p>This view doesn't show fading edges.</p>
    768      * {@hide}
    769      */
    770     static final int FADING_EDGE_NONE = 0x00000000;
    771 
    772     /**
    773      * <p>This view shows horizontal fading edges.</p>
    774      * {@hide}
    775      */
    776     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
    777 
    778     /**
    779      * <p>This view shows vertical fading edges.</p>
    780      * {@hide}
    781      */
    782     static final int FADING_EDGE_VERTICAL = 0x00002000;
    783 
    784     /**
    785      * <p>Mask for use with setFlags indicating bits used for indicating which
    786      * fading edges are enabled.</p>
    787      * {@hide}
    788      */
    789     static final int FADING_EDGE_MASK = 0x00003000;
    790 
    791     /**
    792      * <p>Indicates this view can be clicked. When clickable, a View reacts
    793      * to clicks by notifying the OnClickListener.<p>
    794      * {@hide}
    795      */
    796     static final int CLICKABLE = 0x00004000;
    797 
    798     /**
    799      * <p>Indicates this view is caching its drawing into a bitmap.</p>
    800      * {@hide}
    801      */
    802     static final int DRAWING_CACHE_ENABLED = 0x00008000;
    803 
    804     /**
    805      * <p>Indicates that no icicle should be saved for this view.<p>
    806      * {@hide}
    807      */
    808     static final int SAVE_DISABLED = 0x000010000;
    809 
    810     /**
    811      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
    812      * property.</p>
    813      * {@hide}
    814      */
    815     static final int SAVE_DISABLED_MASK = 0x000010000;
    816 
    817     /**
    818      * <p>Indicates that no drawing cache should ever be created for this view.<p>
    819      * {@hide}
    820      */
    821     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
    822 
    823     /**
    824      * <p>Indicates this view can take / keep focus when int touch mode.</p>
    825      * {@hide}
    826      */
    827     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
    828 
    829     /**
    830      * <p>Enables low quality mode for the drawing cache.</p>
    831      */
    832     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
    833 
    834     /**
    835      * <p>Enables high quality mode for the drawing cache.</p>
    836      */
    837     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
    838 
    839     /**
    840      * <p>Enables automatic quality mode for the drawing cache.</p>
    841      */
    842     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
    843 
    844     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
    845             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
    846     };
    847 
    848     /**
    849      * <p>Mask for use with setFlags indicating bits used for the cache
    850      * quality property.</p>
    851      * {@hide}
    852      */
    853     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
    854 
    855     /**
    856      * <p>
    857      * Indicates this view can be long clicked. When long clickable, a View
    858      * reacts to long clicks by notifying the OnLongClickListener or showing a
    859      * context menu.
    860      * </p>
    861      * {@hide}
    862      */
    863     static final int LONG_CLICKABLE = 0x00200000;
    864 
    865     /**
    866      * <p>Indicates that this view gets its drawable states from its direct parent
    867      * and ignores its original internal states.</p>
    868      *
    869      * @hide
    870      */
    871     static final int DUPLICATE_PARENT_STATE = 0x00400000;
    872 
    873     /**
    874      * The scrollbar style to display the scrollbars inside the content area,
    875      * without increasing the padding. The scrollbars will be overlaid with
    876      * translucency on the view's content.
    877      */
    878     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
    879 
    880     /**
    881      * The scrollbar style to display the scrollbars inside the padded area,
    882      * increasing the padding of the view. The scrollbars will not overlap the
    883      * content area of the view.
    884      */
    885     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
    886 
    887     /**
    888      * The scrollbar style to display the scrollbars at the edge of the view,
    889      * without increasing the padding. The scrollbars will be overlaid with
    890      * translucency.
    891      */
    892     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
    893 
    894     /**
    895      * The scrollbar style to display the scrollbars at the edge of the view,
    896      * increasing the padding of the view. The scrollbars will only overlap the
    897      * background, if any.
    898      */
    899     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
    900 
    901     /**
    902      * Mask to check if the scrollbar style is overlay or inset.
    903      * {@hide}
    904      */
    905     static final int SCROLLBARS_INSET_MASK = 0x01000000;
    906 
    907     /**
    908      * Mask to check if the scrollbar style is inside or outside.
    909      * {@hide}
    910      */
    911     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
    912 
    913     /**
    914      * Mask for scrollbar style.
    915      * {@hide}
    916      */
    917     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
    918 
    919     /**
    920      * View flag indicating that the screen should remain on while the
    921      * window containing this view is visible to the user.  This effectively
    922      * takes care of automatically setting the WindowManager's
    923      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
    924      */
    925     public static final int KEEP_SCREEN_ON = 0x04000000;
    926 
    927     /**
    928      * View flag indicating whether this view should have sound effects enabled
    929      * for events such as clicking and touching.
    930      */
    931     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
    932 
    933     /**
    934      * View flag indicating whether this view should have haptic feedback
    935      * enabled for events such as long presses.
    936      */
    937     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
    938 
    939     /**
    940      * <p>Indicates that the view hierarchy should stop saving state when
    941      * it reaches this view.  If state saving is initiated immediately at
    942      * the view, it will be allowed.
    943      * {@hide}
    944      */
    945     static final int PARENT_SAVE_DISABLED = 0x20000000;
    946 
    947     /**
    948      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
    949      * {@hide}
    950      */
    951     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
    952 
    953     /**
    954      * Horizontal direction of this view is from Left to Right.
    955      * Use with {@link #setLayoutDirection}.
    956      * {@hide}
    957      */
    958     public static final int LAYOUT_DIRECTION_LTR = 0x00000000;
    959 
    960     /**
    961      * Horizontal direction of this view is from Right to Left.
    962      * Use with {@link #setLayoutDirection}.
    963      * {@hide}
    964      */
    965     public static final int LAYOUT_DIRECTION_RTL = 0x40000000;
    966 
    967     /**
    968      * Horizontal direction of this view is inherited from its parent.
    969      * Use with {@link #setLayoutDirection}.
    970      * {@hide}
    971      */
    972     public static final int LAYOUT_DIRECTION_INHERIT = 0x80000000;
    973 
    974     /**
    975      * Horizontal direction of this view is from deduced from the default language
    976      * script for the locale. Use with {@link #setLayoutDirection}.
    977      * {@hide}
    978      */
    979     public static final int LAYOUT_DIRECTION_LOCALE = 0xC0000000;
    980 
    981     /**
    982      * Mask for use with setFlags indicating bits used for horizontalDirection.
    983      * {@hide}
    984      */
    985     static final int LAYOUT_DIRECTION_MASK = 0xC0000000;
    986 
    987     /*
    988      * Array of horizontal direction flags for mapping attribute "horizontalDirection" to correct
    989      * flag value.
    990      * {@hide}
    991      */
    992     private static final int[] LAYOUT_DIRECTION_FLAGS = {LAYOUT_DIRECTION_LTR,
    993         LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LOCALE};
    994 
    995     /**
    996      * Default horizontalDirection.
    997      * {@hide}
    998      */
    999     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
   1000 
   1001     /**
   1002      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1003      * should add all focusable Views regardless if they are focusable in touch mode.
   1004      */
   1005     public static final int FOCUSABLES_ALL = 0x00000000;
   1006 
   1007     /**
   1008      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1009      * should add only Views focusable in touch mode.
   1010      */
   1011     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
   1012 
   1013     /**
   1014      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
   1015      * item.
   1016      */
   1017     public static final int FOCUS_BACKWARD = 0x00000001;
   1018 
   1019     /**
   1020      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
   1021      * item.
   1022      */
   1023     public static final int FOCUS_FORWARD = 0x00000002;
   1024 
   1025     /**
   1026      * Use with {@link #focusSearch(int)}. Move focus to the left.
   1027      */
   1028     public static final int FOCUS_LEFT = 0x00000011;
   1029 
   1030     /**
   1031      * Use with {@link #focusSearch(int)}. Move focus up.
   1032      */
   1033     public static final int FOCUS_UP = 0x00000021;
   1034 
   1035     /**
   1036      * Use with {@link #focusSearch(int)}. Move focus to the right.
   1037      */
   1038     public static final int FOCUS_RIGHT = 0x00000042;
   1039 
   1040     /**
   1041      * Use with {@link #focusSearch(int)}. Move focus down.
   1042      */
   1043     public static final int FOCUS_DOWN = 0x00000082;
   1044 
   1045     /**
   1046      * Bits of {@link #getMeasuredWidthAndState()} and
   1047      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
   1048      */
   1049     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
   1050 
   1051     /**
   1052      * Bits of {@link #getMeasuredWidthAndState()} and
   1053      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
   1054      */
   1055     public static final int MEASURED_STATE_MASK = 0xff000000;
   1056 
   1057     /**
   1058      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
   1059      * for functions that combine both width and height into a single int,
   1060      * such as {@link #getMeasuredState()} and the childState argument of
   1061      * {@link #resolveSizeAndState(int, int, int)}.
   1062      */
   1063     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
   1064 
   1065     /**
   1066      * Bit of {@link #getMeasuredWidthAndState()} and
   1067      * {@link #getMeasuredWidthAndState()} that indicates the measured size
   1068      * is smaller that the space the view would like to have.
   1069      */
   1070     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
   1071 
   1072     /**
   1073      * Base View state sets
   1074      */
   1075     // Singles
   1076     /**
   1077      * Indicates the view has no states set. States are used with
   1078      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1079      * view depending on its state.
   1080      *
   1081      * @see android.graphics.drawable.Drawable
   1082      * @see #getDrawableState()
   1083      */
   1084     protected static final int[] EMPTY_STATE_SET;
   1085     /**
   1086      * Indicates the view is enabled. States are used with
   1087      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1088      * view depending on its state.
   1089      *
   1090      * @see android.graphics.drawable.Drawable
   1091      * @see #getDrawableState()
   1092      */
   1093     protected static final int[] ENABLED_STATE_SET;
   1094     /**
   1095      * Indicates the view is focused. States are used with
   1096      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1097      * view depending on its state.
   1098      *
   1099      * @see android.graphics.drawable.Drawable
   1100      * @see #getDrawableState()
   1101      */
   1102     protected static final int[] FOCUSED_STATE_SET;
   1103     /**
   1104      * Indicates the view is selected. States are used with
   1105      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1106      * view depending on its state.
   1107      *
   1108      * @see android.graphics.drawable.Drawable
   1109      * @see #getDrawableState()
   1110      */
   1111     protected static final int[] SELECTED_STATE_SET;
   1112     /**
   1113      * Indicates the view is pressed. States are used with
   1114      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1115      * view depending on its state.
   1116      *
   1117      * @see android.graphics.drawable.Drawable
   1118      * @see #getDrawableState()
   1119      * @hide
   1120      */
   1121     protected static final int[] PRESSED_STATE_SET;
   1122     /**
   1123      * Indicates the view's window has focus. States are used with
   1124      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1125      * view depending on its state.
   1126      *
   1127      * @see android.graphics.drawable.Drawable
   1128      * @see #getDrawableState()
   1129      */
   1130     protected static final int[] WINDOW_FOCUSED_STATE_SET;
   1131     // Doubles
   1132     /**
   1133      * Indicates the view is enabled and has the focus.
   1134      *
   1135      * @see #ENABLED_STATE_SET
   1136      * @see #FOCUSED_STATE_SET
   1137      */
   1138     protected static final int[] ENABLED_FOCUSED_STATE_SET;
   1139     /**
   1140      * Indicates the view is enabled and selected.
   1141      *
   1142      * @see #ENABLED_STATE_SET
   1143      * @see #SELECTED_STATE_SET
   1144      */
   1145     protected static final int[] ENABLED_SELECTED_STATE_SET;
   1146     /**
   1147      * Indicates the view is enabled and that its window has focus.
   1148      *
   1149      * @see #ENABLED_STATE_SET
   1150      * @see #WINDOW_FOCUSED_STATE_SET
   1151      */
   1152     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
   1153     /**
   1154      * Indicates the view is focused and selected.
   1155      *
   1156      * @see #FOCUSED_STATE_SET
   1157      * @see #SELECTED_STATE_SET
   1158      */
   1159     protected static final int[] FOCUSED_SELECTED_STATE_SET;
   1160     /**
   1161      * Indicates the view has the focus and that its window has the focus.
   1162      *
   1163      * @see #FOCUSED_STATE_SET
   1164      * @see #WINDOW_FOCUSED_STATE_SET
   1165      */
   1166     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1167     /**
   1168      * Indicates the view is selected and that its window has the focus.
   1169      *
   1170      * @see #SELECTED_STATE_SET
   1171      * @see #WINDOW_FOCUSED_STATE_SET
   1172      */
   1173     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
   1174     // Triples
   1175     /**
   1176      * Indicates the view is enabled, focused and selected.
   1177      *
   1178      * @see #ENABLED_STATE_SET
   1179      * @see #FOCUSED_STATE_SET
   1180      * @see #SELECTED_STATE_SET
   1181      */
   1182     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
   1183     /**
   1184      * Indicates the view is enabled, focused and its window has the focus.
   1185      *
   1186      * @see #ENABLED_STATE_SET
   1187      * @see #FOCUSED_STATE_SET
   1188      * @see #WINDOW_FOCUSED_STATE_SET
   1189      */
   1190     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1191     /**
   1192      * Indicates the view is enabled, selected and its window has the focus.
   1193      *
   1194      * @see #ENABLED_STATE_SET
   1195      * @see #SELECTED_STATE_SET
   1196      * @see #WINDOW_FOCUSED_STATE_SET
   1197      */
   1198     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1199     /**
   1200      * Indicates the view is focused, selected and its window has the focus.
   1201      *
   1202      * @see #FOCUSED_STATE_SET
   1203      * @see #SELECTED_STATE_SET
   1204      * @see #WINDOW_FOCUSED_STATE_SET
   1205      */
   1206     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1207     /**
   1208      * Indicates the view is enabled, focused, selected and its window
   1209      * has the focus.
   1210      *
   1211      * @see #ENABLED_STATE_SET
   1212      * @see #FOCUSED_STATE_SET
   1213      * @see #SELECTED_STATE_SET
   1214      * @see #WINDOW_FOCUSED_STATE_SET
   1215      */
   1216     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1217     /**
   1218      * Indicates the view is pressed and its window has the focus.
   1219      *
   1220      * @see #PRESSED_STATE_SET
   1221      * @see #WINDOW_FOCUSED_STATE_SET
   1222      */
   1223     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
   1224     /**
   1225      * Indicates the view is pressed and selected.
   1226      *
   1227      * @see #PRESSED_STATE_SET
   1228      * @see #SELECTED_STATE_SET
   1229      */
   1230     protected static final int[] PRESSED_SELECTED_STATE_SET;
   1231     /**
   1232      * Indicates the view is pressed, selected and its window has the focus.
   1233      *
   1234      * @see #PRESSED_STATE_SET
   1235      * @see #SELECTED_STATE_SET
   1236      * @see #WINDOW_FOCUSED_STATE_SET
   1237      */
   1238     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1239     /**
   1240      * Indicates the view is pressed and focused.
   1241      *
   1242      * @see #PRESSED_STATE_SET
   1243      * @see #FOCUSED_STATE_SET
   1244      */
   1245     protected static final int[] PRESSED_FOCUSED_STATE_SET;
   1246     /**
   1247      * Indicates the view is pressed, focused and its window has the focus.
   1248      *
   1249      * @see #PRESSED_STATE_SET
   1250      * @see #FOCUSED_STATE_SET
   1251      * @see #WINDOW_FOCUSED_STATE_SET
   1252      */
   1253     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1254     /**
   1255      * Indicates the view is pressed, focused and selected.
   1256      *
   1257      * @see #PRESSED_STATE_SET
   1258      * @see #SELECTED_STATE_SET
   1259      * @see #FOCUSED_STATE_SET
   1260      */
   1261     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
   1262     /**
   1263      * Indicates the view is pressed, focused, selected and its window has the focus.
   1264      *
   1265      * @see #PRESSED_STATE_SET
   1266      * @see #FOCUSED_STATE_SET
   1267      * @see #SELECTED_STATE_SET
   1268      * @see #WINDOW_FOCUSED_STATE_SET
   1269      */
   1270     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1271     /**
   1272      * Indicates the view is pressed and enabled.
   1273      *
   1274      * @see #PRESSED_STATE_SET
   1275      * @see #ENABLED_STATE_SET
   1276      */
   1277     protected static final int[] PRESSED_ENABLED_STATE_SET;
   1278     /**
   1279      * Indicates the view is pressed, enabled and its window has the focus.
   1280      *
   1281      * @see #PRESSED_STATE_SET
   1282      * @see #ENABLED_STATE_SET
   1283      * @see #WINDOW_FOCUSED_STATE_SET
   1284      */
   1285     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
   1286     /**
   1287      * Indicates the view is pressed, enabled and selected.
   1288      *
   1289      * @see #PRESSED_STATE_SET
   1290      * @see #ENABLED_STATE_SET
   1291      * @see #SELECTED_STATE_SET
   1292      */
   1293     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
   1294     /**
   1295      * Indicates the view is pressed, enabled, selected and its window has the
   1296      * focus.
   1297      *
   1298      * @see #PRESSED_STATE_SET
   1299      * @see #ENABLED_STATE_SET
   1300      * @see #SELECTED_STATE_SET
   1301      * @see #WINDOW_FOCUSED_STATE_SET
   1302      */
   1303     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1304     /**
   1305      * Indicates the view is pressed, enabled and focused.
   1306      *
   1307      * @see #PRESSED_STATE_SET
   1308      * @see #ENABLED_STATE_SET
   1309      * @see #FOCUSED_STATE_SET
   1310      */
   1311     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
   1312     /**
   1313      * Indicates the view is pressed, enabled, focused and its window has the
   1314      * focus.
   1315      *
   1316      * @see #PRESSED_STATE_SET
   1317      * @see #ENABLED_STATE_SET
   1318      * @see #FOCUSED_STATE_SET
   1319      * @see #WINDOW_FOCUSED_STATE_SET
   1320      */
   1321     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1322     /**
   1323      * Indicates the view is pressed, enabled, focused and selected.
   1324      *
   1325      * @see #PRESSED_STATE_SET
   1326      * @see #ENABLED_STATE_SET
   1327      * @see #SELECTED_STATE_SET
   1328      * @see #FOCUSED_STATE_SET
   1329      */
   1330     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
   1331     /**
   1332      * Indicates the view is pressed, enabled, focused, selected and its window
   1333      * has the focus.
   1334      *
   1335      * @see #PRESSED_STATE_SET
   1336      * @see #ENABLED_STATE_SET
   1337      * @see #SELECTED_STATE_SET
   1338      * @see #FOCUSED_STATE_SET
   1339      * @see #WINDOW_FOCUSED_STATE_SET
   1340      */
   1341     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1342 
   1343     /**
   1344      * The order here is very important to {@link #getDrawableState()}
   1345      */
   1346     private static final int[][] VIEW_STATE_SETS;
   1347 
   1348     static final int VIEW_STATE_WINDOW_FOCUSED = 1;
   1349     static final int VIEW_STATE_SELECTED = 1 << 1;
   1350     static final int VIEW_STATE_FOCUSED = 1 << 2;
   1351     static final int VIEW_STATE_ENABLED = 1 << 3;
   1352     static final int VIEW_STATE_PRESSED = 1 << 4;
   1353     static final int VIEW_STATE_ACTIVATED = 1 << 5;
   1354     static final int VIEW_STATE_ACCELERATED = 1 << 6;
   1355     static final int VIEW_STATE_HOVERED = 1 << 7;
   1356     static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
   1357     static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
   1358 
   1359     static final int[] VIEW_STATE_IDS = new int[] {
   1360         R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
   1361         R.attr.state_selected,          VIEW_STATE_SELECTED,
   1362         R.attr.state_focused,           VIEW_STATE_FOCUSED,
   1363         R.attr.state_enabled,           VIEW_STATE_ENABLED,
   1364         R.attr.state_pressed,           VIEW_STATE_PRESSED,
   1365         R.attr.state_activated,         VIEW_STATE_ACTIVATED,
   1366         R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
   1367         R.attr.state_hovered,           VIEW_STATE_HOVERED,
   1368         R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
   1369         R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED,
   1370     };
   1371 
   1372     static {
   1373         if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
   1374             throw new IllegalStateException(
   1375                     "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
   1376         }
   1377         int[] orderedIds = new int[VIEW_STATE_IDS.length];
   1378         for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
   1379             int viewState = R.styleable.ViewDrawableStates[i];
   1380             for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
   1381                 if (VIEW_STATE_IDS[j] == viewState) {
   1382                     orderedIds[i * 2] = viewState;
   1383                     orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
   1384                 }
   1385             }
   1386         }
   1387         final int NUM_BITS = VIEW_STATE_IDS.length / 2;
   1388         VIEW_STATE_SETS = new int[1 << NUM_BITS][];
   1389         for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
   1390             int numBits = Integer.bitCount(i);
   1391             int[] set = new int[numBits];
   1392             int pos = 0;
   1393             for (int j = 0; j < orderedIds.length; j += 2) {
   1394                 if ((i & orderedIds[j+1]) != 0) {
   1395                     set[pos++] = orderedIds[j];
   1396                 }
   1397             }
   1398             VIEW_STATE_SETS[i] = set;
   1399         }
   1400 
   1401         EMPTY_STATE_SET = VIEW_STATE_SETS[0];
   1402         WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
   1403         SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
   1404         SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1405                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
   1406         FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
   1407         FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1408                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
   1409         FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
   1410                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
   1411         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1412                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
   1413                 | VIEW_STATE_FOCUSED];
   1414         ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
   1415         ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1416                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
   1417         ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
   1418                 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
   1419         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1420                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
   1421                 | VIEW_STATE_ENABLED];
   1422         ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1423                 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
   1424         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1425                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
   1426                 | VIEW_STATE_ENABLED];
   1427         ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
   1428                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
   1429                 | VIEW_STATE_ENABLED];
   1430         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1431                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
   1432                 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
   1433 
   1434         PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
   1435         PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1436                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
   1437         PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
   1438                 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
   1439         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1440                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
   1441                 | VIEW_STATE_PRESSED];
   1442         PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1443                 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
   1444         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1445                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
   1446                 | VIEW_STATE_PRESSED];
   1447         PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
   1448                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
   1449                 | VIEW_STATE_PRESSED];
   1450         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1451                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
   1452                 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
   1453         PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
   1454                 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
   1455         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1456                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
   1457                 | VIEW_STATE_PRESSED];
   1458         PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
   1459                 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
   1460                 | VIEW_STATE_PRESSED];
   1461         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1462                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
   1463                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
   1464         PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1465                 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
   1466                 | VIEW_STATE_PRESSED];
   1467         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1468                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
   1469                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
   1470         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
   1471                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
   1472                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
   1473         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
   1474                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
   1475                 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
   1476                 | VIEW_STATE_PRESSED];
   1477     }
   1478 
   1479     /**
   1480      * Accessibility event types that are dispatched for text population.
   1481      */
   1482     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
   1483             AccessibilityEvent.TYPE_VIEW_CLICKED
   1484             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   1485             | AccessibilityEvent.TYPE_VIEW_SELECTED
   1486             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   1487             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   1488             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   1489             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   1490             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   1491             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED;
   1492 
   1493     /**
   1494      * Temporary Rect currently for use in setBackground().  This will probably
   1495      * be extended in the future to hold our own class with more than just
   1496      * a Rect. :)
   1497      */
   1498     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
   1499 
   1500     /**
   1501      * Map used to store views' tags.
   1502      */
   1503     private SparseArray<Object> mKeyedTags;
   1504 
   1505     /**
   1506      * The next available accessiiblity id.
   1507      */
   1508     private static int sNextAccessibilityViewId;
   1509 
   1510     /**
   1511      * The animation currently associated with this view.
   1512      * @hide
   1513      */
   1514     protected Animation mCurrentAnimation = null;
   1515 
   1516     /**
   1517      * Width as measured during measure pass.
   1518      * {@hide}
   1519      */
   1520     @ViewDebug.ExportedProperty(category = "measurement")
   1521     int mMeasuredWidth;
   1522 
   1523     /**
   1524      * Height as measured during measure pass.
   1525      * {@hide}
   1526      */
   1527     @ViewDebug.ExportedProperty(category = "measurement")
   1528     int mMeasuredHeight;
   1529 
   1530     /**
   1531      * Flag to indicate that this view was marked INVALIDATED, or had its display list
   1532      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
   1533      * its display list. This flag, used only when hw accelerated, allows us to clear the
   1534      * flag while retaining this information until it's needed (at getDisplayList() time and
   1535      * in drawChild(), when we decide to draw a view's children's display lists into our own).
   1536      *
   1537      * {@hide}
   1538      */
   1539     boolean mRecreateDisplayList = false;
   1540 
   1541     /**
   1542      * The view's identifier.
   1543      * {@hide}
   1544      *
   1545      * @see #setId(int)
   1546      * @see #getId()
   1547      */
   1548     @ViewDebug.ExportedProperty(resolveId = true)
   1549     int mID = NO_ID;
   1550 
   1551     /**
   1552      * The stable ID of this view for accessibility purposes.
   1553      */
   1554     int mAccessibilityViewId = NO_ID;
   1555 
   1556     /**
   1557      * The view's tag.
   1558      * {@hide}
   1559      *
   1560      * @see #setTag(Object)
   1561      * @see #getTag()
   1562      */
   1563     protected Object mTag;
   1564 
   1565     // for mPrivateFlags:
   1566     /** {@hide} */
   1567     static final int WANTS_FOCUS                    = 0x00000001;
   1568     /** {@hide} */
   1569     static final int FOCUSED                        = 0x00000002;
   1570     /** {@hide} */
   1571     static final int SELECTED                       = 0x00000004;
   1572     /** {@hide} */
   1573     static final int IS_ROOT_NAMESPACE              = 0x00000008;
   1574     /** {@hide} */
   1575     static final int HAS_BOUNDS                     = 0x00000010;
   1576     /** {@hide} */
   1577     static final int DRAWN                          = 0x00000020;
   1578     /**
   1579      * When this flag is set, this view is running an animation on behalf of its
   1580      * children and should therefore not cancel invalidate requests, even if they
   1581      * lie outside of this view's bounds.
   1582      *
   1583      * {@hide}
   1584      */
   1585     static final int DRAW_ANIMATION                 = 0x00000040;
   1586     /** {@hide} */
   1587     static final int SKIP_DRAW                      = 0x00000080;
   1588     /** {@hide} */
   1589     static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
   1590     /** {@hide} */
   1591     static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
   1592     /** {@hide} */
   1593     static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
   1594     /** {@hide} */
   1595     static final int MEASURED_DIMENSION_SET         = 0x00000800;
   1596     /** {@hide} */
   1597     static final int FORCE_LAYOUT                   = 0x00001000;
   1598     /** {@hide} */
   1599     static final int LAYOUT_REQUIRED                = 0x00002000;
   1600 
   1601     private static final int PRESSED                = 0x00004000;
   1602 
   1603     /** {@hide} */
   1604     static final int DRAWING_CACHE_VALID            = 0x00008000;
   1605     /**
   1606      * Flag used to indicate that this view should be drawn once more (and only once
   1607      * more) after its animation has completed.
   1608      * {@hide}
   1609      */
   1610     static final int ANIMATION_STARTED              = 0x00010000;
   1611 
   1612     private static final int SAVE_STATE_CALLED      = 0x00020000;
   1613 
   1614     /**
   1615      * Indicates that the View returned true when onSetAlpha() was called and that
   1616      * the alpha must be restored.
   1617      * {@hide}
   1618      */
   1619     static final int ALPHA_SET                      = 0x00040000;
   1620 
   1621     /**
   1622      * Set by {@link #setScrollContainer(boolean)}.
   1623      */
   1624     static final int SCROLL_CONTAINER               = 0x00080000;
   1625 
   1626     /**
   1627      * Set by {@link #setScrollContainer(boolean)}.
   1628      */
   1629     static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
   1630 
   1631     /**
   1632      * View flag indicating whether this view was invalidated (fully or partially.)
   1633      *
   1634      * @hide
   1635      */
   1636     static final int DIRTY                          = 0x00200000;
   1637 
   1638     /**
   1639      * View flag indicating whether this view was invalidated by an opaque
   1640      * invalidate request.
   1641      *
   1642      * @hide
   1643      */
   1644     static final int DIRTY_OPAQUE                   = 0x00400000;
   1645 
   1646     /**
   1647      * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
   1648      *
   1649      * @hide
   1650      */
   1651     static final int DIRTY_MASK                     = 0x00600000;
   1652 
   1653     /**
   1654      * Indicates whether the background is opaque.
   1655      *
   1656      * @hide
   1657      */
   1658     static final int OPAQUE_BACKGROUND              = 0x00800000;
   1659 
   1660     /**
   1661      * Indicates whether the scrollbars are opaque.
   1662      *
   1663      * @hide
   1664      */
   1665     static final int OPAQUE_SCROLLBARS              = 0x01000000;
   1666 
   1667     /**
   1668      * Indicates whether the view is opaque.
   1669      *
   1670      * @hide
   1671      */
   1672     static final int OPAQUE_MASK                    = 0x01800000;
   1673 
   1674     /**
   1675      * Indicates a prepressed state;
   1676      * the short time between ACTION_DOWN and recognizing
   1677      * a 'real' press. Prepressed is used to recognize quick taps
   1678      * even when they are shorter than ViewConfiguration.getTapTimeout().
   1679      *
   1680      * @hide
   1681      */
   1682     private static final int PREPRESSED             = 0x02000000;
   1683 
   1684     /**
   1685      * Indicates whether the view is temporarily detached.
   1686      *
   1687      * @hide
   1688      */
   1689     static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
   1690 
   1691     /**
   1692      * Indicates that we should awaken scroll bars once attached
   1693      *
   1694      * @hide
   1695      */
   1696     private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
   1697 
   1698     /**
   1699      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
   1700      * @hide
   1701      */
   1702     private static final int HOVERED              = 0x10000000;
   1703 
   1704     /**
   1705      * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
   1706      * for transform operations
   1707      *
   1708      * @hide
   1709      */
   1710     private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
   1711 
   1712     /** {@hide} */
   1713     static final int ACTIVATED                    = 0x40000000;
   1714 
   1715     /**
   1716      * Indicates that this view was specifically invalidated, not just dirtied because some
   1717      * child view was invalidated. The flag is used to determine when we need to recreate
   1718      * a view's display list (as opposed to just returning a reference to its existing
   1719      * display list).
   1720      *
   1721      * @hide
   1722      */
   1723     static final int INVALIDATED                  = 0x80000000;
   1724 
   1725     /* Masks for mPrivateFlags2 */
   1726 
   1727     /**
   1728      * Indicates that this view has reported that it can accept the current drag's content.
   1729      * Cleared when the drag operation concludes.
   1730      * @hide
   1731      */
   1732     static final int DRAG_CAN_ACCEPT              = 0x00000001;
   1733 
   1734     /**
   1735      * Indicates that this view is currently directly under the drag location in a
   1736      * drag-and-drop operation involving content that it can accept.  Cleared when
   1737      * the drag exits the view, or when the drag operation concludes.
   1738      * @hide
   1739      */
   1740     static final int DRAG_HOVERED                 = 0x00000002;
   1741 
   1742     /**
   1743      * Indicates whether the view layout direction has been resolved and drawn to the
   1744      * right-to-left direction.
   1745      *
   1746      * @hide
   1747      */
   1748     static final int LAYOUT_DIRECTION_RESOLVED_RTL = 0x00000004;
   1749 
   1750     /**
   1751      * Indicates whether the view layout direction has been resolved.
   1752      *
   1753      * @hide
   1754      */
   1755     static final int LAYOUT_DIRECTION_RESOLVED = 0x00000008;
   1756 
   1757 
   1758     /* End of masks for mPrivateFlags2 */
   1759 
   1760     static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
   1761 
   1762     /**
   1763      * Always allow a user to over-scroll this view, provided it is a
   1764      * view that can scroll.
   1765      *
   1766      * @see #getOverScrollMode()
   1767      * @see #setOverScrollMode(int)
   1768      */
   1769     public static final int OVER_SCROLL_ALWAYS = 0;
   1770 
   1771     /**
   1772      * Allow a user to over-scroll this view only if the content is large
   1773      * enough to meaningfully scroll, provided it is a view that can scroll.
   1774      *
   1775      * @see #getOverScrollMode()
   1776      * @see #setOverScrollMode(int)
   1777      */
   1778     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
   1779 
   1780     /**
   1781      * Never allow a user to over-scroll this view.
   1782      *
   1783      * @see #getOverScrollMode()
   1784      * @see #setOverScrollMode(int)
   1785      */
   1786     public static final int OVER_SCROLL_NEVER = 2;
   1787 
   1788     /**
   1789      * View has requested the system UI (status bar) to be visible (the default).
   1790      *
   1791      * @see #setSystemUiVisibility(int)
   1792      */
   1793     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
   1794 
   1795     /**
   1796      * View has requested the system UI to enter an unobtrusive "low profile" mode.
   1797      *
   1798      * This is for use in games, book readers, video players, or any other "immersive" application
   1799      * where the usual system chrome is deemed too distracting.
   1800      *
   1801      * In low profile mode, the status bar and/or navigation icons may dim.
   1802      *
   1803      * @see #setSystemUiVisibility(int)
   1804      */
   1805     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
   1806 
   1807     /**
   1808      * View has requested that the system navigation be temporarily hidden.
   1809      *
   1810      * This is an even less obtrusive state than that called for by
   1811      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
   1812      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
   1813      * those to disappear. This is useful (in conjunction with the
   1814      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
   1815      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
   1816      * window flags) for displaying content using every last pixel on the display.
   1817      *
   1818      * There is a limitation: because navigation controls are so important, the least user
   1819      * interaction will cause them to reappear immediately.
   1820      *
   1821      * @see #setSystemUiVisibility(int)
   1822      */
   1823     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
   1824 
   1825     /**
   1826      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
   1827      */
   1828     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
   1829 
   1830     /**
   1831      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
   1832      */
   1833     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
   1834 
   1835     /**
   1836      * @hide
   1837      *
   1838      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1839      * out of the public fields to keep the undefined bits out of the developer's way.
   1840      *
   1841      * Flag to make the status bar not expandable.  Unless you also
   1842      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
   1843      */
   1844     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
   1845 
   1846     /**
   1847      * @hide
   1848      *
   1849      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1850      * out of the public fields to keep the undefined bits out of the developer's way.
   1851      *
   1852      * Flag to hide notification icons and scrolling ticker text.
   1853      */
   1854     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
   1855 
   1856     /**
   1857      * @hide
   1858      *
   1859      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1860      * out of the public fields to keep the undefined bits out of the developer's way.
   1861      *
   1862      * Flag to disable incoming notification alerts.  This will not block
   1863      * icons, but it will block sound, vibrating and other visual or aural notifications.
   1864      */
   1865     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
   1866 
   1867     /**
   1868      * @hide
   1869      *
   1870      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1871      * out of the public fields to keep the undefined bits out of the developer's way.
   1872      *
   1873      * Flag to hide only the scrolling ticker.  Note that
   1874      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
   1875      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
   1876      */
   1877     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
   1878 
   1879     /**
   1880      * @hide
   1881      *
   1882      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1883      * out of the public fields to keep the undefined bits out of the developer's way.
   1884      *
   1885      * Flag to hide the center system info area.
   1886      */
   1887     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
   1888 
   1889     /**
   1890      * @hide
   1891      *
   1892      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1893      * out of the public fields to keep the undefined bits out of the developer's way.
   1894      *
   1895      * Flag to hide only the home button.  Don't use this
   1896      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   1897      */
   1898     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
   1899 
   1900     /**
   1901      * @hide
   1902      *
   1903      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1904      * out of the public fields to keep the undefined bits out of the developer's way.
   1905      *
   1906      * Flag to hide only the back button. Don't use this
   1907      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   1908      */
   1909     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
   1910 
   1911     /**
   1912      * @hide
   1913      *
   1914      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1915      * out of the public fields to keep the undefined bits out of the developer's way.
   1916      *
   1917      * Flag to hide only the clock.  You might use this if your activity has
   1918      * its own clock making the status bar's clock redundant.
   1919      */
   1920     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
   1921 
   1922     /**
   1923      * @hide
   1924      *
   1925      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   1926      * out of the public fields to keep the undefined bits out of the developer's way.
   1927      *
   1928      * Flag to hide only the recent apps button. Don't use this
   1929      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   1930      */
   1931     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
   1932 
   1933     /**
   1934      * @hide
   1935      *
   1936      * NOTE: This flag may only be used in subtreeSystemUiVisibility, etc. etc.
   1937      *
   1938      * This hides HOME and RECENT and is provided for compatibility with interim implementations.
   1939      */
   1940     @Deprecated
   1941     public static final int STATUS_BAR_DISABLE_NAVIGATION =
   1942             STATUS_BAR_DISABLE_HOME | STATUS_BAR_DISABLE_RECENT;
   1943 
   1944     /**
   1945      * @hide
   1946      */
   1947     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
   1948 
   1949     /**
   1950      * These are the system UI flags that can be cleared by events outside
   1951      * of an application.  Currently this is just the ability to tap on the
   1952      * screen while hiding the navigation bar to have it return.
   1953      * @hide
   1954      */
   1955     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
   1956             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   1957 
   1958     /**
   1959      * Find views that render the specified text.
   1960      *
   1961      * @see #findViewsWithText(ArrayList, CharSequence, int)
   1962      */
   1963     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
   1964 
   1965     /**
   1966      * Find find views that contain the specified content description.
   1967      *
   1968      * @see #findViewsWithText(ArrayList, CharSequence, int)
   1969      */
   1970     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
   1971 
   1972     /**
   1973      * Controls the over-scroll mode for this view.
   1974      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
   1975      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
   1976      * and {@link #OVER_SCROLL_NEVER}.
   1977      */
   1978     private int mOverScrollMode;
   1979 
   1980     /**
   1981      * The parent this view is attached to.
   1982      * {@hide}
   1983      *
   1984      * @see #getParent()
   1985      */
   1986     protected ViewParent mParent;
   1987 
   1988     /**
   1989      * {@hide}
   1990      */
   1991     AttachInfo mAttachInfo;
   1992 
   1993     /**
   1994      * {@hide}
   1995      */
   1996     @ViewDebug.ExportedProperty(flagMapping = {
   1997         @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
   1998                 name = "FORCE_LAYOUT"),
   1999         @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
   2000                 name = "LAYOUT_REQUIRED"),
   2001         @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
   2002             name = "DRAWING_CACHE_INVALID", outputIf = false),
   2003         @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
   2004         @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
   2005         @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
   2006         @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
   2007     })
   2008     int mPrivateFlags;
   2009     int mPrivateFlags2;
   2010 
   2011     /**
   2012      * This view's request for the visibility of the status bar.
   2013      * @hide
   2014      */
   2015     @ViewDebug.ExportedProperty(flagMapping = {
   2016         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
   2017                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
   2018                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
   2019         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   2020                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   2021                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
   2022         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
   2023                                 equals = SYSTEM_UI_FLAG_VISIBLE,
   2024                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
   2025     })
   2026     int mSystemUiVisibility;
   2027 
   2028     /**
   2029      * Count of how many windows this view has been attached to.
   2030      */
   2031     int mWindowAttachCount;
   2032 
   2033     /**
   2034      * The layout parameters associated with this view and used by the parent
   2035      * {@link android.view.ViewGroup} to determine how this view should be
   2036      * laid out.
   2037      * {@hide}
   2038      */
   2039     protected ViewGroup.LayoutParams mLayoutParams;
   2040 
   2041     /**
   2042      * The view flags hold various views states.
   2043      * {@hide}
   2044      */
   2045     @ViewDebug.ExportedProperty
   2046     int mViewFlags;
   2047 
   2048     static class TransformationInfo {
   2049         /**
   2050          * The transform matrix for the View. This transform is calculated internally
   2051          * based on the rotation, scaleX, and scaleY properties. The identity matrix
   2052          * is used by default. Do *not* use this variable directly; instead call
   2053          * getMatrix(), which will automatically recalculate the matrix if necessary
   2054          * to get the correct matrix based on the latest rotation and scale properties.
   2055          */
   2056         private final Matrix mMatrix = new Matrix();
   2057 
   2058         /**
   2059          * The transform matrix for the View. This transform is calculated internally
   2060          * based on the rotation, scaleX, and scaleY properties. The identity matrix
   2061          * is used by default. Do *not* use this variable directly; instead call
   2062          * getInverseMatrix(), which will automatically recalculate the matrix if necessary
   2063          * to get the correct matrix based on the latest rotation and scale properties.
   2064          */
   2065         private Matrix mInverseMatrix;
   2066 
   2067         /**
   2068          * An internal variable that tracks whether we need to recalculate the
   2069          * transform matrix, based on whether the rotation or scaleX/Y properties
   2070          * have changed since the matrix was last calculated.
   2071          */
   2072         boolean mMatrixDirty = false;
   2073 
   2074         /**
   2075          * An internal variable that tracks whether we need to recalculate the
   2076          * transform matrix, based on whether the rotation or scaleX/Y properties
   2077          * have changed since the matrix was last calculated.
   2078          */
   2079         private boolean mInverseMatrixDirty = true;
   2080 
   2081         /**
   2082          * A variable that tracks whether we need to recalculate the
   2083          * transform matrix, based on whether the rotation or scaleX/Y properties
   2084          * have changed since the matrix was last calculated. This variable
   2085          * is only valid after a call to updateMatrix() or to a function that
   2086          * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
   2087          */
   2088         private boolean mMatrixIsIdentity = true;
   2089 
   2090         /**
   2091          * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
   2092          */
   2093         private Camera mCamera = null;
   2094 
   2095         /**
   2096          * This matrix is used when computing the matrix for 3D rotations.
   2097          */
   2098         private Matrix matrix3D = null;
   2099 
   2100         /**
   2101          * These prev values are used to recalculate a centered pivot point when necessary. The
   2102          * pivot point is only used in matrix operations (when rotation, scale, or translation are
   2103          * set), so thes values are only used then as well.
   2104          */
   2105         private int mPrevWidth = -1;
   2106         private int mPrevHeight = -1;
   2107 
   2108         /**
   2109          * The degrees rotation around the vertical axis through the pivot point.
   2110          */
   2111         @ViewDebug.ExportedProperty
   2112         float mRotationY = 0f;
   2113 
   2114         /**
   2115          * The degrees rotation around the horizontal axis through the pivot point.
   2116          */
   2117         @ViewDebug.ExportedProperty
   2118         float mRotationX = 0f;
   2119 
   2120         /**
   2121          * The degrees rotation around the pivot point.
   2122          */
   2123         @ViewDebug.ExportedProperty
   2124         float mRotation = 0f;
   2125 
   2126         /**
   2127          * The amount of translation of the object away from its left property (post-layout).
   2128          */
   2129         @ViewDebug.ExportedProperty
   2130         float mTranslationX = 0f;
   2131 
   2132         /**
   2133          * The amount of translation of the object away from its top property (post-layout).
   2134          */
   2135         @ViewDebug.ExportedProperty
   2136         float mTranslationY = 0f;
   2137 
   2138         /**
   2139          * The amount of scale in the x direction around the pivot point. A
   2140          * value of 1 means no scaling is applied.
   2141          */
   2142         @ViewDebug.ExportedProperty
   2143         float mScaleX = 1f;
   2144 
   2145         /**
   2146          * The amount of scale in the y direction around the pivot point. A
   2147          * value of 1 means no scaling is applied.
   2148          */
   2149         @ViewDebug.ExportedProperty
   2150         float mScaleY = 1f;
   2151 
   2152         /**
   2153          * The amount of scale in the x direction around the pivot point. A
   2154          * value of 1 means no scaling is applied.
   2155          */
   2156         @ViewDebug.ExportedProperty
   2157         float mPivotX = 0f;
   2158 
   2159         /**
   2160          * The amount of scale in the y direction around the pivot point. A
   2161          * value of 1 means no scaling is applied.
   2162          */
   2163         @ViewDebug.ExportedProperty
   2164         float mPivotY = 0f;
   2165 
   2166         /**
   2167          * The opacity of the View. This is a value from 0 to 1, where 0 means
   2168          * completely transparent and 1 means completely opaque.
   2169          */
   2170         @ViewDebug.ExportedProperty
   2171         float mAlpha = 1f;
   2172     }
   2173 
   2174     TransformationInfo mTransformationInfo;
   2175 
   2176     private boolean mLastIsOpaque;
   2177 
   2178     /**
   2179      * Convenience value to check for float values that are close enough to zero to be considered
   2180      * zero.
   2181      */
   2182     private static final float NONZERO_EPSILON = .001f;
   2183 
   2184     /**
   2185      * The distance in pixels from the left edge of this view's parent
   2186      * to the left edge of this view.
   2187      * {@hide}
   2188      */
   2189     @ViewDebug.ExportedProperty(category = "layout")
   2190     protected int mLeft;
   2191     /**
   2192      * The distance in pixels from the left edge of this view's parent
   2193      * to the right edge of this view.
   2194      * {@hide}
   2195      */
   2196     @ViewDebug.ExportedProperty(category = "layout")
   2197     protected int mRight;
   2198     /**
   2199      * The distance in pixels from the top edge of this view's parent
   2200      * to the top edge of this view.
   2201      * {@hide}
   2202      */
   2203     @ViewDebug.ExportedProperty(category = "layout")
   2204     protected int mTop;
   2205     /**
   2206      * The distance in pixels from the top edge of this view's parent
   2207      * to the bottom edge of this view.
   2208      * {@hide}
   2209      */
   2210     @ViewDebug.ExportedProperty(category = "layout")
   2211     protected int mBottom;
   2212 
   2213     /**
   2214      * The offset, in pixels, by which the content of this view is scrolled
   2215      * horizontally.
   2216      * {@hide}
   2217      */
   2218     @ViewDebug.ExportedProperty(category = "scrolling")
   2219     protected int mScrollX;
   2220     /**
   2221      * The offset, in pixels, by which the content of this view is scrolled
   2222      * vertically.
   2223      * {@hide}
   2224      */
   2225     @ViewDebug.ExportedProperty(category = "scrolling")
   2226     protected int mScrollY;
   2227 
   2228     /**
   2229      * The left padding in pixels, that is the distance in pixels between the
   2230      * left edge of this view and the left edge of its content.
   2231      * {@hide}
   2232      */
   2233     @ViewDebug.ExportedProperty(category = "padding")
   2234     protected int mPaddingLeft;
   2235     /**
   2236      * The right padding in pixels, that is the distance in pixels between the
   2237      * right edge of this view and the right edge of its content.
   2238      * {@hide}
   2239      */
   2240     @ViewDebug.ExportedProperty(category = "padding")
   2241     protected int mPaddingRight;
   2242     /**
   2243      * The top padding in pixels, that is the distance in pixels between the
   2244      * top edge of this view and the top edge of its content.
   2245      * {@hide}
   2246      */
   2247     @ViewDebug.ExportedProperty(category = "padding")
   2248     protected int mPaddingTop;
   2249     /**
   2250      * The bottom padding in pixels, that is the distance in pixels between the
   2251      * bottom edge of this view and the bottom edge of its content.
   2252      * {@hide}
   2253      */
   2254     @ViewDebug.ExportedProperty(category = "padding")
   2255     protected int mPaddingBottom;
   2256 
   2257     /**
   2258      * Briefly describes the view and is primarily used for accessibility support.
   2259      */
   2260     private CharSequence mContentDescription;
   2261 
   2262     /**
   2263      * Cache the paddingRight set by the user to append to the scrollbar's size.
   2264      *
   2265      * @hide
   2266      */
   2267     @ViewDebug.ExportedProperty(category = "padding")
   2268     protected int mUserPaddingRight;
   2269 
   2270     /**
   2271      * Cache the paddingBottom set by the user to append to the scrollbar's size.
   2272      *
   2273      * @hide
   2274      */
   2275     @ViewDebug.ExportedProperty(category = "padding")
   2276     protected int mUserPaddingBottom;
   2277 
   2278     /**
   2279      * Cache the paddingLeft set by the user to append to the scrollbar's size.
   2280      *
   2281      * @hide
   2282      */
   2283     @ViewDebug.ExportedProperty(category = "padding")
   2284     protected int mUserPaddingLeft;
   2285 
   2286     /**
   2287      * Cache if the user padding is relative.
   2288      *
   2289      */
   2290     @ViewDebug.ExportedProperty(category = "padding")
   2291     boolean mUserPaddingRelative;
   2292 
   2293     /**
   2294      * Cache the paddingStart set by the user to append to the scrollbar's size.
   2295      *
   2296      */
   2297     @ViewDebug.ExportedProperty(category = "padding")
   2298     int mUserPaddingStart;
   2299 
   2300     /**
   2301      * Cache the paddingEnd set by the user to append to the scrollbar's size.
   2302      *
   2303      */
   2304     @ViewDebug.ExportedProperty(category = "padding")
   2305     int mUserPaddingEnd;
   2306 
   2307     /**
   2308      * @hide
   2309      */
   2310     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
   2311     /**
   2312      * @hide
   2313      */
   2314     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
   2315 
   2316     private Drawable mBGDrawable;
   2317 
   2318     private int mBackgroundResource;
   2319     private boolean mBackgroundSizeChanged;
   2320 
   2321     static class ListenerInfo {
   2322         /**
   2323          * Listener used to dispatch focus change events.
   2324          * This field should be made private, so it is hidden from the SDK.
   2325          * {@hide}
   2326          */
   2327         protected OnFocusChangeListener mOnFocusChangeListener;
   2328 
   2329         /**
   2330          * Listeners for layout change events.
   2331          */
   2332         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
   2333 
   2334         /**
   2335          * Listeners for attach events.
   2336          */
   2337         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
   2338 
   2339         /**
   2340          * Listener used to dispatch click events.
   2341          * This field should be made private, so it is hidden from the SDK.
   2342          * {@hide}
   2343          */
   2344         public OnClickListener mOnClickListener;
   2345 
   2346         /**
   2347          * Listener used to dispatch long click events.
   2348          * This field should be made private, so it is hidden from the SDK.
   2349          * {@hide}
   2350          */
   2351         protected OnLongClickListener mOnLongClickListener;
   2352 
   2353         /**
   2354          * Listener used to build the context menu.
   2355          * This field should be made private, so it is hidden from the SDK.
   2356          * {@hide}
   2357          */
   2358         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
   2359 
   2360         private OnKeyListener mOnKeyListener;
   2361 
   2362         private OnTouchListener mOnTouchListener;
   2363 
   2364         private OnHoverListener mOnHoverListener;
   2365 
   2366         private OnGenericMotionListener mOnGenericMotionListener;
   2367 
   2368         private OnDragListener mOnDragListener;
   2369 
   2370         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
   2371     }
   2372 
   2373     ListenerInfo mListenerInfo;
   2374 
   2375     /**
   2376      * The application environment this view lives in.
   2377      * This field should be made private, so it is hidden from the SDK.
   2378      * {@hide}
   2379      */
   2380     protected Context mContext;
   2381 
   2382     private final Resources mResources;
   2383 
   2384     private ScrollabilityCache mScrollCache;
   2385 
   2386     private int[] mDrawableState = null;
   2387 
   2388     /**
   2389      * Set to true when drawing cache is enabled and cannot be created.
   2390      *
   2391      * @hide
   2392      */
   2393     public boolean mCachingFailed;
   2394 
   2395     private Bitmap mDrawingCache;
   2396     private Bitmap mUnscaledDrawingCache;
   2397     private HardwareLayer mHardwareLayer;
   2398     DisplayList mDisplayList;
   2399 
   2400     /**
   2401      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
   2402      * the user may specify which view to go to next.
   2403      */
   2404     private int mNextFocusLeftId = View.NO_ID;
   2405 
   2406     /**
   2407      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
   2408      * the user may specify which view to go to next.
   2409      */
   2410     private int mNextFocusRightId = View.NO_ID;
   2411 
   2412     /**
   2413      * When this view has focus and the next focus is {@link #FOCUS_UP},
   2414      * the user may specify which view to go to next.
   2415      */
   2416     private int mNextFocusUpId = View.NO_ID;
   2417 
   2418     /**
   2419      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
   2420      * the user may specify which view to go to next.
   2421      */
   2422     private int mNextFocusDownId = View.NO_ID;
   2423 
   2424     /**
   2425      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
   2426      * the user may specify which view to go to next.
   2427      */
   2428     int mNextFocusForwardId = View.NO_ID;
   2429 
   2430     private CheckForLongPress mPendingCheckForLongPress;
   2431     private CheckForTap mPendingCheckForTap = null;
   2432     private PerformClick mPerformClick;
   2433     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
   2434 
   2435     private UnsetPressedState mUnsetPressedState;
   2436 
   2437     /**
   2438      * Whether the long press's action has been invoked.  The tap's action is invoked on the
   2439      * up event while a long press is invoked as soon as the long press duration is reached, so
   2440      * a long press could be performed before the tap is checked, in which case the tap's action
   2441      * should not be invoked.
   2442      */
   2443     private boolean mHasPerformedLongPress;
   2444 
   2445     /**
   2446      * The minimum height of the view. We'll try our best to have the height
   2447      * of this view to at least this amount.
   2448      */
   2449     @ViewDebug.ExportedProperty(category = "measurement")
   2450     private int mMinHeight;
   2451 
   2452     /**
   2453      * The minimum width of the view. We'll try our best to have the width
   2454      * of this view to at least this amount.
   2455      */
   2456     @ViewDebug.ExportedProperty(category = "measurement")
   2457     private int mMinWidth;
   2458 
   2459     /**
   2460      * The delegate to handle touch events that are physically in this view
   2461      * but should be handled by another view.
   2462      */
   2463     private TouchDelegate mTouchDelegate = null;
   2464 
   2465     /**
   2466      * Solid color to use as a background when creating the drawing cache. Enables
   2467      * the cache to use 16 bit bitmaps instead of 32 bit.
   2468      */
   2469     private int mDrawingCacheBackgroundColor = 0;
   2470 
   2471     /**
   2472      * Special tree observer used when mAttachInfo is null.
   2473      */
   2474     private ViewTreeObserver mFloatingTreeObserver;
   2475 
   2476     /**
   2477      * Cache the touch slop from the context that created the view.
   2478      */
   2479     private int mTouchSlop;
   2480 
   2481     /**
   2482      * Object that handles automatic animation of view properties.
   2483      */
   2484     private ViewPropertyAnimator mAnimator = null;
   2485 
   2486     /**
   2487      * Flag indicating that a drag can cross window boundaries.  When
   2488      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
   2489      * with this flag set, all visible applications will be able to participate
   2490      * in the drag operation and receive the dragged content.
   2491      *
   2492      * @hide
   2493      */
   2494     public static final int DRAG_FLAG_GLOBAL = 1;
   2495 
   2496     /**
   2497      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
   2498      */
   2499     private float mVerticalScrollFactor;
   2500 
   2501     /**
   2502      * Position of the vertical scroll bar.
   2503      */
   2504     private int mVerticalScrollbarPosition;
   2505 
   2506     /**
   2507      * Position the scroll bar at the default position as determined by the system.
   2508      */
   2509     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
   2510 
   2511     /**
   2512      * Position the scroll bar along the left edge.
   2513      */
   2514     public static final int SCROLLBAR_POSITION_LEFT = 1;
   2515 
   2516     /**
   2517      * Position the scroll bar along the right edge.
   2518      */
   2519     public static final int SCROLLBAR_POSITION_RIGHT = 2;
   2520 
   2521     /**
   2522      * Indicates that the view does not have a layer.
   2523      *
   2524      * @see #getLayerType()
   2525      * @see #setLayerType(int, android.graphics.Paint)
   2526      * @see #LAYER_TYPE_SOFTWARE
   2527      * @see #LAYER_TYPE_HARDWARE
   2528      */
   2529     public static final int LAYER_TYPE_NONE = 0;
   2530 
   2531     /**
   2532      * <p>Indicates that the view has a software layer. A software layer is backed
   2533      * by a bitmap and causes the view to be rendered using Android's software
   2534      * rendering pipeline, even if hardware acceleration is enabled.</p>
   2535      *
   2536      * <p>Software layers have various usages:</p>
   2537      * <p>When the application is not using hardware acceleration, a software layer
   2538      * is useful to apply a specific color filter and/or blending mode and/or
   2539      * translucency to a view and all its children.</p>
   2540      * <p>When the application is using hardware acceleration, a software layer
   2541      * is useful to render drawing primitives not supported by the hardware
   2542      * accelerated pipeline. It can also be used to cache a complex view tree
   2543      * into a texture and reduce the complexity of drawing operations. For instance,
   2544      * when animating a complex view tree with a translation, a software layer can
   2545      * be used to render the view tree only once.</p>
   2546      * <p>Software layers should be avoided when the affected view tree updates
   2547      * often. Every update will require to re-render the software layer, which can
   2548      * potentially be slow (particularly when hardware acceleration is turned on
   2549      * since the layer will have to be uploaded into a hardware texture after every
   2550      * update.)</p>
   2551      *
   2552      * @see #getLayerType()
   2553      * @see #setLayerType(int, android.graphics.Paint)
   2554      * @see #LAYER_TYPE_NONE
   2555      * @see #LAYER_TYPE_HARDWARE
   2556      */
   2557     public static final int LAYER_TYPE_SOFTWARE = 1;
   2558 
   2559     /**
   2560      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
   2561      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
   2562      * OpenGL hardware) and causes the view to be rendered using Android's hardware
   2563      * rendering pipeline, but only if hardware acceleration is turned on for the
   2564      * view hierarchy. When hardware acceleration is turned off, hardware layers
   2565      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
   2566      *
   2567      * <p>A hardware layer is useful to apply a specific color filter and/or
   2568      * blending mode and/or translucency to a view and all its children.</p>
   2569      * <p>A hardware layer can be used to cache a complex view tree into a
   2570      * texture and reduce the complexity of drawing operations. For instance,
   2571      * when animating a complex view tree with a translation, a hardware layer can
   2572      * be used to render the view tree only once.</p>
   2573      * <p>A hardware layer can also be used to increase the rendering quality when
   2574      * rotation transformations are applied on a view. It can also be used to
   2575      * prevent potential clipping issues when applying 3D transforms on a view.</p>
   2576      *
   2577      * @see #getLayerType()
   2578      * @see #setLayerType(int, android.graphics.Paint)
   2579      * @see #LAYER_TYPE_NONE
   2580      * @see #LAYER_TYPE_SOFTWARE
   2581      */
   2582     public static final int LAYER_TYPE_HARDWARE = 2;
   2583 
   2584     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
   2585             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
   2586             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
   2587             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
   2588     })
   2589     int mLayerType = LAYER_TYPE_NONE;
   2590     Paint mLayerPaint;
   2591     Rect mLocalDirtyRect;
   2592 
   2593     /**
   2594      * Set to true when the view is sending hover accessibility events because it
   2595      * is the innermost hovered view.
   2596      */
   2597     private boolean mSendingHoverAccessibilityEvents;
   2598 
   2599     /**
   2600      * Delegate for injecting accessiblity functionality.
   2601      */
   2602     AccessibilityDelegate mAccessibilityDelegate;
   2603 
   2604     /**
   2605      * Text direction is inherited thru {@link ViewGroup}
   2606      * @hide
   2607      */
   2608     public static final int TEXT_DIRECTION_INHERIT = 0;
   2609 
   2610     /**
   2611      * Text direction is using "first strong algorithm". The first strong directional character
   2612      * determines the paragraph direction. If there is no strong directional character, the
   2613      * paragraph direction is the view's resolved ayout direction.
   2614      *
   2615      * @hide
   2616      */
   2617     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
   2618 
   2619     /**
   2620      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
   2621      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
   2622      * If there are neither, the paragraph direction is the view's resolved layout direction.
   2623      *
   2624      * @hide
   2625      */
   2626     public static final int TEXT_DIRECTION_ANY_RTL = 2;
   2627 
   2628     /**
   2629      * Text direction is forced to LTR.
   2630      *
   2631      * @hide
   2632      */
   2633     public static final int TEXT_DIRECTION_LTR = 3;
   2634 
   2635     /**
   2636      * Text direction is forced to RTL.
   2637      *
   2638      * @hide
   2639      */
   2640     public static final int TEXT_DIRECTION_RTL = 4;
   2641 
   2642     /**
   2643      * Default text direction is inherited
   2644      *
   2645      * @hide
   2646      */
   2647     protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
   2648 
   2649     /**
   2650      * The text direction that has been defined by {@link #setTextDirection(int)}.
   2651      *
   2652      * {@hide}
   2653      */
   2654     @ViewDebug.ExportedProperty(category = "text", mapping = {
   2655             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   2656             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   2657             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   2658             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   2659             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
   2660     })
   2661     private int mTextDirection = DEFAULT_TEXT_DIRECTION;
   2662 
   2663     /**
   2664      * The resolved text direction.  This needs resolution if the value is
   2665      * TEXT_DIRECTION_INHERIT.  The resolution matches mTextDirection if that is
   2666      * not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent
   2667      * chain of the view.
   2668      *
   2669      * {@hide}
   2670      */
   2671     @ViewDebug.ExportedProperty(category = "text", mapping = {
   2672             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   2673             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   2674             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   2675             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   2676             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
   2677     })
   2678     private int mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
   2679 
   2680     /**
   2681      * Consistency verifier for debugging purposes.
   2682      * @hide
   2683      */
   2684     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
   2685             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
   2686                     new InputEventConsistencyVerifier(this, 0) : null;
   2687 
   2688     /**
   2689      * Simple constructor to use when creating a view from code.
   2690      *
   2691      * @param context The Context the view is running in, through which it can
   2692      *        access the current theme, resources, etc.
   2693      */
   2694     public View(Context context) {
   2695         mContext = context;
   2696         mResources = context != null ? context.getResources() : null;
   2697         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | LAYOUT_DIRECTION_INHERIT;
   2698         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
   2699         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
   2700         mUserPaddingStart = -1;
   2701         mUserPaddingEnd = -1;
   2702         mUserPaddingRelative = false;
   2703     }
   2704 
   2705     /**
   2706      * Constructor that is called when inflating a view from XML. This is called
   2707      * when a view is being constructed from an XML file, supplying attributes
   2708      * that were specified in the XML file. This version uses a default style of
   2709      * 0, so the only attribute values applied are those in the Context's Theme
   2710      * and the given AttributeSet.
   2711      *
   2712      * <p>
   2713      * The method onFinishInflate() will be called after all children have been
   2714      * added.
   2715      *
   2716      * @param context The Context the view is running in, through which it can
   2717      *        access the current theme, resources, etc.
   2718      * @param attrs The attributes of the XML tag that is inflating the view.
   2719      * @see #View(Context, AttributeSet, int)
   2720      */
   2721     public View(Context context, AttributeSet attrs) {
   2722         this(context, attrs, 0);
   2723     }
   2724 
   2725     /**
   2726      * Perform inflation from XML and apply a class-specific base style. This
   2727      * constructor of View allows subclasses to use their own base style when
   2728      * they are inflating. For example, a Button class's constructor would call
   2729      * this version of the super class constructor and supply
   2730      * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
   2731      * the theme's button style to modify all of the base view attributes (in
   2732      * particular its background) as well as the Button class's attributes.
   2733      *
   2734      * @param context The Context the view is running in, through which it can
   2735      *        access the current theme, resources, etc.
   2736      * @param attrs The attributes of the XML tag that is inflating the view.
   2737      * @param defStyle The default style to apply to this view. If 0, no style
   2738      *        will be applied (beyond what is included in the theme). This may
   2739      *        either be an attribute resource, whose value will be retrieved
   2740      *        from the current theme, or an explicit style resource.
   2741      * @see #View(Context, AttributeSet)
   2742      */
   2743     public View(Context context, AttributeSet attrs, int defStyle) {
   2744         this(context);
   2745 
   2746         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
   2747                 defStyle, 0);
   2748 
   2749         Drawable background = null;
   2750 
   2751         int leftPadding = -1;
   2752         int topPadding = -1;
   2753         int rightPadding = -1;
   2754         int bottomPadding = -1;
   2755         int startPadding = -1;
   2756         int endPadding = -1;
   2757 
   2758         int padding = -1;
   2759 
   2760         int viewFlagValues = 0;
   2761         int viewFlagMasks = 0;
   2762 
   2763         boolean setScrollContainer = false;
   2764 
   2765         int x = 0;
   2766         int y = 0;
   2767 
   2768         float tx = 0;
   2769         float ty = 0;
   2770         float rotation = 0;
   2771         float rotationX = 0;
   2772         float rotationY = 0;
   2773         float sx = 1f;
   2774         float sy = 1f;
   2775         boolean transformSet = false;
   2776 
   2777         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
   2778 
   2779         int overScrollMode = mOverScrollMode;
   2780         final int N = a.getIndexCount();
   2781         for (int i = 0; i < N; i++) {
   2782             int attr = a.getIndex(i);
   2783             switch (attr) {
   2784                 case com.android.internal.R.styleable.View_background:
   2785                     background = a.getDrawable(attr);
   2786                     break;
   2787                 case com.android.internal.R.styleable.View_padding:
   2788                     padding = a.getDimensionPixelSize(attr, -1);
   2789                     break;
   2790                  case com.android.internal.R.styleable.View_paddingLeft:
   2791                     leftPadding = a.getDimensionPixelSize(attr, -1);
   2792                     break;
   2793                 case com.android.internal.R.styleable.View_paddingTop:
   2794                     topPadding = a.getDimensionPixelSize(attr, -1);
   2795                     break;
   2796                 case com.android.internal.R.styleable.View_paddingRight:
   2797                     rightPadding = a.getDimensionPixelSize(attr, -1);
   2798                     break;
   2799                 case com.android.internal.R.styleable.View_paddingBottom:
   2800                     bottomPadding = a.getDimensionPixelSize(attr, -1);
   2801                     break;
   2802                 case com.android.internal.R.styleable.View_paddingStart:
   2803                     startPadding = a.getDimensionPixelSize(attr, -1);
   2804                     break;
   2805                 case com.android.internal.R.styleable.View_paddingEnd:
   2806                     endPadding = a.getDimensionPixelSize(attr, -1);
   2807                     break;
   2808                 case com.android.internal.R.styleable.View_scrollX:
   2809                     x = a.getDimensionPixelOffset(attr, 0);
   2810                     break;
   2811                 case com.android.internal.R.styleable.View_scrollY:
   2812                     y = a.getDimensionPixelOffset(attr, 0);
   2813                     break;
   2814                 case com.android.internal.R.styleable.View_alpha:
   2815                     setAlpha(a.getFloat(attr, 1f));
   2816                     break;
   2817                 case com.android.internal.R.styleable.View_transformPivotX:
   2818                     setPivotX(a.getDimensionPixelOffset(attr, 0));
   2819                     break;
   2820                 case com.android.internal.R.styleable.View_transformPivotY:
   2821                     setPivotY(a.getDimensionPixelOffset(attr, 0));
   2822                     break;
   2823                 case com.android.internal.R.styleable.View_translationX:
   2824                     tx = a.getDimensionPixelOffset(attr, 0);
   2825                     transformSet = true;
   2826                     break;
   2827                 case com.android.internal.R.styleable.View_translationY:
   2828                     ty = a.getDimensionPixelOffset(attr, 0);
   2829                     transformSet = true;
   2830                     break;
   2831                 case com.android.internal.R.styleable.View_rotation:
   2832                     rotation = a.getFloat(attr, 0);
   2833                     transformSet = true;
   2834                     break;
   2835                 case com.android.internal.R.styleable.View_rotationX:
   2836                     rotationX = a.getFloat(attr, 0);
   2837                     transformSet = true;
   2838                     break;
   2839                 case com.android.internal.R.styleable.View_rotationY:
   2840                     rotationY = a.getFloat(attr, 0);
   2841                     transformSet = true;
   2842                     break;
   2843                 case com.android.internal.R.styleable.View_scaleX:
   2844                     sx = a.getFloat(attr, 1f);
   2845                     transformSet = true;
   2846                     break;
   2847                 case com.android.internal.R.styleable.View_scaleY:
   2848                     sy = a.getFloat(attr, 1f);
   2849                     transformSet = true;
   2850                     break;
   2851                 case com.android.internal.R.styleable.View_id:
   2852                     mID = a.getResourceId(attr, NO_ID);
   2853                     break;
   2854                 case com.android.internal.R.styleable.View_tag:
   2855                     mTag = a.getText(attr);
   2856                     break;
   2857                 case com.android.internal.R.styleable.View_fitsSystemWindows:
   2858                     if (a.getBoolean(attr, false)) {
   2859                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
   2860                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
   2861                     }
   2862                     break;
   2863                 case com.android.internal.R.styleable.View_focusable:
   2864                     if (a.getBoolean(attr, false)) {
   2865                         viewFlagValues |= FOCUSABLE;
   2866                         viewFlagMasks |= FOCUSABLE_MASK;
   2867                     }
   2868                     break;
   2869                 case com.android.internal.R.styleable.View_focusableInTouchMode:
   2870                     if (a.getBoolean(attr, false)) {
   2871                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
   2872                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
   2873                     }
   2874                     break;
   2875                 case com.android.internal.R.styleable.View_clickable:
   2876                     if (a.getBoolean(attr, false)) {
   2877                         viewFlagValues |= CLICKABLE;
   2878                         viewFlagMasks |= CLICKABLE;
   2879                     }
   2880                     break;
   2881                 case com.android.internal.R.styleable.View_longClickable:
   2882                     if (a.getBoolean(attr, false)) {
   2883                         viewFlagValues |= LONG_CLICKABLE;
   2884                         viewFlagMasks |= LONG_CLICKABLE;
   2885                     }
   2886                     break;
   2887                 case com.android.internal.R.styleable.View_saveEnabled:
   2888                     if (!a.getBoolean(attr, true)) {
   2889                         viewFlagValues |= SAVE_DISABLED;
   2890                         viewFlagMasks |= SAVE_DISABLED_MASK;
   2891                     }
   2892                     break;
   2893                 case com.android.internal.R.styleable.View_duplicateParentState:
   2894                     if (a.getBoolean(attr, false)) {
   2895                         viewFlagValues |= DUPLICATE_PARENT_STATE;
   2896                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
   2897                     }
   2898                     break;
   2899                 case com.android.internal.R.styleable.View_visibility:
   2900                     final int visibility = a.getInt(attr, 0);
   2901                     if (visibility != 0) {
   2902                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
   2903                         viewFlagMasks |= VISIBILITY_MASK;
   2904                     }
   2905                     break;
   2906                 case com.android.internal.R.styleable.View_layoutDirection:
   2907                     // Clear any HORIZONTAL_DIRECTION flag already set
   2908                     viewFlagValues &= ~LAYOUT_DIRECTION_MASK;
   2909                     // Set the HORIZONTAL_DIRECTION flags depending on the value of the attribute
   2910                     final int layoutDirection = a.getInt(attr, -1);
   2911                     if (layoutDirection != -1) {
   2912                         viewFlagValues |= LAYOUT_DIRECTION_FLAGS[layoutDirection];
   2913                     } else {
   2914                         // Set to default (LAYOUT_DIRECTION_INHERIT)
   2915                         viewFlagValues |= LAYOUT_DIRECTION_DEFAULT;
   2916                     }
   2917                     viewFlagMasks |= LAYOUT_DIRECTION_MASK;
   2918                     break;
   2919                 case com.android.internal.R.styleable.View_drawingCacheQuality:
   2920                     final int cacheQuality = a.getInt(attr, 0);
   2921                     if (cacheQuality != 0) {
   2922                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
   2923                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
   2924                     }
   2925                     break;
   2926                 case com.android.internal.R.styleable.View_contentDescription:
   2927                     mContentDescription = a.getString(attr);
   2928                     break;
   2929                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
   2930                     if (!a.getBoolean(attr, true)) {
   2931                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
   2932                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
   2933                     }
   2934                     break;
   2935                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
   2936                     if (!a.getBoolean(attr, true)) {
   2937                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
   2938                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
   2939                     }
   2940                     break;
   2941                 case R.styleable.View_scrollbars:
   2942                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
   2943                     if (scrollbars != SCROLLBARS_NONE) {
   2944                         viewFlagValues |= scrollbars;
   2945                         viewFlagMasks |= SCROLLBARS_MASK;
   2946                         initializeScrollbars(a);
   2947                     }
   2948                     break;
   2949                 //noinspection deprecation
   2950                 case R.styleable.View_fadingEdge:
   2951                     if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
   2952                         // Ignore the attribute starting with ICS
   2953                         break;
   2954                     }
   2955                     // With builds < ICS, fall through and apply fading edges
   2956                 case R.styleable.View_requiresFadingEdge:
   2957                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
   2958                     if (fadingEdge != FADING_EDGE_NONE) {
   2959                         viewFlagValues |= fadingEdge;
   2960                         viewFlagMasks |= FADING_EDGE_MASK;
   2961                         initializeFadingEdge(a);
   2962                     }
   2963                     break;
   2964                 case R.styleable.View_scrollbarStyle:
   2965                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
   2966                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   2967                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
   2968                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
   2969                     }
   2970                     break;
   2971                 case R.styleable.View_isScrollContainer:
   2972                     setScrollContainer = true;
   2973                     if (a.getBoolean(attr, false)) {
   2974                         setScrollContainer(true);
   2975                     }
   2976                     break;
   2977                 case com.android.internal.R.styleable.View_keepScreenOn:
   2978                     if (a.getBoolean(attr, false)) {
   2979                         viewFlagValues |= KEEP_SCREEN_ON;
   2980                         viewFlagMasks |= KEEP_SCREEN_ON;
   2981                     }
   2982                     break;
   2983                 case R.styleable.View_filterTouchesWhenObscured:
   2984                     if (a.getBoolean(attr, false)) {
   2985                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
   2986                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
   2987                     }
   2988                     break;
   2989                 case R.styleable.View_nextFocusLeft:
   2990                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
   2991                     break;
   2992                 case R.styleable.View_nextFocusRight:
   2993                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
   2994                     break;
   2995                 case R.styleable.View_nextFocusUp:
   2996                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
   2997                     break;
   2998                 case R.styleable.View_nextFocusDown:
   2999                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
   3000                     break;
   3001                 case R.styleable.View_nextFocusForward:
   3002                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
   3003                     break;
   3004                 case R.styleable.View_minWidth:
   3005                     mMinWidth = a.getDimensionPixelSize(attr, 0);
   3006                     break;
   3007                 case R.styleable.View_minHeight:
   3008                     mMinHeight = a.getDimensionPixelSize(attr, 0);
   3009                     break;
   3010                 case R.styleable.View_onClick:
   3011                     if (context.isRestricted()) {
   3012                         throw new IllegalStateException("The android:onClick attribute cannot "
   3013                                 + "be used within a restricted context");
   3014                     }
   3015 
   3016                     final String handlerName = a.getString(attr);
   3017                     if (handlerName != null) {
   3018                         setOnClickListener(new OnClickListener() {
   3019                             private Method mHandler;
   3020 
   3021                             public void onClick(View v) {
   3022                                 if (mHandler == null) {
   3023                                     try {
   3024                                         mHandler = getContext().getClass().getMethod(handlerName,
   3025                                                 View.class);
   3026                                     } catch (NoSuchMethodException e) {
   3027                                         int id = getId();
   3028                                         String idText = id == NO_ID ? "" : " with id '"
   3029                                                 + getContext().getResources().getResourceEntryName(
   3030                                                     id) + "'";
   3031                                         throw new IllegalStateException("Could not find a method " +
   3032                                                 handlerName + "(View) in the activity "
   3033                                                 + getContext().getClass() + " for onClick handler"
   3034                                                 + " on view " + View.this.getClass() + idText, e);
   3035                                     }
   3036                                 }
   3037 
   3038                                 try {
   3039                                     mHandler.invoke(getContext(), View.this);
   3040                                 } catch (IllegalAccessException e) {
   3041                                     throw new IllegalStateException("Could not execute non "
   3042                                             + "public method of the activity", e);
   3043                                 } catch (InvocationTargetException e) {
   3044                                     throw new IllegalStateException("Could not execute "
   3045                                             + "method of the activity", e);
   3046                                 }
   3047                             }
   3048                         });
   3049                     }
   3050                     break;
   3051                 case R.styleable.View_overScrollMode:
   3052                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
   3053                     break;
   3054                 case R.styleable.View_verticalScrollbarPosition:
   3055                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
   3056                     break;
   3057                 case R.styleable.View_layerType:
   3058                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
   3059                     break;
   3060                 case R.styleable.View_textDirection:
   3061                     mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
   3062                     break;
   3063             }
   3064         }
   3065 
   3066         a.recycle();
   3067 
   3068         setOverScrollMode(overScrollMode);
   3069 
   3070         if (background != null) {
   3071             setBackgroundDrawable(background);
   3072         }
   3073 
   3074         mUserPaddingRelative = (startPadding >= 0 || endPadding >= 0);
   3075 
   3076         // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
   3077         // layout direction). Those cached values will be used later during padding resolution.
   3078         mUserPaddingStart = startPadding;
   3079         mUserPaddingEnd = endPadding;
   3080 
   3081         if (padding >= 0) {
   3082             leftPadding = padding;
   3083             topPadding = padding;
   3084             rightPadding = padding;
   3085             bottomPadding = padding;
   3086         }
   3087 
   3088         // If the user specified the padding (either with android:padding or
   3089         // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
   3090         // use the default padding or the padding from the background drawable
   3091         // (stored at this point in mPadding*)
   3092         setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
   3093                 topPadding >= 0 ? topPadding : mPaddingTop,
   3094                 rightPadding >= 0 ? rightPadding : mPaddingRight,
   3095                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
   3096 
   3097         if (viewFlagMasks != 0) {
   3098             setFlags(viewFlagValues, viewFlagMasks);
   3099         }
   3100 
   3101         // Needs to be called after mViewFlags is set
   3102         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   3103             recomputePadding();
   3104         }
   3105 
   3106         if (x != 0 || y != 0) {
   3107             scrollTo(x, y);
   3108         }
   3109 
   3110         if (transformSet) {
   3111             setTranslationX(tx);
   3112             setTranslationY(ty);
   3113             setRotation(rotation);
   3114             setRotationX(rotationX);
   3115             setRotationY(rotationY);
   3116             setScaleX(sx);
   3117             setScaleY(sy);
   3118         }
   3119 
   3120         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
   3121             setScrollContainer(true);
   3122         }
   3123 
   3124         computeOpaqueFlags();
   3125     }
   3126 
   3127     /**
   3128      * Non-public constructor for use in testing
   3129      */
   3130     View() {
   3131         mResources = null;
   3132     }
   3133 
   3134     /**
   3135      * <p>
   3136      * Initializes the fading edges from a given set of styled attributes. This
   3137      * method should be called by subclasses that need fading edges and when an
   3138      * instance of these subclasses is created programmatically rather than
   3139      * being inflated from XML. This method is automatically called when the XML
   3140      * is inflated.
   3141      * </p>
   3142      *
   3143      * @param a the styled attributes set to initialize the fading edges from
   3144      */
   3145     protected void initializeFadingEdge(TypedArray a) {
   3146         initScrollCache();
   3147 
   3148         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
   3149                 R.styleable.View_fadingEdgeLength,
   3150                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
   3151     }
   3152 
   3153     /**
   3154      * Returns the size of the vertical faded edges used to indicate that more
   3155      * content in this view is visible.
   3156      *
   3157      * @return The size in pixels of the vertical faded edge or 0 if vertical
   3158      *         faded edges are not enabled for this view.
   3159      * @attr ref android.R.styleable#View_fadingEdgeLength
   3160      */
   3161     public int getVerticalFadingEdgeLength() {
   3162         if (isVerticalFadingEdgeEnabled()) {
   3163             ScrollabilityCache cache = mScrollCache;
   3164             if (cache != null) {
   3165                 return cache.fadingEdgeLength;
   3166             }
   3167         }
   3168         return 0;
   3169     }
   3170 
   3171     /**
   3172      * Set the size of the faded edge used to indicate that more content in this
   3173      * view is available.  Will not change whether the fading edge is enabled; use
   3174      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
   3175      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
   3176      * for the vertical or horizontal fading edges.
   3177      *
   3178      * @param length The size in pixels of the faded edge used to indicate that more
   3179      *        content in this view is visible.
   3180      */
   3181     public void setFadingEdgeLength(int length) {
   3182         initScrollCache();
   3183         mScrollCache.fadingEdgeLength = length;
   3184     }
   3185 
   3186     /**
   3187      * Returns the size of the horizontal faded edges used to indicate that more
   3188      * content in this view is visible.
   3189      *
   3190      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
   3191      *         faded edges are not enabled for this view.
   3192      * @attr ref android.R.styleable#View_fadingEdgeLength
   3193      */
   3194     public int getHorizontalFadingEdgeLength() {
   3195         if (isHorizontalFadingEdgeEnabled()) {
   3196             ScrollabilityCache cache = mScrollCache;
   3197             if (cache != null) {
   3198                 return cache.fadingEdgeLength;
   3199             }
   3200         }
   3201         return 0;
   3202     }
   3203 
   3204     /**
   3205      * Returns the width of the vertical scrollbar.
   3206      *
   3207      * @return The width in pixels of the vertical scrollbar or 0 if there
   3208      *         is no vertical scrollbar.
   3209      */
   3210     public int getVerticalScrollbarWidth() {
   3211         ScrollabilityCache cache = mScrollCache;
   3212         if (cache != null) {
   3213             ScrollBarDrawable scrollBar = cache.scrollBar;
   3214             if (scrollBar != null) {
   3215                 int size = scrollBar.getSize(true);
   3216                 if (size <= 0) {
   3217                     size = cache.scrollBarSize;
   3218                 }
   3219                 return size;
   3220             }
   3221             return 0;
   3222         }
   3223         return 0;
   3224     }
   3225 
   3226     /**
   3227      * Returns the height of the horizontal scrollbar.
   3228      *
   3229      * @return The height in pixels of the horizontal scrollbar or 0 if
   3230      *         there is no horizontal scrollbar.
   3231      */
   3232     protected int getHorizontalScrollbarHeight() {
   3233         ScrollabilityCache cache = mScrollCache;
   3234         if (cache != null) {
   3235             ScrollBarDrawable scrollBar = cache.scrollBar;
   3236             if (scrollBar != null) {
   3237                 int size = scrollBar.getSize(false);
   3238                 if (size <= 0) {
   3239                     size = cache.scrollBarSize;
   3240                 }
   3241                 return size;
   3242             }
   3243             return 0;
   3244         }
   3245         return 0;
   3246     }
   3247 
   3248     /**
   3249      * <p>
   3250      * Initializes the scrollbars from a given set of styled attributes. This
   3251      * method should be called by subclasses that need scrollbars and when an
   3252      * instance of these subclasses is created programmatically rather than
   3253      * being inflated from XML. This method is automatically called when the XML
   3254      * is inflated.
   3255      * </p>
   3256      *
   3257      * @param a the styled attributes set to initialize the scrollbars from
   3258      */
   3259     protected void initializeScrollbars(TypedArray a) {
   3260         initScrollCache();
   3261 
   3262         final ScrollabilityCache scrollabilityCache = mScrollCache;
   3263 
   3264         if (scrollabilityCache.scrollBar == null) {
   3265             scrollabilityCache.scrollBar = new ScrollBarDrawable();
   3266         }
   3267 
   3268         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
   3269 
   3270         if (!fadeScrollbars) {
   3271             scrollabilityCache.state = ScrollabilityCache.ON;
   3272         }
   3273         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   3274 
   3275 
   3276         scrollabilityCache.scrollBarFadeDuration = a.getInt(
   3277                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
   3278                         .getScrollBarFadeDuration());
   3279         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
   3280                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
   3281                 ViewConfiguration.getScrollDefaultDelay());
   3282 
   3283 
   3284         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
   3285                 com.android.internal.R.styleable.View_scrollbarSize,
   3286                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
   3287 
   3288         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
   3289         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
   3290 
   3291         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
   3292         if (thumb != null) {
   3293             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
   3294         }
   3295 
   3296         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
   3297                 false);
   3298         if (alwaysDraw) {
   3299             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
   3300         }
   3301 
   3302         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
   3303         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
   3304 
   3305         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
   3306         if (thumb != null) {
   3307             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
   3308         }
   3309 
   3310         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
   3311                 false);
   3312         if (alwaysDraw) {
   3313             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
   3314         }
   3315 
   3316         // Re-apply user/background padding so that scrollbar(s) get added
   3317         resolvePadding();
   3318     }
   3319 
   3320     /**
   3321      * <p>
   3322      * Initalizes the scrollability cache if necessary.
   3323      * </p>
   3324      */
   3325     private void initScrollCache() {
   3326         if (mScrollCache == null) {
   3327             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
   3328         }
   3329     }
   3330 
   3331     /**
   3332      * Set the position of the vertical scroll bar. Should be one of
   3333      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
   3334      * {@link #SCROLLBAR_POSITION_RIGHT}.
   3335      *
   3336      * @param position Where the vertical scroll bar should be positioned.
   3337      */
   3338     public void setVerticalScrollbarPosition(int position) {
   3339         if (mVerticalScrollbarPosition != position) {
   3340             mVerticalScrollbarPosition = position;
   3341             computeOpaqueFlags();
   3342             resolvePadding();
   3343         }
   3344     }
   3345 
   3346     /**
   3347      * @return The position where the vertical scroll bar will show, if applicable.
   3348      * @see #setVerticalScrollbarPosition(int)
   3349      */
   3350     public int getVerticalScrollbarPosition() {
   3351         return mVerticalScrollbarPosition;
   3352     }
   3353 
   3354     ListenerInfo getListenerInfo() {
   3355         if (mListenerInfo != null) {
   3356             return mListenerInfo;
   3357         }
   3358         mListenerInfo = new ListenerInfo();
   3359         return mListenerInfo;
   3360     }
   3361 
   3362     /**
   3363      * Register a callback to be invoked when focus of this view changed.
   3364      *
   3365      * @param l The callback that will run.
   3366      */
   3367     public void setOnFocusChangeListener(OnFocusChangeListener l) {
   3368         getListenerInfo().mOnFocusChangeListener = l;
   3369     }
   3370 
   3371     /**
   3372      * Add a listener that will be called when the bounds of the view change due to
   3373      * layout processing.
   3374      *
   3375      * @param listener The listener that will be called when layout bounds change.
   3376      */
   3377     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
   3378         ListenerInfo li = getListenerInfo();
   3379         if (li.mOnLayoutChangeListeners == null) {
   3380             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
   3381         }
   3382         if (!li.mOnLayoutChangeListeners.contains(listener)) {
   3383             li.mOnLayoutChangeListeners.add(listener);
   3384         }
   3385     }
   3386 
   3387     /**
   3388      * Remove a listener for layout changes.
   3389      *
   3390      * @param listener The listener for layout bounds change.
   3391      */
   3392     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
   3393         ListenerInfo li = mListenerInfo;
   3394         if (li == null || li.mOnLayoutChangeListeners == null) {
   3395             return;
   3396         }
   3397         li.mOnLayoutChangeListeners.remove(listener);
   3398     }
   3399 
   3400     /**
   3401      * Add a listener for attach state changes.
   3402      *
   3403      * This listener will be called whenever this view is attached or detached
   3404      * from a window. Remove the listener using
   3405      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
   3406      *
   3407      * @param listener Listener to attach
   3408      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
   3409      */
   3410     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   3411         ListenerInfo li = getListenerInfo();
   3412         if (li.mOnAttachStateChangeListeners == null) {
   3413             li.mOnAttachStateChangeListeners
   3414                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
   3415         }
   3416         li.mOnAttachStateChangeListeners.add(listener);
   3417     }
   3418 
   3419     /**
   3420      * Remove a listener for attach state changes. The listener will receive no further
   3421      * notification of window attach/detach events.
   3422      *
   3423      * @param listener Listener to remove
   3424      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
   3425      */
   3426     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   3427         ListenerInfo li = mListenerInfo;
   3428         if (li == null || li.mOnAttachStateChangeListeners == null) {
   3429             return;
   3430         }
   3431         li.mOnAttachStateChangeListeners.remove(listener);
   3432     }
   3433 
   3434     /**
   3435      * Returns the focus-change callback registered for this view.
   3436      *
   3437      * @return The callback, or null if one is not registered.
   3438      */
   3439     public OnFocusChangeListener getOnFocusChangeListener() {
   3440         ListenerInfo li = mListenerInfo;
   3441         return li != null ? li.mOnFocusChangeListener : null;
   3442     }
   3443 
   3444     /**
   3445      * Register a callback to be invoked when this view is clicked. If this view is not
   3446      * clickable, it becomes clickable.
   3447      *
   3448      * @param l The callback that will run
   3449      *
   3450      * @see #setClickable(boolean)
   3451      */
   3452     public void setOnClickListener(OnClickListener l) {
   3453         if (!isClickable()) {
   3454             setClickable(true);
   3455         }
   3456         getListenerInfo().mOnClickListener = l;
   3457     }
   3458 
   3459     /**
   3460      * Return whether this view has an attached OnClickListener.  Returns
   3461      * true if there is a listener, false if there is none.
   3462      */
   3463     public boolean hasOnClickListeners() {
   3464         ListenerInfo li = mListenerInfo;
   3465         return (li != null && li.mOnClickListener != null);
   3466     }
   3467 
   3468     /**
   3469      * Register a callback to be invoked when this view is clicked and held. If this view is not
   3470      * long clickable, it becomes long clickable.
   3471      *
   3472      * @param l The callback that will run
   3473      *
   3474      * @see #setLongClickable(boolean)
   3475      */
   3476     public void setOnLongClickListener(OnLongClickListener l) {
   3477         if (!isLongClickable()) {
   3478             setLongClickable(true);
   3479         }
   3480         getListenerInfo().mOnLongClickListener = l;
   3481     }
   3482 
   3483     /**
   3484      * Register a callback to be invoked when the context menu for this view is
   3485      * being built. If this view is not long clickable, it becomes long clickable.
   3486      *
   3487      * @param l The callback that will run
   3488      *
   3489      */
   3490     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
   3491         if (!isLongClickable()) {
   3492             setLongClickable(true);
   3493         }
   3494         getListenerInfo().mOnCreateContextMenuListener = l;
   3495     }
   3496 
   3497     /**
   3498      * Call this view's OnClickListener, if it is defined.  Performs all normal
   3499      * actions associated with clicking: reporting accessibility event, playing
   3500      * a sound, etc.
   3501      *
   3502      * @return True there was an assigned OnClickListener that was called, false
   3503      *         otherwise is returned.
   3504      */
   3505     public boolean performClick() {
   3506         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
   3507 
   3508         ListenerInfo li = mListenerInfo;
   3509         if (li != null && li.mOnClickListener != null) {
   3510             playSoundEffect(SoundEffectConstants.CLICK);
   3511             li.mOnClickListener.onClick(this);
   3512             return true;
   3513         }
   3514 
   3515         return false;
   3516     }
   3517 
   3518     /**
   3519      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
   3520      * this only calls the listener, and does not do any associated clicking
   3521      * actions like reporting an accessibility event.
   3522      *
   3523      * @return True there was an assigned OnClickListener that was called, false
   3524      *         otherwise is returned.
   3525      */
   3526     public boolean callOnClick() {
   3527         ListenerInfo li = mListenerInfo;
   3528         if (li != null && li.mOnClickListener != null) {
   3529             li.mOnClickListener.onClick(this);
   3530             return true;
   3531         }
   3532         return false;
   3533     }
   3534 
   3535     /**
   3536      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
   3537      * OnLongClickListener did not consume the event.
   3538      *
   3539      * @return True if one of the above receivers consumed the event, false otherwise.
   3540      */
   3541     public boolean performLongClick() {
   3542         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
   3543 
   3544         boolean handled = false;
   3545         ListenerInfo li = mListenerInfo;
   3546         if (li != null && li.mOnLongClickListener != null) {
   3547             handled = li.mOnLongClickListener.onLongClick(View.this);
   3548         }
   3549         if (!handled) {
   3550             handled = showContextMenu();
   3551         }
   3552         if (handled) {
   3553             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
   3554         }
   3555         return handled;
   3556     }
   3557 
   3558     /**
   3559      * Performs button-related actions during a touch down event.
   3560      *
   3561      * @param event The event.
   3562      * @return True if the down was consumed.
   3563      *
   3564      * @hide
   3565      */
   3566     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
   3567         if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
   3568             if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
   3569                 return true;
   3570             }
   3571         }
   3572         return false;
   3573     }
   3574 
   3575     /**
   3576      * Bring up the context menu for this view.
   3577      *
   3578      * @return Whether a context menu was displayed.
   3579      */
   3580     public boolean showContextMenu() {
   3581         return getParent().showContextMenuForChild(this);
   3582     }
   3583 
   3584     /**
   3585      * Bring up the context menu for this view, referring to the item under the specified point.
   3586      *
   3587      * @param x The referenced x coordinate.
   3588      * @param y The referenced y coordinate.
   3589      * @param metaState The keyboard modifiers that were pressed.
   3590      * @return Whether a context menu was displayed.
   3591      *
   3592      * @hide
   3593      */
   3594     public boolean showContextMenu(float x, float y, int metaState) {
   3595         return showContextMenu();
   3596     }
   3597 
   3598     /**
   3599      * Start an action mode.
   3600      *
   3601      * @param callback Callback that will control the lifecycle of the action mode
   3602      * @return The new action mode if it is started, null otherwise
   3603      *
   3604      * @see ActionMode
   3605      */
   3606     public ActionMode startActionMode(ActionMode.Callback callback) {
   3607         return getParent().startActionModeForChild(this, callback);
   3608     }
   3609 
   3610     /**
   3611      * Register a callback to be invoked when a key is pressed in this view.
   3612      * @param l the key listener to attach to this view
   3613      */
   3614     public void setOnKeyListener(OnKeyListener l) {
   3615         getListenerInfo().mOnKeyListener = l;
   3616     }
   3617 
   3618     /**
   3619      * Register a callback to be invoked when a touch event is sent to this view.
   3620      * @param l the touch listener to attach to this view
   3621      */
   3622     public void setOnTouchListener(OnTouchListener l) {
   3623         getListenerInfo().mOnTouchListener = l;
   3624     }
   3625 
   3626     /**
   3627      * Register a callback to be invoked when a generic motion event is sent to this view.
   3628      * @param l the generic motion listener to attach to this view
   3629      */
   3630     public void setOnGenericMotionListener(OnGenericMotionListener l) {
   3631         getListenerInfo().mOnGenericMotionListener = l;
   3632     }
   3633 
   3634     /**
   3635      * Register a callback to be invoked when a hover event is sent to this view.
   3636      * @param l the hover listener to attach to this view
   3637      */
   3638     public void setOnHoverListener(OnHoverListener l) {
   3639         getListenerInfo().mOnHoverListener = l;
   3640     }
   3641 
   3642     /**
   3643      * Register a drag event listener callback object for this View. The parameter is
   3644      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
   3645      * View, the system calls the
   3646      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
   3647      * @param l An implementation of {@link android.view.View.OnDragListener}.
   3648      */
   3649     public void setOnDragListener(OnDragListener l) {
   3650         getListenerInfo().mOnDragListener = l;
   3651     }
   3652 
   3653     /**
   3654      * Give this view focus. This will cause
   3655      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
   3656      *
   3657      * Note: this does not check whether this {@link View} should get focus, it just
   3658      * gives it focus no matter what.  It should only be called internally by framework
   3659      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
   3660      *
   3661      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
   3662      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
   3663      *        focus moved when requestFocus() is called. It may not always
   3664      *        apply, in which case use the default View.FOCUS_DOWN.
   3665      * @param previouslyFocusedRect The rectangle of the view that had focus
   3666      *        prior in this View's coordinate system.
   3667      */
   3668     void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
   3669         if (DBG) {
   3670             System.out.println(this + " requestFocus()");
   3671         }
   3672 
   3673         if ((mPrivateFlags & FOCUSED) == 0) {
   3674             mPrivateFlags |= FOCUSED;
   3675 
   3676             if (mParent != null) {
   3677                 mParent.requestChildFocus(this, this);
   3678             }
   3679 
   3680             onFocusChanged(true, direction, previouslyFocusedRect);
   3681             refreshDrawableState();
   3682         }
   3683     }
   3684 
   3685     /**
   3686      * Request that a rectangle of this view be visible on the screen,
   3687      * scrolling if necessary just enough.
   3688      *
   3689      * <p>A View should call this if it maintains some notion of which part
   3690      * of its content is interesting.  For example, a text editing view
   3691      * should call this when its cursor moves.
   3692      *
   3693      * @param rectangle The rectangle.
   3694      * @return Whether any parent scrolled.
   3695      */
   3696     public boolean requestRectangleOnScreen(Rect rectangle) {
   3697         return requestRectangleOnScreen(rectangle, false);
   3698     }
   3699 
   3700     /**
   3701      * Request that a rectangle of this view be visible on the screen,
   3702      * scrolling if necessary just enough.
   3703      *
   3704      * <p>A View should call this if it maintains some notion of which part
   3705      * of its content is interesting.  For example, a text editing view
   3706      * should call this when its cursor moves.
   3707      *
   3708      * <p>When <code>immediate</code> is set to true, scrolling will not be
   3709      * animated.
   3710      *
   3711      * @param rectangle The rectangle.
   3712      * @param immediate True to forbid animated scrolling, false otherwise
   3713      * @return Whether any parent scrolled.
   3714      */
   3715     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
   3716         View child = this;
   3717         ViewParent parent = mParent;
   3718         boolean scrolled = false;
   3719         while (parent != null) {
   3720             scrolled |= parent.requestChildRectangleOnScreen(child,
   3721                     rectangle, immediate);
   3722 
   3723             // offset rect so next call has the rectangle in the
   3724             // coordinate system of its direct child.
   3725             rectangle.offset(child.getLeft(), child.getTop());
   3726             rectangle.offset(-child.getScrollX(), -child.getScrollY());
   3727 
   3728             if (!(parent instanceof View)) {
   3729                 break;
   3730             }
   3731 
   3732             child = (View) parent;
   3733             parent = child.getParent();
   3734         }
   3735         return scrolled;
   3736     }
   3737 
   3738     /**
   3739      * Called when this view wants to give up focus. This will cause
   3740      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
   3741      */
   3742     public void clearFocus() {
   3743         if (DBG) {
   3744             System.out.println(this + " clearFocus()");
   3745         }
   3746 
   3747         if ((mPrivateFlags & FOCUSED) != 0) {
   3748             mPrivateFlags &= ~FOCUSED;
   3749 
   3750             if (mParent != null) {
   3751                 mParent.clearChildFocus(this);
   3752             }
   3753 
   3754             onFocusChanged(false, 0, null);
   3755             refreshDrawableState();
   3756         }
   3757     }
   3758 
   3759     /**
   3760      * Called to clear the focus of a view that is about to be removed.
   3761      * Doesn't call clearChildFocus, which prevents this view from taking
   3762      * focus again before it has been removed from the parent
   3763      */
   3764     void clearFocusForRemoval() {
   3765         if ((mPrivateFlags & FOCUSED) != 0) {
   3766             mPrivateFlags &= ~FOCUSED;
   3767 
   3768             onFocusChanged(false, 0, null);
   3769             refreshDrawableState();
   3770         }
   3771     }
   3772 
   3773     /**
   3774      * Called internally by the view system when a new view is getting focus.
   3775      * This is what clears the old focus.
   3776      */
   3777     void unFocus() {
   3778         if (DBG) {
   3779             System.out.println(this + " unFocus()");
   3780         }
   3781 
   3782         if ((mPrivateFlags & FOCUSED) != 0) {
   3783             mPrivateFlags &= ~FOCUSED;
   3784 
   3785             onFocusChanged(false, 0, null);
   3786             refreshDrawableState();
   3787         }
   3788     }
   3789 
   3790     /**
   3791      * Returns true if this view has focus iteself, or is the ancestor of the
   3792      * view that has focus.
   3793      *
   3794      * @return True if this view has or contains focus, false otherwise.
   3795      */
   3796     @ViewDebug.ExportedProperty(category = "focus")
   3797     public boolean hasFocus() {
   3798         return (mPrivateFlags & FOCUSED) != 0;
   3799     }
   3800 
   3801     /**
   3802      * Returns true if this view is focusable or if it contains a reachable View
   3803      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
   3804      * is a View whose parents do not block descendants focus.
   3805      *
   3806      * Only {@link #VISIBLE} views are considered focusable.
   3807      *
   3808      * @return True if the view is focusable or if the view contains a focusable
   3809      *         View, false otherwise.
   3810      *
   3811      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
   3812      */
   3813     public boolean hasFocusable() {
   3814         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
   3815     }
   3816 
   3817     /**
   3818      * Called by the view system when the focus state of this view changes.
   3819      * When the focus change event is caused by directional navigation, direction
   3820      * and previouslyFocusedRect provide insight into where the focus is coming from.
   3821      * When overriding, be sure to call up through to the super class so that
   3822      * the standard focus handling will occur.
   3823      *
   3824      * @param gainFocus True if the View has focus; false otherwise.
   3825      * @param direction The direction focus has moved when requestFocus()
   3826      *                  is called to give this view focus. Values are
   3827      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
   3828      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
   3829      *                  It may not always apply, in which case use the default.
   3830      * @param previouslyFocusedRect The rectangle, in this view's coordinate
   3831      *        system, of the previously focused view.  If applicable, this will be
   3832      *        passed in as finer grained information about where the focus is coming
   3833      *        from (in addition to direction).  Will be <code>null</code> otherwise.
   3834      */
   3835     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
   3836         if (gainFocus) {
   3837             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
   3838         }
   3839 
   3840         InputMethodManager imm = InputMethodManager.peekInstance();
   3841         if (!gainFocus) {
   3842             if (isPressed()) {
   3843                 setPressed(false);
   3844             }
   3845             if (imm != null && mAttachInfo != null
   3846                     && mAttachInfo.mHasWindowFocus) {
   3847                 imm.focusOut(this);
   3848             }
   3849             onFocusLost();
   3850         } else if (imm != null && mAttachInfo != null
   3851                 && mAttachInfo.mHasWindowFocus) {
   3852             imm.focusIn(this);
   3853         }
   3854 
   3855         invalidate(true);
   3856         ListenerInfo li = mListenerInfo;
   3857         if (li != null && li.mOnFocusChangeListener != null) {
   3858             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
   3859         }
   3860 
   3861         if (mAttachInfo != null) {
   3862             mAttachInfo.mKeyDispatchState.reset(this);
   3863         }
   3864     }
   3865 
   3866     /**
   3867      * Sends an accessibility event of the given type. If accessiiblity is
   3868      * not enabled this method has no effect. The default implementation calls
   3869      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
   3870      * to populate information about the event source (this View), then calls
   3871      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
   3872      * populate the text content of the event source including its descendants,
   3873      * and last calls
   3874      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
   3875      * on its parent to resuest sending of the event to interested parties.
   3876      * <p>
   3877      * If an {@link AccessibilityDelegate} has been specified via calling
   3878      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   3879      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
   3880      * responsible for handling this call.
   3881      * </p>
   3882      *
   3883      * @param eventType The type of the event to send, as defined by several types from
   3884      * {@link android.view.accessibility.AccessibilityEvent}, such as
   3885      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
   3886      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
   3887      *
   3888      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   3889      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   3890      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
   3891      * @see AccessibilityDelegate
   3892      */
   3893     public void sendAccessibilityEvent(int eventType) {
   3894         if (mAccessibilityDelegate != null) {
   3895             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
   3896         } else {
   3897             sendAccessibilityEventInternal(eventType);
   3898         }
   3899     }
   3900 
   3901     /**
   3902      * @see #sendAccessibilityEvent(int)
   3903      *
   3904      * Note: Called from the default {@link AccessibilityDelegate}.
   3905      */
   3906     void sendAccessibilityEventInternal(int eventType) {
   3907         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   3908             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
   3909         }
   3910     }
   3911 
   3912     /**
   3913      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
   3914      * takes as an argument an empty {@link AccessibilityEvent} and does not
   3915      * perform a check whether accessibility is enabled.
   3916      * <p>
   3917      * If an {@link AccessibilityDelegate} has been specified via calling
   3918      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   3919      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
   3920      * is responsible for handling this call.
   3921      * </p>
   3922      *
   3923      * @param event The event to send.
   3924      *
   3925      * @see #sendAccessibilityEvent(int)
   3926      */
   3927     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
   3928         if (mAccessibilityDelegate != null) {
   3929            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   3930         } else {
   3931             sendAccessibilityEventUncheckedInternal(event);
   3932         }
   3933     }
   3934 
   3935     /**
   3936      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
   3937      *
   3938      * Note: Called from the default {@link AccessibilityDelegate}.
   3939      */
   3940     void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
   3941         if (!isShown()) {
   3942             return;
   3943         }
   3944         onInitializeAccessibilityEvent(event);
   3945         // Only a subset of accessibility events populates text content.
   3946         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
   3947             dispatchPopulateAccessibilityEvent(event);
   3948         }
   3949         // In the beginning we called #isShown(), so we know that getParent() is not null.
   3950         getParent().requestSendAccessibilityEvent(this, event);
   3951     }
   3952 
   3953     /**
   3954      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
   3955      * to its children for adding their text content to the event. Note that the
   3956      * event text is populated in a separate dispatch path since we add to the
   3957      * event not only the text of the source but also the text of all its descendants.
   3958      * A typical implementation will call
   3959      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
   3960      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   3961      * on each child. Override this method if custom population of the event text
   3962      * content is required.
   3963      * <p>
   3964      * If an {@link AccessibilityDelegate} has been specified via calling
   3965      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   3966      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
   3967      * is responsible for handling this call.
   3968      * </p>
   3969      * <p>
   3970      * <em>Note:</em> Accessibility events of certain types are not dispatched for
   3971      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
   3972      * </p>
   3973      *
   3974      * @param event The event.
   3975      *
   3976      * @return True if the event population was completed.
   3977      */
   3978     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
   3979         if (mAccessibilityDelegate != null) {
   3980             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
   3981         } else {
   3982             return dispatchPopulateAccessibilityEventInternal(event);
   3983         }
   3984     }
   3985 
   3986     /**
   3987      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   3988      *
   3989      * Note: Called from the default {@link AccessibilityDelegate}.
   3990      */
   3991     boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   3992         onPopulateAccessibilityEvent(event);
   3993         return false;
   3994     }
   3995 
   3996     /**
   3997      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   3998      * giving a chance to this View to populate the accessibility event with its
   3999      * text content. While this method is free to modify event
   4000      * attributes other than text content, doing so should normally be performed in
   4001      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
   4002      * <p>
   4003      * Example: Adding formatted date string to an accessibility event in addition
   4004      *          to the text added by the super implementation:
   4005      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   4006      *     super.onPopulateAccessibilityEvent(event);
   4007      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
   4008      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
   4009      *         mCurrentDate.getTimeInMillis(), flags);
   4010      *     event.getText().add(selectedDateUtterance);
   4011      * }</pre>
   4012      * <p>
   4013      * If an {@link AccessibilityDelegate} has been specified via calling
   4014      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   4015      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
   4016      * is responsible for handling this call.
   4017      * </p>
   4018      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   4019      * information to the event, in case the default implementation has basic information to add.
   4020      * </p>
   4021      *
   4022      * @param event The accessibility event which to populate.
   4023      *
   4024      * @see #sendAccessibilityEvent(int)
   4025      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   4026      */
   4027     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   4028         if (mAccessibilityDelegate != null) {
   4029             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
   4030         } else {
   4031             onPopulateAccessibilityEventInternal(event);
   4032         }
   4033     }
   4034 
   4035     /**
   4036      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
   4037      *
   4038      * Note: Called from the default {@link AccessibilityDelegate}.
   4039      */
   4040     void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   4041 
   4042     }
   4043 
   4044     /**
   4045      * Initializes an {@link AccessibilityEvent} with information about
   4046      * this View which is the event source. In other words, the source of
   4047      * an accessibility event is the view whose state change triggered firing
   4048      * the event.
   4049      * <p>
   4050      * Example: Setting the password property of an event in addition
   4051      *          to properties set by the super implementation:
   4052      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   4053      *     super.onInitializeAccessibilityEvent(event);
   4054      *     event.setPassword(true);
   4055      * }</pre>
   4056      * <p>
   4057      * If an {@link AccessibilityDelegate} has been specified via calling
   4058      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   4059      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
   4060      * is responsible for handling this call.
   4061      * </p>
   4062      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   4063      * information to the event, in case the default implementation has basic information to add.
   4064      * </p>
   4065      * @param event The event to initialize.
   4066      *
   4067      * @see #sendAccessibilityEvent(int)
   4068      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   4069      */
   4070     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   4071         if (mAccessibilityDelegate != null) {
   4072             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
   4073         } else {
   4074             onInitializeAccessibilityEventInternal(event);
   4075         }
   4076     }
   4077 
   4078     /**
   4079      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   4080      *
   4081      * Note: Called from the default {@link AccessibilityDelegate}.
   4082      */
   4083     void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
   4084         event.setSource(this);
   4085         event.setClassName(getClass().getName());
   4086         event.setPackageName(getContext().getPackageName());
   4087         event.setEnabled(isEnabled());
   4088         event.setContentDescription(mContentDescription);
   4089 
   4090         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
   4091             ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
   4092             getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
   4093                     FOCUSABLES_ALL);
   4094             event.setItemCount(focusablesTempList.size());
   4095             event.setCurrentItemIndex(focusablesTempList.indexOf(this));
   4096             focusablesTempList.clear();
   4097         }
   4098     }
   4099 
   4100     /**
   4101      * Returns an {@link AccessibilityNodeInfo} representing this view from the
   4102      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   4103      * This method is responsible for obtaining an accessibility node info from a
   4104      * pool of reusable instances and calling
   4105      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
   4106      * initialize the former.
   4107      * <p>
   4108      * Note: The client is responsible for recycling the obtained instance by calling
   4109      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
   4110      * </p>
   4111      * @return A populated {@link AccessibilityNodeInfo}.
   4112      *
   4113      * @see AccessibilityNodeInfo
   4114      */
   4115     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
   4116         AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
   4117         onInitializeAccessibilityNodeInfo(info);
   4118         return info;
   4119     }
   4120 
   4121     /**
   4122      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
   4123      * The base implementation sets:
   4124      * <ul>
   4125      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
   4126      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
   4127      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
   4128      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
   4129      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
   4130      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
   4131      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
   4132      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
   4133      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
   4134      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
   4135      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
   4136      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
   4137      * </ul>
   4138      * <p>
   4139      * Subclasses should override this method, call the super implementation,
   4140      * and set additional attributes.
   4141      * </p>
   4142      * <p>
   4143      * If an {@link AccessibilityDelegate} has been specified via calling
   4144      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   4145      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
   4146      * is responsible for handling this call.
   4147      * </p>
   4148      *
   4149      * @param info The instance to initialize.
   4150      */
   4151     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
   4152         if (mAccessibilityDelegate != null) {
   4153             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
   4154         } else {
   4155             onInitializeAccessibilityNodeInfoInternal(info);
   4156         }
   4157     }
   4158 
   4159     /**
   4160      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   4161      *
   4162      * Note: Called from the default {@link AccessibilityDelegate}.
   4163      */
   4164     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
   4165         Rect bounds = mAttachInfo.mTmpInvalRect;
   4166         getDrawingRect(bounds);
   4167         info.setBoundsInParent(bounds);
   4168 
   4169         int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
   4170         getLocationOnScreen(locationOnScreen);
   4171         bounds.offsetTo(0, 0);
   4172         bounds.offset(locationOnScreen[0], locationOnScreen[1]);
   4173         info.setBoundsInScreen(bounds);
   4174 
   4175         if ((mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
   4176             ViewParent parent = getParent();
   4177             if (parent instanceof View) {
   4178                 View parentView = (View) parent;
   4179                 info.setParent(parentView);
   4180             }
   4181         }
   4182 
   4183         info.setPackageName(mContext.getPackageName());
   4184         info.setClassName(getClass().getName());
   4185         info.setContentDescription(getContentDescription());
   4186 
   4187         info.setEnabled(isEnabled());
   4188         info.setClickable(isClickable());
   4189         info.setFocusable(isFocusable());
   4190         info.setFocused(isFocused());
   4191         info.setSelected(isSelected());
   4192         info.setLongClickable(isLongClickable());
   4193 
   4194         // TODO: These make sense only if we are in an AdapterView but all
   4195         // views can be selected. Maybe from accessiiblity perspective
   4196         // we should report as selectable view in an AdapterView.
   4197         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
   4198         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
   4199 
   4200         if (isFocusable()) {
   4201             if (isFocused()) {
   4202                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
   4203             } else {
   4204                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
   4205             }
   4206         }
   4207     }
   4208 
   4209     /**
   4210      * Sets a delegate for implementing accessibility support via compositon as
   4211      * opposed to inheritance. The delegate's primary use is for implementing
   4212      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
   4213      *
   4214      * @param delegate The delegate instance.
   4215      *
   4216      * @see AccessibilityDelegate
   4217      */
   4218     public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
   4219         mAccessibilityDelegate = delegate;
   4220     }
   4221 
   4222     /**
   4223      * Gets the unique identifier of this view on the screen for accessibility purposes.
   4224      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
   4225      *
   4226      * @return The view accessibility id.
   4227      *
   4228      * @hide
   4229      */
   4230     public int getAccessibilityViewId() {
   4231         if (mAccessibilityViewId == NO_ID) {
   4232             mAccessibilityViewId = sNextAccessibilityViewId++;
   4233         }
   4234         return mAccessibilityViewId;
   4235     }
   4236 
   4237     /**
   4238      * Gets the unique identifier of the window in which this View reseides.
   4239      *
   4240      * @return The window accessibility id.
   4241      *
   4242      * @hide
   4243      */
   4244     public int getAccessibilityWindowId() {
   4245         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
   4246     }
   4247 
   4248     /**
   4249      * Gets the {@link View} description. It briefly describes the view and is
   4250      * primarily used for accessibility support. Set this property to enable
   4251      * better accessibility support for your application. This is especially
   4252      * true for views that do not have textual representation (For example,
   4253      * ImageButton).
   4254      *
   4255      * @return The content descriptiopn.
   4256      *
   4257      * @attr ref android.R.styleable#View_contentDescription
   4258      */
   4259     public CharSequence getContentDescription() {
   4260         return mContentDescription;
   4261     }
   4262 
   4263     /**
   4264      * Sets the {@link View} description. It briefly describes the view and is
   4265      * primarily used for accessibility support. Set this property to enable
   4266      * better accessibility support for your application. This is especially
   4267      * true for views that do not have textual representation (For example,
   4268      * ImageButton).
   4269      *
   4270      * @param contentDescription The content description.
   4271      *
   4272      * @attr ref android.R.styleable#View_contentDescription
   4273      */
   4274     @RemotableViewMethod
   4275     public void setContentDescription(CharSequence contentDescription) {
   4276         mContentDescription = contentDescription;
   4277     }
   4278 
   4279     /**
   4280      * Invoked whenever this view loses focus, either by losing window focus or by losing
   4281      * focus within its window. This method can be used to clear any state tied to the
   4282      * focus. For instance, if a button is held pressed with the trackball and the window
   4283      * loses focus, this method can be used to cancel the press.
   4284      *
   4285      * Subclasses of View overriding this method should always call super.onFocusLost().
   4286      *
   4287      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
   4288      * @see #onWindowFocusChanged(boolean)
   4289      *
   4290      * @hide pending API council approval
   4291      */
   4292     protected void onFocusLost() {
   4293         resetPressedState();
   4294     }
   4295 
   4296     private void resetPressedState() {
   4297         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   4298             return;
   4299         }
   4300 
   4301         if (isPressed()) {
   4302             setPressed(false);
   4303 
   4304             if (!mHasPerformedLongPress) {
   4305                 removeLongPressCallback();
   4306             }
   4307         }
   4308     }
   4309 
   4310     /**
   4311      * Returns true if this view has focus
   4312      *
   4313      * @return True if this view has focus, false otherwise.
   4314      */
   4315     @ViewDebug.ExportedProperty(category = "focus")
   4316     public boolean isFocused() {
   4317         return (mPrivateFlags & FOCUSED) != 0;
   4318     }
   4319 
   4320     /**
   4321      * Find the view in the hierarchy rooted at this view that currently has
   4322      * focus.
   4323      *
   4324      * @return The view that currently has focus, or null if no focused view can
   4325      *         be found.
   4326      */
   4327     public View findFocus() {
   4328         return (mPrivateFlags & FOCUSED) != 0 ? this : null;
   4329     }
   4330 
   4331     /**
   4332      * Change whether this view is one of the set of scrollable containers in
   4333      * its window.  This will be used to determine whether the window can
   4334      * resize or must pan when a soft input area is open -- scrollable
   4335      * containers allow the window to use resize mode since the container
   4336      * will appropriately shrink.
   4337      */
   4338     public void setScrollContainer(boolean isScrollContainer) {
   4339         if (isScrollContainer) {
   4340             if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
   4341                 mAttachInfo.mScrollContainers.add(this);
   4342                 mPrivateFlags |= SCROLL_CONTAINER_ADDED;
   4343             }
   4344             mPrivateFlags |= SCROLL_CONTAINER;
   4345         } else {
   4346             if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
   4347                 mAttachInfo.mScrollContainers.remove(this);
   4348             }
   4349             mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
   4350         }
   4351     }
   4352 
   4353     /**
   4354      * Returns the quality of the drawing cache.
   4355      *
   4356      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   4357      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   4358      *
   4359      * @see #setDrawingCacheQuality(int)
   4360      * @see #setDrawingCacheEnabled(boolean)
   4361      * @see #isDrawingCacheEnabled()
   4362      *
   4363      * @attr ref android.R.styleable#View_drawingCacheQuality
   4364      */
   4365     public int getDrawingCacheQuality() {
   4366         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
   4367     }
   4368 
   4369     /**
   4370      * Set the drawing cache quality of this view. This value is used only when the
   4371      * drawing cache is enabled
   4372      *
   4373      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   4374      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   4375      *
   4376      * @see #getDrawingCacheQuality()
   4377      * @see #setDrawingCacheEnabled(boolean)
   4378      * @see #isDrawingCacheEnabled()
   4379      *
   4380      * @attr ref android.R.styleable#View_drawingCacheQuality
   4381      */
   4382     public void setDrawingCacheQuality(int quality) {
   4383         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
   4384     }
   4385 
   4386     /**
   4387      * Returns whether the screen should remain on, corresponding to the current
   4388      * value of {@link #KEEP_SCREEN_ON}.
   4389      *
   4390      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
   4391      *
   4392      * @see #setKeepScreenOn(boolean)
   4393      *
   4394      * @attr ref android.R.styleable#View_keepScreenOn
   4395      */
   4396     public boolean getKeepScreenOn() {
   4397         return (mViewFlags & KEEP_SCREEN_ON) != 0;
   4398     }
   4399 
   4400     /**
   4401      * Controls whether the screen should remain on, modifying the
   4402      * value of {@link #KEEP_SCREEN_ON}.
   4403      *
   4404      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
   4405      *
   4406      * @see #getKeepScreenOn()
   4407      *
   4408      * @attr ref android.R.styleable#View_keepScreenOn
   4409      */
   4410     public void setKeepScreenOn(boolean keepScreenOn) {
   4411         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
   4412     }
   4413 
   4414     /**
   4415      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   4416      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   4417      *
   4418      * @attr ref android.R.styleable#View_nextFocusLeft
   4419      */
   4420     public int getNextFocusLeftId() {
   4421         return mNextFocusLeftId;
   4422     }
   4423 
   4424     /**
   4425      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   4426      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
   4427      * decide automatically.
   4428      *
   4429      * @attr ref android.R.styleable#View_nextFocusLeft
   4430      */
   4431     public void setNextFocusLeftId(int nextFocusLeftId) {
   4432         mNextFocusLeftId = nextFocusLeftId;
   4433     }
   4434 
   4435     /**
   4436      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   4437      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   4438      *
   4439      * @attr ref android.R.styleable#View_nextFocusRight
   4440      */
   4441     public int getNextFocusRightId() {
   4442         return mNextFocusRightId;
   4443     }
   4444 
   4445     /**
   4446      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   4447      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
   4448      * decide automatically.
   4449      *
   4450      * @attr ref android.R.styleable#View_nextFocusRight
   4451      */
   4452     public void setNextFocusRightId(int nextFocusRightId) {
   4453         mNextFocusRightId = nextFocusRightId;
   4454     }
   4455 
   4456     /**
   4457      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   4458      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   4459      *
   4460      * @attr ref android.R.styleable#View_nextFocusUp
   4461      */
   4462     public int getNextFocusUpId() {
   4463         return mNextFocusUpId;
   4464     }
   4465 
   4466     /**
   4467      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   4468      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
   4469      * decide automatically.
   4470      *
   4471      * @attr ref android.R.styleable#View_nextFocusUp
   4472      */
   4473     public void setNextFocusUpId(int nextFocusUpId) {
   4474         mNextFocusUpId = nextFocusUpId;
   4475     }
   4476 
   4477     /**
   4478      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   4479      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   4480      *
   4481      * @attr ref android.R.styleable#View_nextFocusDown
   4482      */
   4483     public int getNextFocusDownId() {
   4484         return mNextFocusDownId;
   4485     }
   4486 
   4487     /**
   4488      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   4489      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
   4490      * decide automatically.
   4491      *
   4492      * @attr ref android.R.styleable#View_nextFocusDown
   4493      */
   4494     public void setNextFocusDownId(int nextFocusDownId) {
   4495         mNextFocusDownId = nextFocusDownId;
   4496     }
   4497 
   4498     /**
   4499      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   4500      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   4501      *
   4502      * @attr ref android.R.styleable#View_nextFocusForward
   4503      */
   4504     public int getNextFocusForwardId() {
   4505         return mNextFocusForwardId;
   4506     }
   4507 
   4508     /**
   4509      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   4510      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
   4511      * decide automatically.
   4512      *
   4513      * @attr ref android.R.styleable#View_nextFocusForward
   4514      */
   4515     public void setNextFocusForwardId(int nextFocusForwardId) {
   4516         mNextFocusForwardId = nextFocusForwardId;
   4517     }
   4518 
   4519     /**
   4520      * Returns the visibility of this view and all of its ancestors
   4521      *
   4522      * @return True if this view and all of its ancestors are {@link #VISIBLE}
   4523      */
   4524     public boolean isShown() {
   4525         View current = this;
   4526         //noinspection ConstantConditions
   4527         do {
   4528             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   4529                 return false;
   4530             }
   4531             ViewParent parent = current.mParent;
   4532             if (parent == null) {
   4533                 return false; // We are not attached to the view root
   4534             }
   4535             if (!(parent instanceof View)) {
   4536                 return true;
   4537             }
   4538             current = (View) parent;
   4539         } while (current != null);
   4540 
   4541         return false;
   4542     }
   4543 
   4544     /**
   4545      * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
   4546      * is set
   4547      *
   4548      * @param insets Insets for system windows
   4549      *
   4550      * @return True if this view applied the insets, false otherwise
   4551      */
   4552     protected boolean fitSystemWindows(Rect insets) {
   4553         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
   4554             mPaddingLeft = insets.left;
   4555             mPaddingTop = insets.top;
   4556             mPaddingRight = insets.right;
   4557             mPaddingBottom = insets.bottom;
   4558             requestLayout();
   4559             return true;
   4560         }
   4561         return false;
   4562     }
   4563 
   4564     /**
   4565      * Set whether or not this view should account for system screen decorations
   4566      * such as the status bar and inset its content. This allows this view to be
   4567      * positioned in absolute screen coordinates and remain visible to the user.
   4568      *
   4569      * <p>This should only be used by top-level window decor views.
   4570      *
   4571      * @param fitSystemWindows true to inset content for system screen decorations, false for
   4572      *                         default behavior.
   4573      *
   4574      * @attr ref android.R.styleable#View_fitsSystemWindows
   4575      */
   4576     public void setFitsSystemWindows(boolean fitSystemWindows) {
   4577         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
   4578     }
   4579 
   4580     /**
   4581      * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
   4582      * will account for system screen decorations such as the status bar and inset its
   4583      * content. This allows the view to be positioned in absolute screen coordinates
   4584      * and remain visible to the user.
   4585      *
   4586      * @return true if this view will adjust its content bounds for system screen decorations.
   4587      *
   4588      * @attr ref android.R.styleable#View_fitsSystemWindows
   4589      */
   4590     public boolean fitsSystemWindows() {
   4591         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
   4592     }
   4593 
   4594     /**
   4595      * Returns the visibility status for this view.
   4596      *
   4597      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   4598      * @attr ref android.R.styleable#View_visibility
   4599      */
   4600     @ViewDebug.ExportedProperty(mapping = {
   4601         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
   4602         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
   4603         @ViewDebug.IntToString(from = GONE,      to = "GONE")
   4604     })
   4605     public int getVisibility() {
   4606         return mViewFlags & VISIBILITY_MASK;
   4607     }
   4608 
   4609     /**
   4610      * Set the enabled state of this view.
   4611      *
   4612      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   4613      * @attr ref android.R.styleable#View_visibility
   4614      */
   4615     @RemotableViewMethod
   4616     public void setVisibility(int visibility) {
   4617         setFlags(visibility, VISIBILITY_MASK);
   4618         if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
   4619     }
   4620 
   4621     /**
   4622      * Returns the enabled status for this view. The interpretation of the
   4623      * enabled state varies by subclass.
   4624      *
   4625      * @return True if this view is enabled, false otherwise.
   4626      */
   4627     @ViewDebug.ExportedProperty
   4628     public boolean isEnabled() {
   4629         return (mViewFlags & ENABLED_MASK) == ENABLED;
   4630     }
   4631 
   4632     /**
   4633      * Set the enabled state of this view. The interpretation of the enabled
   4634      * state varies by subclass.
   4635      *
   4636      * @param enabled True if this view is enabled, false otherwise.
   4637      */
   4638     @RemotableViewMethod
   4639     public void setEnabled(boolean enabled) {
   4640         if (enabled == isEnabled()) return;
   4641 
   4642         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
   4643 
   4644         /*
   4645          * The View most likely has to change its appearance, so refresh
   4646          * the drawable state.
   4647          */
   4648         refreshDrawableState();
   4649 
   4650         // Invalidate too, since the default behavior for views is to be
   4651         // be drawn at 50% alpha rather than to change the drawable.
   4652         invalidate(true);
   4653     }
   4654 
   4655     /**
   4656      * Set whether this view can receive the focus.
   4657      *
   4658      * Setting this to false will also ensure that this view is not focusable
   4659      * in touch mode.
   4660      *
   4661      * @param focusable If true, this view can receive the focus.
   4662      *
   4663      * @see #setFocusableInTouchMode(boolean)
   4664      * @attr ref android.R.styleable#View_focusable
   4665      */
   4666     public void setFocusable(boolean focusable) {
   4667         if (!focusable) {
   4668             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
   4669         }
   4670         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
   4671     }
   4672 
   4673     /**
   4674      * Set whether this view can receive focus while in touch mode.
   4675      *
   4676      * Setting this to true will also ensure that this view is focusable.
   4677      *
   4678      * @param focusableInTouchMode If true, this view can receive the focus while
   4679      *   in touch mode.
   4680      *
   4681      * @see #setFocusable(boolean)
   4682      * @attr ref android.R.styleable#View_focusableInTouchMode
   4683      */
   4684     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
   4685         // Focusable in touch mode should always be set before the focusable flag
   4686         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
   4687         // which, in touch mode, will not successfully request focus on this view
   4688         // because the focusable in touch mode flag is not set
   4689         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
   4690         if (focusableInTouchMode) {
   4691             setFlags(FOCUSABLE, FOCUSABLE_MASK);
   4692         }
   4693     }
   4694 
   4695     /**
   4696      * Set whether this view should have sound effects enabled for events such as
   4697      * clicking and touching.
   4698      *
   4699      * <p>You may wish to disable sound effects for a view if you already play sounds,
   4700      * for instance, a dial key that plays dtmf tones.
   4701      *
   4702      * @param soundEffectsEnabled whether sound effects are enabled for this view.
   4703      * @see #isSoundEffectsEnabled()
   4704      * @see #playSoundEffect(int)
   4705      * @attr ref android.R.styleable#View_soundEffectsEnabled
   4706      */
   4707     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
   4708         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
   4709     }
   4710 
   4711     /**
   4712      * @return whether this view should have sound effects enabled for events such as
   4713      *     clicking and touching.
   4714      *
   4715      * @see #setSoundEffectsEnabled(boolean)
   4716      * @see #playSoundEffect(int)
   4717      * @attr ref android.R.styleable#View_soundEffectsEnabled
   4718      */
   4719     @ViewDebug.ExportedProperty
   4720     public boolean isSoundEffectsEnabled() {
   4721         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
   4722     }
   4723 
   4724     /**
   4725      * Set whether this view should have haptic feedback for events such as
   4726      * long presses.
   4727      *
   4728      * <p>You may wish to disable haptic feedback if your view already controls
   4729      * its own haptic feedback.
   4730      *
   4731      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
   4732      * @see #isHapticFeedbackEnabled()
   4733      * @see #performHapticFeedback(int)
   4734      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   4735      */
   4736     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
   4737         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
   4738     }
   4739 
   4740     /**
   4741      * @return whether this view should have haptic feedback enabled for events
   4742      * long presses.
   4743      *
   4744      * @see #setHapticFeedbackEnabled(boolean)
   4745      * @see #performHapticFeedback(int)
   4746      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   4747      */
   4748     @ViewDebug.ExportedProperty
   4749     public boolean isHapticFeedbackEnabled() {
   4750         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
   4751     }
   4752 
   4753     /**
   4754      * Returns the layout direction for this view.
   4755      *
   4756      * @return One of {@link #LAYOUT_DIRECTION_LTR},
   4757      *   {@link #LAYOUT_DIRECTION_RTL},
   4758      *   {@link #LAYOUT_DIRECTION_INHERIT} or
   4759      *   {@link #LAYOUT_DIRECTION_LOCALE}.
   4760      * @attr ref android.R.styleable#View_layoutDirection
   4761      *
   4762      * @hide
   4763      */
   4764     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   4765         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
   4766         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
   4767         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
   4768         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
   4769     })
   4770     public int getLayoutDirection() {
   4771         return mViewFlags & LAYOUT_DIRECTION_MASK;
   4772     }
   4773 
   4774     /**
   4775      * Set the layout direction for this view. This will propagate a reset of layout direction
   4776      * resolution to the view's children and resolve layout direction for this view.
   4777      *
   4778      * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
   4779      *   {@link #LAYOUT_DIRECTION_RTL},
   4780      *   {@link #LAYOUT_DIRECTION_INHERIT} or
   4781      *   {@link #LAYOUT_DIRECTION_LOCALE}.
   4782      *
   4783      * @attr ref android.R.styleable#View_layoutDirection
   4784      *
   4785      * @hide
   4786      */
   4787     @RemotableViewMethod
   4788     public void setLayoutDirection(int layoutDirection) {
   4789         if (getLayoutDirection() != layoutDirection) {
   4790             resetResolvedLayoutDirection();
   4791             // Setting the flag will also request a layout.
   4792             setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
   4793         }
   4794     }
   4795 
   4796     /**
   4797      * Returns the resolved layout direction for this view.
   4798      *
   4799      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
   4800      * {@link #LAYOUT_DIRECTION_LTR} id the layout direction is not RTL.
   4801      *
   4802      * @hide
   4803      */
   4804     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   4805         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "RESOLVED_DIRECTION_LTR"),
   4806         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RESOLVED_DIRECTION_RTL")
   4807     })
   4808     public int getResolvedLayoutDirection() {
   4809         resolveLayoutDirectionIfNeeded();
   4810         return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
   4811                 LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
   4812     }
   4813 
   4814     /**
   4815      * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from
   4816      * layout attribute and/or the inherited value from the parent.</p>
   4817      *
   4818      * @return true if the layout is right-to-left.
   4819      *
   4820      * @hide
   4821      */
   4822     @ViewDebug.ExportedProperty(category = "layout")
   4823     public boolean isLayoutRtl() {
   4824         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
   4825     }
   4826 
   4827     /**
   4828      * If this view doesn't do any drawing on its own, set this flag to
   4829      * allow further optimizations. By default, this flag is not set on
   4830      * View, but could be set on some View subclasses such as ViewGroup.
   4831      *
   4832      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
   4833      * you should clear this flag.
   4834      *
   4835      * @param willNotDraw whether or not this View draw on its own
   4836      */
   4837     public void setWillNotDraw(boolean willNotDraw) {
   4838         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
   4839     }
   4840 
   4841     /**
   4842      * Returns whether or not this View draws on its own.
   4843      *
   4844      * @return true if this view has nothing to draw, false otherwise
   4845      */
   4846     @ViewDebug.ExportedProperty(category = "drawing")
   4847     public boolean willNotDraw() {
   4848         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
   4849     }
   4850 
   4851     /**
   4852      * When a View's drawing cache is enabled, drawing is redirected to an
   4853      * offscreen bitmap. Some views, like an ImageView, must be able to
   4854      * bypass this mechanism if they already draw a single bitmap, to avoid
   4855      * unnecessary usage of the memory.
   4856      *
   4857      * @param willNotCacheDrawing true if this view does not cache its
   4858      *        drawing, false otherwise
   4859      */
   4860     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
   4861         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
   4862     }
   4863 
   4864     /**
   4865      * Returns whether or not this View can cache its drawing or not.
   4866      *
   4867      * @return true if this view does not cache its drawing, false otherwise
   4868      */
   4869     @ViewDebug.ExportedProperty(category = "drawing")
   4870     public boolean willNotCacheDrawing() {
   4871         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
   4872     }
   4873 
   4874     /**
   4875      * Indicates whether this view reacts to click events or not.
   4876      *
   4877      * @return true if the view is clickable, false otherwise
   4878      *
   4879      * @see #setClickable(boolean)
   4880      * @attr ref android.R.styleable#View_clickable
   4881      */
   4882     @ViewDebug.ExportedProperty
   4883     public boolean isClickable() {
   4884         return (mViewFlags & CLICKABLE) == CLICKABLE;
   4885     }
   4886 
   4887     /**
   4888      * Enables or disables click events for this view. When a view
   4889      * is clickable it will change its state to "pressed" on every click.
   4890      * Subclasses should set the view clickable to visually react to
   4891      * user's clicks.
   4892      *
   4893      * @param clickable true to make the view clickable, false otherwise
   4894      *
   4895      * @see #isClickable()
   4896      * @attr ref android.R.styleable#View_clickable
   4897      */
   4898     public void setClickable(boolean clickable) {
   4899         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
   4900     }
   4901 
   4902     /**
   4903      * Indicates whether this view reacts to long click events or not.
   4904      *
   4905      * @return true if the view is long clickable, false otherwise
   4906      *
   4907      * @see #setLongClickable(boolean)
   4908      * @attr ref android.R.styleable#View_longClickable
   4909      */
   4910     public boolean isLongClickable() {
   4911         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   4912     }
   4913 
   4914     /**
   4915      * Enables or disables long click events for this view. When a view is long
   4916      * clickable it reacts to the user holding down the button for a longer
   4917      * duration than a tap. This event can either launch the listener or a
   4918      * context menu.
   4919      *
   4920      * @param longClickable true to make the view long clickable, false otherwise
   4921      * @see #isLongClickable()
   4922      * @attr ref android.R.styleable#View_longClickable
   4923      */
   4924     public void setLongClickable(boolean longClickable) {
   4925         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
   4926     }
   4927 
   4928     /**
   4929      * Sets the pressed state for this view.
   4930      *
   4931      * @see #isClickable()
   4932      * @see #setClickable(boolean)
   4933      *
   4934      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
   4935      *        the View's internal state from a previously set "pressed" state.
   4936      */
   4937     public void setPressed(boolean pressed) {
   4938         if (pressed) {
   4939             mPrivateFlags |= PRESSED;
   4940         } else {
   4941             mPrivateFlags &= ~PRESSED;
   4942         }
   4943         refreshDrawableState();
   4944         dispatchSetPressed(pressed);
   4945     }
   4946 
   4947     /**
   4948      * Dispatch setPressed to all of this View's children.
   4949      *
   4950      * @see #setPressed(boolean)
   4951      *
   4952      * @param pressed The new pressed state
   4953      */
   4954     protected void dispatchSetPressed(boolean pressed) {
   4955     }
   4956 
   4957     /**
   4958      * Indicates whether the view is currently in pressed state. Unless
   4959      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
   4960      * the pressed state.
   4961      *
   4962      * @see #setPressed(boolean)
   4963      * @see #isClickable()
   4964      * @see #setClickable(boolean)
   4965      *
   4966      * @return true if the view is currently pressed, false otherwise
   4967      */
   4968     public boolean isPressed() {
   4969         return (mPrivateFlags & PRESSED) == PRESSED;
   4970     }
   4971 
   4972     /**
   4973      * Indicates whether this view will save its state (that is,
   4974      * whether its {@link #onSaveInstanceState} method will be called).
   4975      *
   4976      * @return Returns true if the view state saving is enabled, else false.
   4977      *
   4978      * @see #setSaveEnabled(boolean)
   4979      * @attr ref android.R.styleable#View_saveEnabled
   4980      */
   4981     public boolean isSaveEnabled() {
   4982         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
   4983     }
   4984 
   4985     /**
   4986      * Controls whether the saving of this view's state is
   4987      * enabled (that is, whether its {@link #onSaveInstanceState} method
   4988      * will be called).  Note that even if freezing is enabled, the
   4989      * view still must have an id assigned to it (via {@link #setId(int)})
   4990      * for its state to be saved.  This flag can only disable the
   4991      * saving of this view; any child views may still have their state saved.
   4992      *
   4993      * @param enabled Set to false to <em>disable</em> state saving, or true
   4994      * (the default) to allow it.
   4995      *
   4996      * @see #isSaveEnabled()
   4997      * @see #setId(int)
   4998      * @see #onSaveInstanceState()
   4999      * @attr ref android.R.styleable#View_saveEnabled
   5000      */
   5001     public void setSaveEnabled(boolean enabled) {
   5002         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
   5003     }
   5004 
   5005     /**
   5006      * Gets whether the framework should discard touches when the view's
   5007      * window is obscured by another visible window.
   5008      * Refer to the {@link View} security documentation for more details.
   5009      *
   5010      * @return True if touch filtering is enabled.
   5011      *
   5012      * @see #setFilterTouchesWhenObscured(boolean)
   5013      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   5014      */
   5015     @ViewDebug.ExportedProperty
   5016     public boolean getFilterTouchesWhenObscured() {
   5017         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
   5018     }
   5019 
   5020     /**
   5021      * Sets whether the framework should discard touches when the view's
   5022      * window is obscured by another visible window.
   5023      * Refer to the {@link View} security documentation for more details.
   5024      *
   5025      * @param enabled True if touch filtering should be enabled.
   5026      *
   5027      * @see #getFilterTouchesWhenObscured
   5028      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   5029      */
   5030     public void setFilterTouchesWhenObscured(boolean enabled) {
   5031         setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
   5032                 FILTER_TOUCHES_WHEN_OBSCURED);
   5033     }
   5034 
   5035     /**
   5036      * Indicates whether the entire hierarchy under this view will save its
   5037      * state when a state saving traversal occurs from its parent.  The default
   5038      * is true; if false, these views will not be saved unless
   5039      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   5040      *
   5041      * @return Returns true if the view state saving from parent is enabled, else false.
   5042      *
   5043      * @see #setSaveFromParentEnabled(boolean)
   5044      */
   5045     public boolean isSaveFromParentEnabled() {
   5046         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
   5047     }
   5048 
   5049     /**
   5050      * Controls whether the entire hierarchy under this view will save its
   5051      * state when a state saving traversal occurs from its parent.  The default
   5052      * is true; if false, these views will not be saved unless
   5053      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   5054      *
   5055      * @param enabled Set to false to <em>disable</em> state saving, or true
   5056      * (the default) to allow it.
   5057      *
   5058      * @see #isSaveFromParentEnabled()
   5059      * @see #setId(int)
   5060      * @see #onSaveInstanceState()
   5061      */
   5062     public void setSaveFromParentEnabled(boolean enabled) {
   5063         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
   5064     }
   5065 
   5066 
   5067     /**
   5068      * Returns whether this View is able to take focus.
   5069      *
   5070      * @return True if this view can take focus, or false otherwise.
   5071      * @attr ref android.R.styleable#View_focusable
   5072      */
   5073     @ViewDebug.ExportedProperty(category = "focus")
   5074     public final boolean isFocusable() {
   5075         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
   5076     }
   5077 
   5078     /**
   5079      * When a view is focusable, it may not want to take focus when in touch mode.
   5080      * For example, a button would like focus when the user is navigating via a D-pad
   5081      * so that the user can click on it, but once the user starts touching the screen,
   5082      * the button shouldn't take focus
   5083      * @return Whether the view is focusable in touch mode.
   5084      * @attr ref android.R.styleable#View_focusableInTouchMode
   5085      */
   5086     @ViewDebug.ExportedProperty
   5087     public final boolean isFocusableInTouchMode() {
   5088         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
   5089     }
   5090 
   5091     /**
   5092      * Find the nearest view in the specified direction that can take focus.
   5093      * This does not actually give focus to that view.
   5094      *
   5095      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   5096      *
   5097      * @return The nearest focusable in the specified direction, or null if none
   5098      *         can be found.
   5099      */
   5100     public View focusSearch(int direction) {
   5101         if (mParent != null) {
   5102             return mParent.focusSearch(this, direction);
   5103         } else {
   5104             return null;
   5105         }
   5106     }
   5107 
   5108     /**
   5109      * This method is the last chance for the focused view and its ancestors to
   5110      * respond to an arrow key. This is called when the focused view did not
   5111      * consume the key internally, nor could the view system find a new view in
   5112      * the requested direction to give focus to.
   5113      *
   5114      * @param focused The currently focused view.
   5115      * @param direction The direction focus wants to move. One of FOCUS_UP,
   5116      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
   5117      * @return True if the this view consumed this unhandled move.
   5118      */
   5119     public boolean dispatchUnhandledMove(View focused, int direction) {
   5120         return false;
   5121     }
   5122 
   5123     /**
   5124      * If a user manually specified the next view id for a particular direction,
   5125      * use the root to look up the view.
   5126      * @param root The root view of the hierarchy containing this view.
   5127      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
   5128      * or FOCUS_BACKWARD.
   5129      * @return The user specified next view, or null if there is none.
   5130      */
   5131     View findUserSetNextFocus(View root, int direction) {
   5132         switch (direction) {
   5133             case FOCUS_LEFT:
   5134                 if (mNextFocusLeftId == View.NO_ID) return null;
   5135                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
   5136             case FOCUS_RIGHT:
   5137                 if (mNextFocusRightId == View.NO_ID) return null;
   5138                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
   5139             case FOCUS_UP:
   5140                 if (mNextFocusUpId == View.NO_ID) return null;
   5141                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
   5142             case FOCUS_DOWN:
   5143                 if (mNextFocusDownId == View.NO_ID) return null;
   5144                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
   5145             case FOCUS_FORWARD:
   5146                 if (mNextFocusForwardId == View.NO_ID) return null;
   5147                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
   5148             case FOCUS_BACKWARD: {
   5149                 final int id = mID;
   5150                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
   5151                     @Override
   5152                     public boolean apply(View t) {
   5153                         return t.mNextFocusForwardId == id;
   5154                     }
   5155                 });
   5156             }
   5157         }
   5158         return null;
   5159     }
   5160 
   5161     private View findViewInsideOutShouldExist(View root, final int childViewId) {
   5162         View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
   5163             @Override
   5164             public boolean apply(View t) {
   5165                 return t.mID == childViewId;
   5166             }
   5167         });
   5168 
   5169         if (result == null) {
   5170             Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
   5171                     + "by user for id " + childViewId);
   5172         }
   5173         return result;
   5174     }
   5175 
   5176     /**
   5177      * Find and return all focusable views that are descendants of this view,
   5178      * possibly including this view if it is focusable itself.
   5179      *
   5180      * @param direction The direction of the focus
   5181      * @return A list of focusable views
   5182      */
   5183     public ArrayList<View> getFocusables(int direction) {
   5184         ArrayList<View> result = new ArrayList<View>(24);
   5185         addFocusables(result, direction);
   5186         return result;
   5187     }
   5188 
   5189     /**
   5190      * Add any focusable views that are descendants of this view (possibly
   5191      * including this view if it is focusable itself) to views.  If we are in touch mode,
   5192      * only add views that are also focusable in touch mode.
   5193      *
   5194      * @param views Focusable views found so far
   5195      * @param direction The direction of the focus
   5196      */
   5197     public void addFocusables(ArrayList<View> views, int direction) {
   5198         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
   5199     }
   5200 
   5201     /**
   5202      * Adds any focusable views that are descendants of this view (possibly
   5203      * including this view if it is focusable itself) to views. This method
   5204      * adds all focusable views regardless if we are in touch mode or
   5205      * only views focusable in touch mode if we are in touch mode depending on
   5206      * the focusable mode paramater.
   5207      *
   5208      * @param views Focusable views found so far or null if all we are interested is
   5209      *        the number of focusables.
   5210      * @param direction The direction of the focus.
   5211      * @param focusableMode The type of focusables to be added.
   5212      *
   5213      * @see #FOCUSABLES_ALL
   5214      * @see #FOCUSABLES_TOUCH_MODE
   5215      */
   5216     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
   5217         if (!isFocusable()) {
   5218             return;
   5219         }
   5220 
   5221         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
   5222                 isInTouchMode() && !isFocusableInTouchMode()) {
   5223             return;
   5224         }
   5225 
   5226         if (views != null) {
   5227             views.add(this);
   5228         }
   5229     }
   5230 
   5231     /**
   5232      * Finds the Views that contain given text. The containment is case insensitive.
   5233      * The search is performed by either the text that the View renders or the content
   5234      * description that describes the view for accessibility purposes and the view does
   5235      * not render or both. Clients can specify how the search is to be performed via
   5236      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
   5237      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
   5238      *
   5239      * @param outViews The output list of matching Views.
   5240      * @param searched The text to match against.
   5241      *
   5242      * @see #FIND_VIEWS_WITH_TEXT
   5243      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
   5244      * @see #setContentDescription(CharSequence)
   5245      */
   5246     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
   5247         if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 && !TextUtils.isEmpty(searched)
   5248                 && !TextUtils.isEmpty(mContentDescription)) {
   5249             String searchedLowerCase = searched.toString().toLowerCase();
   5250             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
   5251             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
   5252                 outViews.add(this);
   5253             }
   5254         }
   5255     }
   5256 
   5257     /**
   5258      * Find and return all touchable views that are descendants of this view,
   5259      * possibly including this view if it is touchable itself.
   5260      *
   5261      * @return A list of touchable views
   5262      */
   5263     public ArrayList<View> getTouchables() {
   5264         ArrayList<View> result = new ArrayList<View>();
   5265         addTouchables(result);
   5266         return result;
   5267     }
   5268 
   5269     /**
   5270      * Add any touchable views that are descendants of this view (possibly
   5271      * including this view if it is touchable itself) to views.
   5272      *
   5273      * @param views Touchable views found so far
   5274      */
   5275     public void addTouchables(ArrayList<View> views) {
   5276         final int viewFlags = mViewFlags;
   5277 
   5278         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   5279                 && (viewFlags & ENABLED_MASK) == ENABLED) {
   5280             views.add(this);
   5281         }
   5282     }
   5283 
   5284     /**
   5285      * Call this to try to give focus to a specific view or to one of its
   5286      * descendants.
   5287      *
   5288      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   5289      * false), or if it is focusable and it is not focusable in touch mode
   5290      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   5291      *
   5292      * See also {@link #focusSearch(int)}, which is what you call to say that you
   5293      * have focus, and you want your parent to look for the next one.
   5294      *
   5295      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
   5296      * {@link #FOCUS_DOWN} and <code>null</code>.
   5297      *
   5298      * @return Whether this view or one of its descendants actually took focus.
   5299      */
   5300     public final boolean requestFocus() {
   5301         return requestFocus(View.FOCUS_DOWN);
   5302     }
   5303 
   5304 
   5305     /**
   5306      * Call this to try to give focus to a specific view or to one of its
   5307      * descendants and give it a hint about what direction focus is heading.
   5308      *
   5309      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   5310      * false), or if it is focusable and it is not focusable in touch mode
   5311      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   5312      *
   5313      * See also {@link #focusSearch(int)}, which is what you call to say that you
   5314      * have focus, and you want your parent to look for the next one.
   5315      *
   5316      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
   5317      * <code>null</code> set for the previously focused rectangle.
   5318      *
   5319      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   5320      * @return Whether this view or one of its descendants actually took focus.
   5321      */
   5322     public final boolean requestFocus(int direction) {
   5323         return requestFocus(direction, null);
   5324     }
   5325 
   5326     /**
   5327      * Call this to try to give focus to a specific view or to one of its descendants
   5328      * and give it hints about the direction and a specific rectangle that the focus
   5329      * is coming from.  The rectangle can help give larger views a finer grained hint
   5330      * about where focus is coming from, and therefore, where to show selection, or
   5331      * forward focus change internally.
   5332      *
   5333      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   5334      * false), or if it is focusable and it is not focusable in touch mode
   5335      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   5336      *
   5337      * A View will not take focus if it is not visible.
   5338      *
   5339      * A View will not take focus if one of its parents has
   5340      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
   5341      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
   5342      *
   5343      * See also {@link #focusSearch(int)}, which is what you call to say that you
   5344      * have focus, and you want your parent to look for the next one.
   5345      *
   5346      * You may wish to override this method if your custom {@link View} has an internal
   5347      * {@link View} that it wishes to forward the request to.
   5348      *
   5349      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   5350      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
   5351      *        to give a finer grained hint about where focus is coming from.  May be null
   5352      *        if there is no hint.
   5353      * @return Whether this view or one of its descendants actually took focus.
   5354      */
   5355     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
   5356         // need to be focusable
   5357         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
   5358                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   5359             return false;
   5360         }
   5361 
   5362         // need to be focusable in touch mode if in touch mode
   5363         if (isInTouchMode() &&
   5364             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
   5365                return false;
   5366         }
   5367 
   5368         // need to not have any parents blocking us
   5369         if (hasAncestorThatBlocksDescendantFocus()) {
   5370             return false;
   5371         }
   5372 
   5373         handleFocusGainInternal(direction, previouslyFocusedRect);
   5374         return true;
   5375     }
   5376 
   5377     /** Gets the ViewAncestor, or null if not attached. */
   5378     /*package*/ ViewRootImpl getViewRootImpl() {
   5379         View root = getRootView();
   5380         return root != null ? (ViewRootImpl)root.getParent() : null;
   5381     }
   5382 
   5383     /**
   5384      * Call this to try to give focus to a specific view or to one of its descendants. This is a
   5385      * special variant of {@link #requestFocus() } that will allow views that are not focuable in
   5386      * touch mode to request focus when they are touched.
   5387      *
   5388      * @return Whether this view or one of its descendants actually took focus.
   5389      *
   5390      * @see #isInTouchMode()
   5391      *
   5392      */
   5393     public final boolean requestFocusFromTouch() {
   5394         // Leave touch mode if we need to
   5395         if (isInTouchMode()) {
   5396             ViewRootImpl viewRoot = getViewRootImpl();
   5397             if (viewRoot != null) {
   5398                 viewRoot.ensureTouchMode(false);
   5399             }
   5400         }
   5401         return requestFocus(View.FOCUS_DOWN);
   5402     }
   5403 
   5404     /**
   5405      * @return Whether any ancestor of this view blocks descendant focus.
   5406      */
   5407     private boolean hasAncestorThatBlocksDescendantFocus() {
   5408         ViewParent ancestor = mParent;
   5409         while (ancestor instanceof ViewGroup) {
   5410             final ViewGroup vgAncestor = (ViewGroup) ancestor;
   5411             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
   5412                 return true;
   5413             } else {
   5414                 ancestor = vgAncestor.getParent();
   5415             }
   5416         }
   5417         return false;
   5418     }
   5419 
   5420     /**
   5421      * @hide
   5422      */
   5423     public void dispatchStartTemporaryDetach() {
   5424         onStartTemporaryDetach();
   5425     }
   5426 
   5427     /**
   5428      * This is called when a container is going to temporarily detach a child, with
   5429      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
   5430      * It will either be followed by {@link #onFinishTemporaryDetach()} or
   5431      * {@link #onDetachedFromWindow()} when the container is done.
   5432      */
   5433     public void onStartTemporaryDetach() {
   5434         removeUnsetPressCallback();
   5435         mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
   5436     }
   5437 
   5438     /**
   5439      * @hide
   5440      */
   5441     public void dispatchFinishTemporaryDetach() {
   5442         onFinishTemporaryDetach();
   5443     }
   5444 
   5445     /**
   5446      * Called after {@link #onStartTemporaryDetach} when the container is done
   5447      * changing the view.
   5448      */
   5449     public void onFinishTemporaryDetach() {
   5450     }
   5451 
   5452     /**
   5453      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
   5454      * for this view's window.  Returns null if the view is not currently attached
   5455      * to the window.  Normally you will not need to use this directly, but
   5456      * just use the standard high-level event callbacks like
   5457      * {@link #onKeyDown(int, KeyEvent)}.
   5458      */
   5459     public KeyEvent.DispatcherState getKeyDispatcherState() {
   5460         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
   5461     }
   5462 
   5463     /**
   5464      * Dispatch a key event before it is processed by any input method
   5465      * associated with the view hierarchy.  This can be used to intercept
   5466      * key events in special situations before the IME consumes them; a
   5467      * typical example would be handling the BACK key to update the application's
   5468      * UI instead of allowing the IME to see it and close itself.
   5469      *
   5470      * @param event The key event to be dispatched.
   5471      * @return True if the event was handled, false otherwise.
   5472      */
   5473     public boolean dispatchKeyEventPreIme(KeyEvent event) {
   5474         return onKeyPreIme(event.getKeyCode(), event);
   5475     }
   5476 
   5477     /**
   5478      * Dispatch a key event to the next view on the focus path. This path runs
   5479      * from the top of the view tree down to the currently focused view. If this
   5480      * view has focus, it will dispatch to itself. Otherwise it will dispatch
   5481      * the next node down the focus path. This method also fires any key
   5482      * listeners.
   5483      *
   5484      * @param event The key event to be dispatched.
   5485      * @return True if the event was handled, false otherwise.
   5486      */
   5487     public boolean dispatchKeyEvent(KeyEvent event) {
   5488         if (mInputEventConsistencyVerifier != null) {
   5489             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
   5490         }
   5491 
   5492         // Give any attached key listener a first crack at the event.
   5493         //noinspection SimplifiableIfStatement
   5494         ListenerInfo li = mListenerInfo;
   5495         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   5496                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
   5497             return true;
   5498         }
   5499 
   5500         if (event.dispatch(this, mAttachInfo != null
   5501                 ? mAttachInfo.mKeyDispatchState : null, this)) {
   5502             return true;
   5503         }
   5504 
   5505         if (mInputEventConsistencyVerifier != null) {
   5506             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   5507         }
   5508         return false;
   5509     }
   5510 
   5511     /**
   5512      * Dispatches a key shortcut event.
   5513      *
   5514      * @param event The key event to be dispatched.
   5515      * @return True if the event was handled by the view, false otherwise.
   5516      */
   5517     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   5518         return onKeyShortcut(event.getKeyCode(), event);
   5519     }
   5520 
   5521     /**
   5522      * Pass the touch screen motion event down to the target view, or this
   5523      * view if it is the target.
   5524      *
   5525      * @param event The motion event to be dispatched.
   5526      * @return True if the event was handled by the view, false otherwise.
   5527      */
   5528     public boolean dispatchTouchEvent(MotionEvent event) {
   5529         if (mInputEventConsistencyVerifier != null) {
   5530             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
   5531         }
   5532 
   5533         if (onFilterTouchEventForSecurity(event)) {
   5534             //noinspection SimplifiableIfStatement
   5535             ListenerInfo li = mListenerInfo;
   5536             if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   5537                     && li.mOnTouchListener.onTouch(this, event)) {
   5538                 return true;
   5539             }
   5540 
   5541             if (onTouchEvent(event)) {
   5542                 return true;
   5543             }
   5544         }
   5545 
   5546         if (mInputEventConsistencyVerifier != null) {
   5547             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   5548         }
   5549         return false;
   5550     }
   5551 
   5552     /**
   5553      * Filter the touch event to apply security policies.
   5554      *
   5555      * @param event The motion event to be filtered.
   5556      * @return True if the event should be dispatched, false if the event should be dropped.
   5557      *
   5558      * @see #getFilterTouchesWhenObscured
   5559      */
   5560     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
   5561         //noinspection RedundantIfStatement
   5562         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
   5563                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
   5564             // Window is obscured, drop this touch.
   5565             return false;
   5566         }
   5567         return true;
   5568     }
   5569 
   5570     /**
   5571      * Pass a trackball motion event down to the focused view.
   5572      *
   5573      * @param event The motion event to be dispatched.
   5574      * @return True if the event was handled by the view, false otherwise.
   5575      */
   5576     public boolean dispatchTrackballEvent(MotionEvent event) {
   5577         if (mInputEventConsistencyVerifier != null) {
   5578             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
   5579         }
   5580 
   5581         return onTrackballEvent(event);
   5582     }
   5583 
   5584     /**
   5585      * Dispatch a generic motion event.
   5586      * <p>
   5587      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   5588      * are delivered to the view under the pointer.  All other generic motion events are
   5589      * delivered to the focused view.  Hover events are handled specially and are delivered
   5590      * to {@link #onHoverEvent(MotionEvent)}.
   5591      * </p>
   5592      *
   5593      * @param event The motion event to be dispatched.
   5594      * @return True if the event was handled by the view, false otherwise.
   5595      */
   5596     public boolean dispatchGenericMotionEvent(MotionEvent event) {
   5597         if (mInputEventConsistencyVerifier != null) {
   5598             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
   5599         }
   5600 
   5601         final int source = event.getSource();
   5602         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   5603             final int action = event.getAction();
   5604             if (action == MotionEvent.ACTION_HOVER_ENTER
   5605                     || action == MotionEvent.ACTION_HOVER_MOVE
   5606                     || action == MotionEvent.ACTION_HOVER_EXIT) {
   5607                 if (dispatchHoverEvent(event)) {
   5608                     return true;
   5609                 }
   5610             } else if (dispatchGenericPointerEvent(event)) {
   5611                 return true;
   5612             }
   5613         } else if (dispatchGenericFocusedEvent(event)) {
   5614             return true;
   5615         }
   5616 
   5617         if (dispatchGenericMotionEventInternal(event)) {
   5618             return true;
   5619         }
   5620 
   5621         if (mInputEventConsistencyVerifier != null) {
   5622             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   5623         }
   5624         return false;
   5625     }
   5626 
   5627     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
   5628         //noinspection SimplifiableIfStatement
   5629         ListenerInfo li = mListenerInfo;
   5630         if (li != null && li.mOnGenericMotionListener != null
   5631                 && (mViewFlags & ENABLED_MASK) == ENABLED
   5632                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
   5633             return true;
   5634         }
   5635 
   5636         if (onGenericMotionEvent(event)) {
   5637             return true;
   5638         }
   5639 
   5640         if (mInputEventConsistencyVerifier != null) {
   5641             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   5642         }
   5643         return false;
   5644     }
   5645 
   5646     /**
   5647      * Dispatch a hover event.
   5648      * <p>
   5649      * Do not call this method directly.
   5650      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   5651      * </p>
   5652      *
   5653      * @param event The motion event to be dispatched.
   5654      * @return True if the event was handled by the view, false otherwise.
   5655      */
   5656     protected boolean dispatchHoverEvent(MotionEvent event) {
   5657         //noinspection SimplifiableIfStatement
   5658         ListenerInfo li = mListenerInfo;
   5659         if (li != null && li.mOnHoverListener != null
   5660                 && (mViewFlags & ENABLED_MASK) == ENABLED
   5661                 && li.mOnHoverListener.onHover(this, event)) {
   5662             return true;
   5663         }
   5664 
   5665         return onHoverEvent(event);
   5666     }
   5667 
   5668     /**
   5669      * Returns true if the view has a child to which it has recently sent
   5670      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
   5671      * it does not have a hovered child, then it must be the innermost hovered view.
   5672      * @hide
   5673      */
   5674     protected boolean hasHoveredChild() {
   5675         return false;
   5676     }
   5677 
   5678     /**
   5679      * Dispatch a generic motion event to the view under the first pointer.
   5680      * <p>
   5681      * Do not call this method directly.
   5682      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   5683      * </p>
   5684      *
   5685      * @param event The motion event to be dispatched.
   5686      * @return True if the event was handled by the view, false otherwise.
   5687      */
   5688     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
   5689         return false;
   5690     }
   5691 
   5692     /**
   5693      * Dispatch a generic motion event to the currently focused view.
   5694      * <p>
   5695      * Do not call this method directly.
   5696      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   5697      * </p>
   5698      *
   5699      * @param event The motion event to be dispatched.
   5700      * @return True if the event was handled by the view, false otherwise.
   5701      */
   5702     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
   5703         return false;
   5704     }
   5705 
   5706     /**
   5707      * Dispatch a pointer event.
   5708      * <p>
   5709      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
   5710      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
   5711      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
   5712      * and should not be expected to handle other pointing device features.
   5713      * </p>
   5714      *
   5715      * @param event The motion event to be dispatched.
   5716      * @return True if the event was handled by the view, false otherwise.
   5717      * @hide
   5718      */
   5719     public final boolean dispatchPointerEvent(MotionEvent event) {
   5720         if (event.isTouchEvent()) {
   5721             return dispatchTouchEvent(event);
   5722         } else {
   5723             return dispatchGenericMotionEvent(event);
   5724         }
   5725     }
   5726 
   5727     /**
   5728      * Called when the window containing this view gains or loses window focus.
   5729      * ViewGroups should override to route to their children.
   5730      *
   5731      * @param hasFocus True if the window containing this view now has focus,
   5732      *        false otherwise.
   5733      */
   5734     public void dispatchWindowFocusChanged(boolean hasFocus) {
   5735         onWindowFocusChanged(hasFocus);
   5736     }
   5737 
   5738     /**
   5739      * Called when the window containing this view gains or loses focus.  Note
   5740      * that this is separate from view focus: to receive key events, both
   5741      * your view and its window must have focus.  If a window is displayed
   5742      * on top of yours that takes input focus, then your own window will lose
   5743      * focus but the view focus will remain unchanged.
   5744      *
   5745      * @param hasWindowFocus True if the window containing this view now has
   5746      *        focus, false otherwise.
   5747      */
   5748     public void onWindowFocusChanged(boolean hasWindowFocus) {
   5749         InputMethodManager imm = InputMethodManager.peekInstance();
   5750         if (!hasWindowFocus) {
   5751             if (isPressed()) {
   5752                 setPressed(false);
   5753             }
   5754             if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
   5755                 imm.focusOut(this);
   5756             }
   5757             removeLongPressCallback();
   5758             removeTapCallback();
   5759             onFocusLost();
   5760         } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
   5761             imm.focusIn(this);
   5762         }
   5763         refreshDrawableState();
   5764     }
   5765 
   5766     /**
   5767      * Returns true if this view is in a window that currently has window focus.
   5768      * Note that this is not the same as the view itself having focus.
   5769      *
   5770      * @return True if this view is in a window that currently has window focus.
   5771      */
   5772     public boolean hasWindowFocus() {
   5773         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
   5774     }
   5775 
   5776     /**
   5777      * Dispatch a view visibility change down the view hierarchy.
   5778      * ViewGroups should override to route to their children.
   5779      * @param changedView The view whose visibility changed. Could be 'this' or
   5780      * an ancestor view.
   5781      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   5782      * {@link #INVISIBLE} or {@link #GONE}.
   5783      */
   5784     protected void dispatchVisibilityChanged(View changedView, int visibility) {
   5785         onVisibilityChanged(changedView, visibility);
   5786     }
   5787 
   5788     /**
   5789      * Called when the visibility of the view or an ancestor of the view is changed.
   5790      * @param changedView The view whose visibility changed. Could be 'this' or
   5791      * an ancestor view.
   5792      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   5793      * {@link #INVISIBLE} or {@link #GONE}.
   5794      */
   5795     protected void onVisibilityChanged(View changedView, int visibility) {
   5796         if (visibility == VISIBLE) {
   5797             if (mAttachInfo != null) {
   5798                 initialAwakenScrollBars();
   5799             } else {
   5800                 mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
   5801             }
   5802         }
   5803     }
   5804 
   5805     /**
   5806      * Dispatch a hint about whether this view is displayed. For instance, when
   5807      * a View moves out of the screen, it might receives a display hint indicating
   5808      * the view is not displayed. Applications should not <em>rely</em> on this hint
   5809      * as there is no guarantee that they will receive one.
   5810      *
   5811      * @param hint A hint about whether or not this view is displayed:
   5812      * {@link #VISIBLE} or {@link #INVISIBLE}.
   5813      */
   5814     public void dispatchDisplayHint(int hint) {
   5815         onDisplayHint(hint);
   5816     }
   5817 
   5818     /**
   5819      * Gives this view a hint about whether is displayed or not. For instance, when
   5820      * a View moves out of the screen, it might receives a display hint indicating
   5821      * the view is not displayed. Applications should not <em>rely</em> on this hint
   5822      * as there is no guarantee that they will receive one.
   5823      *
   5824      * @param hint A hint about whether or not this view is displayed:
   5825      * {@link #VISIBLE} or {@link #INVISIBLE}.
   5826      */
   5827     protected void onDisplayHint(int hint) {
   5828     }
   5829 
   5830     /**
   5831      * Dispatch a window visibility change down the view hierarchy.
   5832      * ViewGroups should override to route to their children.
   5833      *
   5834      * @param visibility The new visibility of the window.
   5835      *
   5836      * @see #onWindowVisibilityChanged(int)
   5837      */
   5838     public void dispatchWindowVisibilityChanged(int visibility) {
   5839         onWindowVisibilityChanged(visibility);
   5840     }
   5841 
   5842     /**
   5843      * Called when the window containing has change its visibility
   5844      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
   5845      * that this tells you whether or not your window is being made visible
   5846      * to the window manager; this does <em>not</em> tell you whether or not
   5847      * your window is obscured by other windows on the screen, even if it
   5848      * is itself visible.
   5849      *
   5850      * @param visibility The new visibility of the window.
   5851      */
   5852     protected void onWindowVisibilityChanged(int visibility) {
   5853         if (visibility == VISIBLE) {
   5854             initialAwakenScrollBars();
   5855         }
   5856     }
   5857 
   5858     /**
   5859      * Returns the current visibility of the window this view is attached to
   5860      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
   5861      *
   5862      * @return Returns the current visibility of the view's window.
   5863      */
   5864     public int getWindowVisibility() {
   5865         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
   5866     }
   5867 
   5868     /**
   5869      * Retrieve the overall visible display size in which the window this view is
   5870      * attached to has been positioned in.  This takes into account screen
   5871      * decorations above the window, for both cases where the window itself
   5872      * is being position inside of them or the window is being placed under
   5873      * then and covered insets are used for the window to position its content
   5874      * inside.  In effect, this tells you the available area where content can
   5875      * be placed and remain visible to users.
   5876      *
   5877      * <p>This function requires an IPC back to the window manager to retrieve
   5878      * the requested information, so should not be used in performance critical
   5879      * code like drawing.
   5880      *
   5881      * @param outRect Filled in with the visible display frame.  If the view
   5882      * is not attached to a window, this is simply the raw display size.
   5883      */
   5884     public void getWindowVisibleDisplayFrame(Rect outRect) {
   5885         if (mAttachInfo != null) {
   5886             try {
   5887                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   5888             } catch (RemoteException e) {
   5889                 return;
   5890             }
   5891             // XXX This is really broken, and probably all needs to be done
   5892             // in the window manager, and we need to know more about whether
   5893             // we want the area behind or in front of the IME.
   5894             final Rect insets = mAttachInfo.mVisibleInsets;
   5895             outRect.left += insets.left;
   5896             outRect.top += insets.top;
   5897             outRect.right -= insets.right;
   5898             outRect.bottom -= insets.bottom;
   5899             return;
   5900         }
   5901         Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
   5902         d.getRectSize(outRect);
   5903     }
   5904 
   5905     /**
   5906      * Dispatch a notification about a resource configuration change down
   5907      * the view hierarchy.
   5908      * ViewGroups should override to route to their children.
   5909      *
   5910      * @param newConfig The new resource configuration.
   5911      *
   5912      * @see #onConfigurationChanged(android.content.res.Configuration)
   5913      */
   5914     public void dispatchConfigurationChanged(Configuration newConfig) {
   5915         onConfigurationChanged(newConfig);
   5916     }
   5917 
   5918     /**
   5919      * Called when the current configuration of the resources being used
   5920      * by the application have changed.  You can use this to decide when
   5921      * to reload resources that can changed based on orientation and other
   5922      * configuration characterstics.  You only need to use this if you are
   5923      * not relying on the normal {@link android.app.Activity} mechanism of
   5924      * recreating the activity instance upon a configuration change.
   5925      *
   5926      * @param newConfig The new resource configuration.
   5927      */
   5928     protected void onConfigurationChanged(Configuration newConfig) {
   5929     }
   5930 
   5931     /**
   5932      * Private function to aggregate all per-view attributes in to the view
   5933      * root.
   5934      */
   5935     void dispatchCollectViewAttributes(int visibility) {
   5936         performCollectViewAttributes(visibility);
   5937     }
   5938 
   5939     void performCollectViewAttributes(int visibility) {
   5940         if ((visibility & VISIBILITY_MASK) == VISIBLE && mAttachInfo != null) {
   5941             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
   5942                 mAttachInfo.mKeepScreenOn = true;
   5943             }
   5944             mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility;
   5945             ListenerInfo li = mListenerInfo;
   5946             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   5947                 mAttachInfo.mHasSystemUiListeners = true;
   5948             }
   5949         }
   5950     }
   5951 
   5952     void needGlobalAttributesUpdate(boolean force) {
   5953         final AttachInfo ai = mAttachInfo;
   5954         if (ai != null) {
   5955             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
   5956                     || ai.mHasSystemUiListeners) {
   5957                 ai.mRecomputeGlobalAttributes = true;
   5958             }
   5959         }
   5960     }
   5961 
   5962     /**
   5963      * Returns whether the device is currently in touch mode.  Touch mode is entered
   5964      * once the user begins interacting with the device by touch, and affects various
   5965      * things like whether focus is always visible to the user.
   5966      *
   5967      * @return Whether the device is in touch mode.
   5968      */
   5969     @ViewDebug.ExportedProperty
   5970     public boolean isInTouchMode() {
   5971         if (mAttachInfo != null) {
   5972             return mAttachInfo.mInTouchMode;
   5973         } else {
   5974             return ViewRootImpl.isInTouchMode();
   5975         }
   5976     }
   5977 
   5978     /**
   5979      * Returns the context the view is running in, through which it can
   5980      * access the current theme, resources, etc.
   5981      *
   5982      * @return The view's Context.
   5983      */
   5984     @ViewDebug.CapturedViewProperty
   5985     public final Context getContext() {
   5986         return mContext;
   5987     }
   5988 
   5989     /**
   5990      * Handle a key event before it is processed by any input method
   5991      * associated with the view hierarchy.  This can be used to intercept
   5992      * key events in special situations before the IME consumes them; a
   5993      * typical example would be handling the BACK key to update the application's
   5994      * UI instead of allowing the IME to see it and close itself.
   5995      *
   5996      * @param keyCode The value in event.getKeyCode().
   5997      * @param event Description of the key event.
   5998      * @return If you handled the event, return true. If you want to allow the
   5999      *         event to be handled by the next receiver, return false.
   6000      */
   6001     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
   6002         return false;
   6003     }
   6004 
   6005     /**
   6006      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
   6007      * KeyEvent.Callback.onKeyDown()}: perform press of the view
   6008      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
   6009      * is released, if the view is enabled and clickable.
   6010      *
   6011      * @param keyCode A key code that represents the button pressed, from
   6012      *                {@link android.view.KeyEvent}.
   6013      * @param event   The KeyEvent object that defines the button action.
   6014      */
   6015     public boolean onKeyDown(int keyCode, KeyEvent event) {
   6016         boolean result = false;
   6017 
   6018         switch (keyCode) {
   6019             case KeyEvent.KEYCODE_DPAD_CENTER:
   6020             case KeyEvent.KEYCODE_ENTER: {
   6021                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   6022                     return true;
   6023                 }
   6024                 // Long clickable items don't necessarily have to be clickable
   6025                 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
   6026                         (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
   6027                         (event.getRepeatCount() == 0)) {
   6028                     setPressed(true);
   6029                     checkForLongClick(0);
   6030                     return true;
   6031                 }
   6032                 break;
   6033             }
   6034         }
   6035         return result;
   6036     }
   6037 
   6038     /**
   6039      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
   6040      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
   6041      * the event).
   6042      */
   6043     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
   6044         return false;
   6045     }
   6046 
   6047     /**
   6048      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
   6049      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
   6050      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
   6051      * {@link KeyEvent#KEYCODE_ENTER} is released.
   6052      *
   6053      * @param keyCode A key code that represents the button pressed, from
   6054      *                {@link android.view.KeyEvent}.
   6055      * @param event   The KeyEvent object that defines the button action.
   6056      */
   6057     public boolean onKeyUp(int keyCode, KeyEvent event) {
   6058         boolean result = false;
   6059 
   6060         switch (keyCode) {
   6061             case KeyEvent.KEYCODE_DPAD_CENTER:
   6062             case KeyEvent.KEYCODE_ENTER: {
   6063                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   6064                     return true;
   6065                 }
   6066                 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
   6067                     setPressed(false);
   6068 
   6069                     if (!mHasPerformedLongPress) {
   6070                         // This is a tap, so remove the longpress check
   6071                         removeLongPressCallback();
   6072 
   6073                         result = performClick();
   6074                     }
   6075                 }
   6076                 break;
   6077             }
   6078         }
   6079         return result;
   6080     }
   6081 
   6082     /**
   6083      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   6084      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
   6085      * the event).
   6086      *
   6087      * @param keyCode     A key code that represents the button pressed, from
   6088      *                    {@link android.view.KeyEvent}.
   6089      * @param repeatCount The number of times the action was made.
   6090      * @param event       The KeyEvent object that defines the button action.
   6091      */
   6092     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
   6093         return false;
   6094     }
   6095 
   6096     /**
   6097      * Called on the focused view when a key shortcut event is not handled.
   6098      * Override this method to implement local key shortcuts for the View.
   6099      * Key shortcuts can also be implemented by setting the
   6100      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
   6101      *
   6102      * @param keyCode The value in event.getKeyCode().
   6103      * @param event Description of the key event.
   6104      * @return If you handled the event, return true. If you want to allow the
   6105      *         event to be handled by the next receiver, return false.
   6106      */
   6107     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
   6108         return false;
   6109     }
   6110 
   6111     /**
   6112      * Check whether the called view is a text editor, in which case it
   6113      * would make sense to automatically display a soft input window for
   6114      * it.  Subclasses should override this if they implement
   6115      * {@link #onCreateInputConnection(EditorInfo)} to return true if
   6116      * a call on that method would return a non-null InputConnection, and
   6117      * they are really a first-class editor that the user would normally
   6118      * start typing on when the go into a window containing your view.
   6119      *
   6120      * <p>The default implementation always returns false.  This does
   6121      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
   6122      * will not be called or the user can not otherwise perform edits on your
   6123      * view; it is just a hint to the system that this is not the primary
   6124      * purpose of this view.
   6125      *
   6126      * @return Returns true if this view is a text editor, else false.
   6127      */
   6128     public boolean onCheckIsTextEditor() {
   6129         return false;
   6130     }
   6131 
   6132     /**
   6133      * Create a new InputConnection for an InputMethod to interact
   6134      * with the view.  The default implementation returns null, since it doesn't
   6135      * support input methods.  You can override this to implement such support.
   6136      * This is only needed for views that take focus and text input.
   6137      *
   6138      * <p>When implementing this, you probably also want to implement
   6139      * {@link #onCheckIsTextEditor()} to indicate you will return a
   6140      * non-null InputConnection.
   6141      *
   6142      * @param outAttrs Fill in with attribute information about the connection.
   6143      */
   6144     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   6145         return null;
   6146     }
   6147 
   6148     /**
   6149      * Called by the {@link android.view.inputmethod.InputMethodManager}
   6150      * when a view who is not the current
   6151      * input connection target is trying to make a call on the manager.  The
   6152      * default implementation returns false; you can override this to return
   6153      * true for certain views if you are performing InputConnection proxying
   6154      * to them.
   6155      * @param view The View that is making the InputMethodManager call.
   6156      * @return Return true to allow the call, false to reject.
   6157      */
   6158     public boolean checkInputConnectionProxy(View view) {
   6159         return false;
   6160     }
   6161 
   6162     /**
   6163      * Show the context menu for this view. It is not safe to hold on to the
   6164      * menu after returning from this method.
   6165      *
   6166      * You should normally not overload this method. Overload
   6167      * {@link #onCreateContextMenu(ContextMenu)} or define an
   6168      * {@link OnCreateContextMenuListener} to add items to the context menu.
   6169      *
   6170      * @param menu The context menu to populate
   6171      */
   6172     public void createContextMenu(ContextMenu menu) {
   6173         ContextMenuInfo menuInfo = getContextMenuInfo();
   6174 
   6175         // Sets the current menu info so all items added to menu will have
   6176         // my extra info set.
   6177         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
   6178 
   6179         onCreateContextMenu(menu);
   6180         ListenerInfo li = mListenerInfo;
   6181         if (li != null && li.mOnCreateContextMenuListener != null) {
   6182             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
   6183         }
   6184 
   6185         // Clear the extra information so subsequent items that aren't mine don't
   6186         // have my extra info.
   6187         ((MenuBuilder)menu).setCurrentMenuInfo(null);
   6188 
   6189         if (mParent != null) {
   6190             mParent.createContextMenu(menu);
   6191         }
   6192     }
   6193 
   6194     /**
   6195      * Views should implement this if they have extra information to associate
   6196      * with the context menu. The return result is supplied as a parameter to
   6197      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
   6198      * callback.
   6199      *
   6200      * @return Extra information about the item for which the context menu
   6201      *         should be shown. This information will vary across different
   6202      *         subclasses of View.
   6203      */
   6204     protected ContextMenuInfo getContextMenuInfo() {
   6205         return null;
   6206     }
   6207 
   6208     /**
   6209      * Views should implement this if the view itself is going to add items to
   6210      * the context menu.
   6211      *
   6212      * @param menu the context menu to populate
   6213      */
   6214     protected void onCreateContextMenu(ContextMenu menu) {
   6215     }
   6216 
   6217     /**
   6218      * Implement this method to handle trackball motion events.  The
   6219      * <em>relative</em> movement of the trackball since the last event
   6220      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
   6221      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
   6222      * that a movement of 1 corresponds to the user pressing one DPAD key (so
   6223      * they will often be fractional values, representing the more fine-grained
   6224      * movement information available from a trackball).
   6225      *
   6226      * @param event The motion event.
   6227      * @return True if the event was handled, false otherwise.
   6228      */
   6229     public boolean onTrackballEvent(MotionEvent event) {
   6230         return false;
   6231     }
   6232 
   6233     /**
   6234      * Implement this method to handle generic motion events.
   6235      * <p>
   6236      * Generic motion events describe joystick movements, mouse hovers, track pad
   6237      * touches, scroll wheel movements and other input events.  The
   6238      * {@link MotionEvent#getSource() source} of the motion event specifies
   6239      * the class of input that was received.  Implementations of this method
   6240      * must examine the bits in the source before processing the event.
   6241      * The following code example shows how this is done.
   6242      * </p><p>
   6243      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   6244      * are delivered to the view under the pointer.  All other generic motion events are
   6245      * delivered to the focused view.
   6246      * </p>
   6247      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
   6248      *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
   6249      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
   6250      *             // process the joystick movement...
   6251      *             return true;
   6252      *         }
   6253      *     }
   6254      *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
   6255      *         switch (event.getAction()) {
   6256      *             case MotionEvent.ACTION_HOVER_MOVE:
   6257      *                 // process the mouse hover movement...
   6258      *                 return true;
   6259      *             case MotionEvent.ACTION_SCROLL:
   6260      *                 // process the scroll wheel movement...
   6261      *                 return true;
   6262      *         }
   6263      *     }
   6264      *     return super.onGenericMotionEvent(event);
   6265      * }</pre>
   6266      *
   6267      * @param event The generic motion event being processed.
   6268      * @return True if the event was handled, false otherwise.
   6269      */
   6270     public boolean onGenericMotionEvent(MotionEvent event) {
   6271         return false;
   6272     }
   6273 
   6274     /**
   6275      * Implement this method to handle hover events.
   6276      * <p>
   6277      * This method is called whenever a pointer is hovering into, over, or out of the
   6278      * bounds of a view and the view is not currently being touched.
   6279      * Hover events are represented as pointer events with action
   6280      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
   6281      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
   6282      * </p>
   6283      * <ul>
   6284      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
   6285      * when the pointer enters the bounds of the view.</li>
   6286      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
   6287      * when the pointer has already entered the bounds of the view and has moved.</li>
   6288      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
   6289      * when the pointer has exited the bounds of the view or when the pointer is
   6290      * about to go down due to a button click, tap, or similar user action that
   6291      * causes the view to be touched.</li>
   6292      * </ul>
   6293      * <p>
   6294      * The view should implement this method to return true to indicate that it is
   6295      * handling the hover event, such as by changing its drawable state.
   6296      * </p><p>
   6297      * The default implementation calls {@link #setHovered} to update the hovered state
   6298      * of the view when a hover enter or hover exit event is received, if the view
   6299      * is enabled and is clickable.  The default implementation also sends hover
   6300      * accessibility events.
   6301      * </p>
   6302      *
   6303      * @param event The motion event that describes the hover.
   6304      * @return True if the view handled the hover event.
   6305      *
   6306      * @see #isHovered
   6307      * @see #setHovered
   6308      * @see #onHoverChanged
   6309      */
   6310     public boolean onHoverEvent(MotionEvent event) {
   6311         // The root view may receive hover (or touch) events that are outside the bounds of
   6312         // the window.  This code ensures that we only send accessibility events for
   6313         // hovers that are actually within the bounds of the root view.
   6314         final int action = event.getAction();
   6315         if (!mSendingHoverAccessibilityEvents) {
   6316             if ((action == MotionEvent.ACTION_HOVER_ENTER
   6317                     || action == MotionEvent.ACTION_HOVER_MOVE)
   6318                     && !hasHoveredChild()
   6319                     && pointInView(event.getX(), event.getY())) {
   6320                 mSendingHoverAccessibilityEvents = true;
   6321                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
   6322             }
   6323         } else {
   6324             if (action == MotionEvent.ACTION_HOVER_EXIT
   6325                     || (action == MotionEvent.ACTION_HOVER_MOVE
   6326                             && !pointInView(event.getX(), event.getY()))) {
   6327                 mSendingHoverAccessibilityEvents = false;
   6328                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
   6329             }
   6330         }
   6331 
   6332         if (isHoverable()) {
   6333             switch (action) {
   6334                 case MotionEvent.ACTION_HOVER_ENTER:
   6335                     setHovered(true);
   6336                     break;
   6337                 case MotionEvent.ACTION_HOVER_EXIT:
   6338                     setHovered(false);
   6339                     break;
   6340             }
   6341 
   6342             // Dispatch the event to onGenericMotionEvent before returning true.
   6343             // This is to provide compatibility with existing applications that
   6344             // handled HOVER_MOVE events in onGenericMotionEvent and that would
   6345             // break because of the new default handling for hoverable views
   6346             // in onHoverEvent.
   6347             // Note that onGenericMotionEvent will be called by default when
   6348             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
   6349             dispatchGenericMotionEventInternal(event);
   6350             return true;
   6351         }
   6352         return false;
   6353     }
   6354 
   6355     /**
   6356      * Returns true if the view should handle {@link #onHoverEvent}
   6357      * by calling {@link #setHovered} to change its hovered state.
   6358      *
   6359      * @return True if the view is hoverable.
   6360      */
   6361     private boolean isHoverable() {
   6362         final int viewFlags = mViewFlags;
   6363         //noinspection SimplifiableIfStatement
   6364         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   6365             return false;
   6366         }
   6367 
   6368         return (viewFlags & CLICKABLE) == CLICKABLE
   6369                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   6370     }
   6371 
   6372     /**
   6373      * Returns true if the view is currently hovered.
   6374      *
   6375      * @return True if the view is currently hovered.
   6376      *
   6377      * @see #setHovered
   6378      * @see #onHoverChanged
   6379      */
   6380     @ViewDebug.ExportedProperty
   6381     public boolean isHovered() {
   6382         return (mPrivateFlags & HOVERED) != 0;
   6383     }
   6384 
   6385     /**
   6386      * Sets whether the view is currently hovered.
   6387      * <p>
   6388      * Calling this method also changes the drawable state of the view.  This
   6389      * enables the view to react to hover by using different drawable resources
   6390      * to change its appearance.
   6391      * </p><p>
   6392      * The {@link #onHoverChanged} method is called when the hovered state changes.
   6393      * </p>
   6394      *
   6395      * @param hovered True if the view is hovered.
   6396      *
   6397      * @see #isHovered
   6398      * @see #onHoverChanged
   6399      */
   6400     public void setHovered(boolean hovered) {
   6401         if (hovered) {
   6402             if ((mPrivateFlags & HOVERED) == 0) {
   6403                 mPrivateFlags |= HOVERED;
   6404                 refreshDrawableState();
   6405                 onHoverChanged(true);
   6406             }
   6407         } else {
   6408             if ((mPrivateFlags & HOVERED) != 0) {
   6409                 mPrivateFlags &= ~HOVERED;
   6410                 refreshDrawableState();
   6411                 onHoverChanged(false);
   6412             }
   6413         }
   6414     }
   6415 
   6416     /**
   6417      * Implement this method to handle hover state changes.
   6418      * <p>
   6419      * This method is called whenever the hover state changes as a result of a
   6420      * call to {@link #setHovered}.
   6421      * </p>
   6422      *
   6423      * @param hovered The current hover state, as returned by {@link #isHovered}.
   6424      *
   6425      * @see #isHovered
   6426      * @see #setHovered
   6427      */
   6428     public void onHoverChanged(boolean hovered) {
   6429     }
   6430 
   6431     /**
   6432      * Implement this method to handle touch screen motion events.
   6433      *
   6434      * @param event The motion event.
   6435      * @return True if the event was handled, false otherwise.
   6436      */
   6437     public boolean onTouchEvent(MotionEvent event) {
   6438         final int viewFlags = mViewFlags;
   6439 
   6440         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   6441             if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
   6442                 mPrivateFlags &= ~PRESSED;
   6443                 refreshDrawableState();
   6444             }
   6445             // A disabled view that is clickable still consumes the touch
   6446             // events, it just doesn't respond to them.
   6447             return (((viewFlags & CLICKABLE) == CLICKABLE ||
   6448                     (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
   6449         }
   6450 
   6451         if (mTouchDelegate != null) {
   6452             if (mTouchDelegate.onTouchEvent(event)) {
   6453                 return true;
   6454             }
   6455         }
   6456 
   6457         if (((viewFlags & CLICKABLE) == CLICKABLE ||
   6458                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
   6459             switch (event.getAction()) {
   6460                 case MotionEvent.ACTION_UP:
   6461                     boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
   6462                     if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
   6463                         // take focus if we don't have it already and we should in
   6464                         // touch mode.
   6465                         boolean focusTaken = false;
   6466                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
   6467                             focusTaken = requestFocus();
   6468                         }
   6469 
   6470                         if (prepressed) {
   6471                             // The button is being released before we actually
   6472                             // showed it as pressed.  Make it show the pressed
   6473                             // state now (before scheduling the click) to ensure
   6474                             // the user sees it.
   6475                             mPrivateFlags |= PRESSED;
   6476                             refreshDrawableState();
   6477                        }
   6478 
   6479                         if (!mHasPerformedLongPress) {
   6480                             // This is a tap, so remove the longpress check
   6481                             removeLongPressCallback();
   6482 
   6483                             // Only perform take click actions if we were in the pressed state
   6484                             if (!focusTaken) {
   6485                                 // Use a Runnable and post this rather than calling
   6486                                 // performClick directly. This lets other visual state
   6487                                 // of the view update before click actions start.
   6488                                 if (mPerformClick == null) {
   6489                                     mPerformClick = new PerformClick();
   6490                                 }
   6491                                 if (!post(mPerformClick)) {
   6492                                     performClick();
   6493                                 }
   6494                             }
   6495                         }
   6496 
   6497                         if (mUnsetPressedState == null) {
   6498                             mUnsetPressedState = new UnsetPressedState();
   6499                         }
   6500 
   6501                         if (prepressed) {
   6502                             postDelayed(mUnsetPressedState,
   6503                                     ViewConfiguration.getPressedStateDuration());
   6504                         } else if (!post(mUnsetPressedState)) {
   6505                             // If the post failed, unpress right now
   6506                             mUnsetPressedState.run();
   6507                         }
   6508                         removeTapCallback();
   6509                     }
   6510                     break;
   6511 
   6512                 case MotionEvent.ACTION_DOWN:
   6513                     mHasPerformedLongPress = false;
   6514 
   6515                     if (performButtonActionOnTouchDown(event)) {
   6516                         break;
   6517                     }
   6518 
   6519                     // Walk up the hierarchy to determine if we're inside a scrolling container.
   6520                     boolean isInScrollingContainer = isInScrollingContainer();
   6521 
   6522                     // For views inside a scrolling container, delay the pressed feedback for
   6523                     // a short period in case this is a scroll.
   6524                     if (isInScrollingContainer) {
   6525                         mPrivateFlags |= PREPRESSED;
   6526                         if (mPendingCheckForTap == null) {
   6527                             mPendingCheckForTap = new CheckForTap();
   6528                         }
   6529                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
   6530                     } else {
   6531                         // Not inside a scrolling container, so show the feedback right away
   6532                         mPrivateFlags |= PRESSED;
   6533                         refreshDrawableState();
   6534                         checkForLongClick(0);
   6535                     }
   6536                     break;
   6537 
   6538                 case MotionEvent.ACTION_CANCEL:
   6539                     mPrivateFlags &= ~PRESSED;
   6540                     refreshDrawableState();
   6541                     removeTapCallback();
   6542                     break;
   6543 
   6544                 case MotionEvent.ACTION_MOVE:
   6545                     final int x = (int) event.getX();
   6546                     final int y = (int) event.getY();
   6547 
   6548                     // Be lenient about moving outside of buttons
   6549                     if (!pointInView(x, y, mTouchSlop)) {
   6550                         // Outside button
   6551                         removeTapCallback();
   6552                         if ((mPrivateFlags & PRESSED) != 0) {
   6553                             // Remove any future long press/tap checks
   6554                             removeLongPressCallback();
   6555 
   6556                             // Need to switch from pressed to not pressed
   6557                             mPrivateFlags &= ~PRESSED;
   6558                             refreshDrawableState();
   6559                         }
   6560                     }
   6561                     break;
   6562             }
   6563             return true;
   6564         }
   6565 
   6566         return false;
   6567     }
   6568 
   6569     /**
   6570      * @hide
   6571      */
   6572     public boolean isInScrollingContainer() {
   6573         ViewParent p = getParent();
   6574         while (p != null && p instanceof ViewGroup) {
   6575             if (((ViewGroup) p).shouldDelayChildPressedState()) {
   6576                 return true;
   6577             }
   6578             p = p.getParent();
   6579         }
   6580         return false;
   6581     }
   6582 
   6583     /**
   6584      * Remove the longpress detection timer.
   6585      */
   6586     private void removeLongPressCallback() {
   6587         if (mPendingCheckForLongPress != null) {
   6588           removeCallbacks(mPendingCheckForLongPress);
   6589         }
   6590     }
   6591 
   6592     /**
   6593      * Remove the pending click action
   6594      */
   6595     private void removePerformClickCallback() {
   6596         if (mPerformClick != null) {
   6597             removeCallbacks(mPerformClick);
   6598         }
   6599     }
   6600 
   6601     /**
   6602      * Remove the prepress detection timer.
   6603      */
   6604     private void removeUnsetPressCallback() {
   6605         if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
   6606             setPressed(false);
   6607             removeCallbacks(mUnsetPressedState);
   6608         }
   6609     }
   6610 
   6611     /**
   6612      * Remove the tap detection timer.
   6613      */
   6614     private void removeTapCallback() {
   6615         if (mPendingCheckForTap != null) {
   6616             mPrivateFlags &= ~PREPRESSED;
   6617             removeCallbacks(mPendingCheckForTap);
   6618         }
   6619     }
   6620 
   6621     /**
   6622      * Cancels a pending long press.  Your subclass can use this if you
   6623      * want the context menu to come up if the user presses and holds
   6624      * at the same place, but you don't want it to come up if they press
   6625      * and then move around enough to cause scrolling.
   6626      */
   6627     public void cancelLongPress() {
   6628         removeLongPressCallback();
   6629 
   6630         /*
   6631          * The prepressed state handled by the tap callback is a display
   6632          * construct, but the tap callback will post a long press callback
   6633          * less its own timeout. Remove it here.
   6634          */
   6635         removeTapCallback();
   6636     }
   6637 
   6638     /**
   6639      * Remove the pending callback for sending a
   6640      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   6641      */
   6642     private void removeSendViewScrolledAccessibilityEventCallback() {
   6643         if (mSendViewScrolledAccessibilityEvent != null) {
   6644             removeCallbacks(mSendViewScrolledAccessibilityEvent);
   6645         }
   6646     }
   6647 
   6648     /**
   6649      * Sets the TouchDelegate for this View.
   6650      */
   6651     public void setTouchDelegate(TouchDelegate delegate) {
   6652         mTouchDelegate = delegate;
   6653     }
   6654 
   6655     /**
   6656      * Gets the TouchDelegate for this View.
   6657      */
   6658     public TouchDelegate getTouchDelegate() {
   6659         return mTouchDelegate;
   6660     }
   6661 
   6662     /**
   6663      * Set flags controlling behavior of this view.
   6664      *
   6665      * @param flags Constant indicating the value which should be set
   6666      * @param mask Constant indicating the bit range that should be changed
   6667      */
   6668     void setFlags(int flags, int mask) {
   6669         int old = mViewFlags;
   6670         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
   6671 
   6672         int changed = mViewFlags ^ old;
   6673         if (changed == 0) {
   6674             return;
   6675         }
   6676         int privateFlags = mPrivateFlags;
   6677 
   6678         /* Check if the FOCUSABLE bit has changed */
   6679         if (((changed & FOCUSABLE_MASK) != 0) &&
   6680                 ((privateFlags & HAS_BOUNDS) !=0)) {
   6681             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
   6682                     && ((privateFlags & FOCUSED) != 0)) {
   6683                 /* Give up focus if we are no longer focusable */
   6684                 clearFocus();
   6685             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
   6686                     && ((privateFlags & FOCUSED) == 0)) {
   6687                 /*
   6688                  * Tell the view system that we are now available to take focus
   6689                  * if no one else already has it.
   6690                  */
   6691                 if (mParent != null) mParent.focusableViewAvailable(this);
   6692             }
   6693         }
   6694 
   6695         if ((flags & VISIBILITY_MASK) == VISIBLE) {
   6696             if ((changed & VISIBILITY_MASK) != 0) {
   6697                 /*
   6698                  * If this view is becoming visible, invalidate it in case it changed while
   6699                  * it was not visible. Marking it drawn ensures that the invalidation will
   6700                  * go through.
   6701                  */
   6702                 mPrivateFlags |= DRAWN;
   6703                 invalidate(true);
   6704 
   6705                 needGlobalAttributesUpdate(true);
   6706 
   6707                 // a view becoming visible is worth notifying the parent
   6708                 // about in case nothing has focus.  even if this specific view
   6709                 // isn't focusable, it may contain something that is, so let
   6710                 // the root view try to give this focus if nothing else does.
   6711                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
   6712                     mParent.focusableViewAvailable(this);
   6713                 }
   6714             }
   6715         }
   6716 
   6717         /* Check if the GONE bit has changed */
   6718         if ((changed & GONE) != 0) {
   6719             needGlobalAttributesUpdate(false);
   6720             requestLayout();
   6721 
   6722             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
   6723                 if (hasFocus()) clearFocus();
   6724                 destroyDrawingCache();
   6725                 if (mParent instanceof View) {
   6726                     // GONE views noop invalidation, so invalidate the parent
   6727                     ((View) mParent).invalidate(true);
   6728                 }
   6729                 // Mark the view drawn to ensure that it gets invalidated properly the next
   6730                 // time it is visible and gets invalidated
   6731                 mPrivateFlags |= DRAWN;
   6732             }
   6733             if (mAttachInfo != null) {
   6734                 mAttachInfo.mViewVisibilityChanged = true;
   6735             }
   6736         }
   6737 
   6738         /* Check if the VISIBLE bit has changed */
   6739         if ((changed & INVISIBLE) != 0) {
   6740             needGlobalAttributesUpdate(false);
   6741             /*
   6742              * If this view is becoming invisible, set the DRAWN flag so that
   6743              * the next invalidate() will not be skipped.
   6744              */
   6745             mPrivateFlags |= DRAWN;
   6746 
   6747             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
   6748                 // root view becoming invisible shouldn't clear focus
   6749                 if (getRootView() != this) {
   6750                     clearFocus();
   6751                 }
   6752             }
   6753             if (mAttachInfo != null) {
   6754                 mAttachInfo.mViewVisibilityChanged = true;
   6755             }
   6756         }
   6757 
   6758         if ((changed & VISIBILITY_MASK) != 0) {
   6759             if (mParent instanceof ViewGroup) {
   6760                 ((ViewGroup) mParent).onChildVisibilityChanged(this, (flags & VISIBILITY_MASK));
   6761                 ((View) mParent).invalidate(true);
   6762             } else if (mParent != null) {
   6763                 mParent.invalidateChild(this, null);
   6764             }
   6765             dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
   6766         }
   6767 
   6768         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
   6769             destroyDrawingCache();
   6770         }
   6771 
   6772         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
   6773             destroyDrawingCache();
   6774             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   6775             invalidateParentCaches();
   6776         }
   6777 
   6778         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
   6779             destroyDrawingCache();
   6780             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   6781         }
   6782 
   6783         if ((changed & DRAW_MASK) != 0) {
   6784             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
   6785                 if (mBGDrawable != null) {
   6786                     mPrivateFlags &= ~SKIP_DRAW;
   6787                     mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
   6788                 } else {
   6789                     mPrivateFlags |= SKIP_DRAW;
   6790                 }
   6791             } else {
   6792                 mPrivateFlags &= ~SKIP_DRAW;
   6793             }
   6794             requestLayout();
   6795             invalidate(true);
   6796         }
   6797 
   6798         if ((changed & KEEP_SCREEN_ON) != 0) {
   6799             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   6800                 mParent.recomputeViewAttributes(this);
   6801             }
   6802         }
   6803 
   6804         if ((changed & LAYOUT_DIRECTION_MASK) != 0) {
   6805             requestLayout();
   6806         }
   6807     }
   6808 
   6809     /**
   6810      * Change the view's z order in the tree, so it's on top of other sibling
   6811      * views
   6812      */
   6813     public void bringToFront() {
   6814         if (mParent != null) {
   6815             mParent.bringChildToFront(this);
   6816         }
   6817     }
   6818 
   6819     /**
   6820      * This is called in response to an internal scroll in this view (i.e., the
   6821      * view scrolled its own contents). This is typically as a result of
   6822      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
   6823      * called.
   6824      *
   6825      * @param l Current horizontal scroll origin.
   6826      * @param t Current vertical scroll origin.
   6827      * @param oldl Previous horizontal scroll origin.
   6828      * @param oldt Previous vertical scroll origin.
   6829      */
   6830     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   6831         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   6832             postSendViewScrolledAccessibilityEventCallback();
   6833         }
   6834 
   6835         mBackgroundSizeChanged = true;
   6836 
   6837         final AttachInfo ai = mAttachInfo;
   6838         if (ai != null) {
   6839             ai.mViewScrollChanged = true;
   6840         }
   6841     }
   6842 
   6843     /**
   6844      * Interface definition for a callback to be invoked when the layout bounds of a view
   6845      * changes due to layout processing.
   6846      */
   6847     public interface OnLayoutChangeListener {
   6848         /**
   6849          * Called when the focus state of a view has changed.
   6850          *
   6851          * @param v The view whose state has changed.
   6852          * @param left The new value of the view's left property.
   6853          * @param top The new value of the view's top property.
   6854          * @param right The new value of the view's right property.
   6855          * @param bottom The new value of the view's bottom property.
   6856          * @param oldLeft The previous value of the view's left property.
   6857          * @param oldTop The previous value of the view's top property.
   6858          * @param oldRight The previous value of the view's right property.
   6859          * @param oldBottom The previous value of the view's bottom property.
   6860          */
   6861         void onLayoutChange(View v, int left, int top, int right, int bottom,
   6862             int oldLeft, int oldTop, int oldRight, int oldBottom);
   6863     }
   6864 
   6865     /**
   6866      * This is called during layout when the size of this view has changed. If
   6867      * you were just added to the view hierarchy, you're called with the old
   6868      * values of 0.
   6869      *
   6870      * @param w Current width of this view.
   6871      * @param h Current height of this view.
   6872      * @param oldw Old width of this view.
   6873      * @param oldh Old height of this view.
   6874      */
   6875     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   6876     }
   6877 
   6878     /**
   6879      * Called by draw to draw the child views. This may be overridden
   6880      * by derived classes to gain control just before its children are drawn
   6881      * (but after its own view has been drawn).
   6882      * @param canvas the canvas on which to draw the view
   6883      */
   6884     protected void dispatchDraw(Canvas canvas) {
   6885     }
   6886 
   6887     /**
   6888      * Gets the parent of this view. Note that the parent is a
   6889      * ViewParent and not necessarily a View.
   6890      *
   6891      * @return Parent of this view.
   6892      */
   6893     public final ViewParent getParent() {
   6894         return mParent;
   6895     }
   6896 
   6897     /**
   6898      * Set the horizontal scrolled position of your view. This will cause a call to
   6899      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   6900      * invalidated.
   6901      * @param value the x position to scroll to
   6902      */
   6903     public void setScrollX(int value) {
   6904         scrollTo(value, mScrollY);
   6905     }
   6906 
   6907     /**
   6908      * Set the vertical scrolled position of your view. This will cause a call to
   6909      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   6910      * invalidated.
   6911      * @param value the y position to scroll to
   6912      */
   6913     public void setScrollY(int value) {
   6914         scrollTo(mScrollX, value);
   6915     }
   6916 
   6917     /**
   6918      * Return the scrolled left position of this view. This is the left edge of
   6919      * the displayed part of your view. You do not need to draw any pixels
   6920      * farther left, since those are outside of the frame of your view on
   6921      * screen.
   6922      *
   6923      * @return The left edge of the displayed part of your view, in pixels.
   6924      */
   6925     public final int getScrollX() {
   6926         return mScrollX;
   6927     }
   6928 
   6929     /**
   6930      * Return the scrolled top position of this view. This is the top edge of
   6931      * the displayed part of your view. You do not need to draw any pixels above
   6932      * it, since those are outside of the frame of your view on screen.
   6933      *
   6934      * @return The top edge of the displayed part of your view, in pixels.
   6935      */
   6936     public final int getScrollY() {
   6937         return mScrollY;
   6938     }
   6939 
   6940     /**
   6941      * Return the width of the your view.
   6942      *
   6943      * @return The width of your view, in pixels.
   6944      */
   6945     @ViewDebug.ExportedProperty(category = "layout")
   6946     public final int getWidth() {
   6947         return mRight - mLeft;
   6948     }
   6949 
   6950     /**
   6951      * Return the height of your view.
   6952      *
   6953      * @return The height of your view, in pixels.
   6954      */
   6955     @ViewDebug.ExportedProperty(category = "layout")
   6956     public final int getHeight() {
   6957         return mBottom - mTop;
   6958     }
   6959 
   6960     /**
   6961      * Return the visible drawing bounds of your view. Fills in the output
   6962      * rectangle with the values from getScrollX(), getScrollY(),
   6963      * getWidth(), and getHeight().
   6964      *
   6965      * @param outRect The (scrolled) drawing bounds of the view.
   6966      */
   6967     public void getDrawingRect(Rect outRect) {
   6968         outRect.left = mScrollX;
   6969         outRect.top = mScrollY;
   6970         outRect.right = mScrollX + (mRight - mLeft);
   6971         outRect.bottom = mScrollY + (mBottom - mTop);
   6972     }
   6973 
   6974     /**
   6975      * Like {@link #getMeasuredWidthAndState()}, but only returns the
   6976      * raw width component (that is the result is masked by
   6977      * {@link #MEASURED_SIZE_MASK}).
   6978      *
   6979      * @return The raw measured width of this view.
   6980      */
   6981     public final int getMeasuredWidth() {
   6982         return mMeasuredWidth & MEASURED_SIZE_MASK;
   6983     }
   6984 
   6985     /**
   6986      * Return the full width measurement information for this view as computed
   6987      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   6988      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   6989      * This should be used during measurement and layout calculations only. Use
   6990      * {@link #getWidth()} to see how wide a view is after layout.
   6991      *
   6992      * @return The measured width of this view as a bit mask.
   6993      */
   6994     public final int getMeasuredWidthAndState() {
   6995         return mMeasuredWidth;
   6996     }
   6997 
   6998     /**
   6999      * Like {@link #getMeasuredHeightAndState()}, but only returns the
   7000      * raw width component (that is the result is masked by
   7001      * {@link #MEASURED_SIZE_MASK}).
   7002      *
   7003      * @return The raw measured height of this view.
   7004      */
   7005     public final int getMeasuredHeight() {
   7006         return mMeasuredHeight & MEASURED_SIZE_MASK;
   7007     }
   7008 
   7009     /**
   7010      * Return the full height measurement information for this view as computed
   7011      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   7012      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   7013      * This should be used during measurement and layout calculations only. Use
   7014      * {@link #getHeight()} to see how wide a view is after layout.
   7015      *
   7016      * @return The measured width of this view as a bit mask.
   7017      */
   7018     public final int getMeasuredHeightAndState() {
   7019         return mMeasuredHeight;
   7020     }
   7021 
   7022     /**
   7023      * Return only the state bits of {@link #getMeasuredWidthAndState()}
   7024      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
   7025      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
   7026      * and the height component is at the shifted bits
   7027      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
   7028      */
   7029     public final int getMeasuredState() {
   7030         return (mMeasuredWidth&MEASURED_STATE_MASK)
   7031                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
   7032                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
   7033     }
   7034 
   7035     /**
   7036      * The transform matrix of this view, which is calculated based on the current
   7037      * roation, scale, and pivot properties.
   7038      *
   7039      * @see #getRotation()
   7040      * @see #getScaleX()
   7041      * @see #getScaleY()
   7042      * @see #getPivotX()
   7043      * @see #getPivotY()
   7044      * @return The current transform matrix for the view
   7045      */
   7046     public Matrix getMatrix() {
   7047         if (mTransformationInfo != null) {
   7048             updateMatrix();
   7049             return mTransformationInfo.mMatrix;
   7050         }
   7051         return Matrix.IDENTITY_MATRIX;
   7052     }
   7053 
   7054     /**
   7055      * Utility function to determine if the value is far enough away from zero to be
   7056      * considered non-zero.
   7057      * @param value A floating point value to check for zero-ness
   7058      * @return whether the passed-in value is far enough away from zero to be considered non-zero
   7059      */
   7060     private static boolean nonzero(float value) {
   7061         return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
   7062     }
   7063 
   7064     /**
   7065      * Returns true if the transform matrix is the identity matrix.
   7066      * Recomputes the matrix if necessary.
   7067      *
   7068      * @return True if the transform matrix is the identity matrix, false otherwise.
   7069      */
   7070     final boolean hasIdentityMatrix() {
   7071         if (mTransformationInfo != null) {
   7072             updateMatrix();
   7073             return mTransformationInfo.mMatrixIsIdentity;
   7074         }
   7075         return true;
   7076     }
   7077 
   7078     void ensureTransformationInfo() {
   7079         if (mTransformationInfo == null) {
   7080             mTransformationInfo = new TransformationInfo();
   7081         }
   7082     }
   7083 
   7084     /**
   7085      * Recomputes the transform matrix if necessary.
   7086      */
   7087     private void updateMatrix() {
   7088         final TransformationInfo info = mTransformationInfo;
   7089         if (info == null) {
   7090             return;
   7091         }
   7092         if (info.mMatrixDirty) {
   7093             // transform-related properties have changed since the last time someone
   7094             // asked for the matrix; recalculate it with the current values
   7095 
   7096             // Figure out if we need to update the pivot point
   7097             if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
   7098                 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
   7099                     info.mPrevWidth = mRight - mLeft;
   7100                     info.mPrevHeight = mBottom - mTop;
   7101                     info.mPivotX = info.mPrevWidth / 2f;
   7102                     info.mPivotY = info.mPrevHeight / 2f;
   7103                 }
   7104             }
   7105             info.mMatrix.reset();
   7106             if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
   7107                 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
   7108                 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
   7109                 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
   7110             } else {
   7111                 if (info.mCamera == null) {
   7112                     info.mCamera = new Camera();
   7113                     info.matrix3D = new Matrix();
   7114                 }
   7115                 info.mCamera.save();
   7116                 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
   7117                 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
   7118                 info.mCamera.getMatrix(info.matrix3D);
   7119                 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
   7120                 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
   7121                         info.mPivotY + info.mTranslationY);
   7122                 info.mMatrix.postConcat(info.matrix3D);
   7123                 info.mCamera.restore();
   7124             }
   7125             info.mMatrixDirty = false;
   7126             info.mMatrixIsIdentity = info.mMatrix.isIdentity();
   7127             info.mInverseMatrixDirty = true;
   7128         }
   7129     }
   7130 
   7131     /**
   7132      * Utility method to retrieve the inverse of the current mMatrix property.
   7133      * We cache the matrix to avoid recalculating it when transform properties
   7134      * have not changed.
   7135      *
   7136      * @return The inverse of the current matrix of this view.
   7137      */
   7138     final Matrix getInverseMatrix() {
   7139         final TransformationInfo info = mTransformationInfo;
   7140         if (info != null) {
   7141             updateMatrix();
   7142             if (info.mInverseMatrixDirty) {
   7143                 if (info.mInverseMatrix == null) {
   7144                     info.mInverseMatrix = new Matrix();
   7145                 }
   7146                 info.mMatrix.invert(info.mInverseMatrix);
   7147                 info.mInverseMatrixDirty = false;
   7148             }
   7149             return info.mInverseMatrix;
   7150         }
   7151         return Matrix.IDENTITY_MATRIX;
   7152     }
   7153 
   7154     /**
   7155      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
   7156      * views are drawn) from the camera to this view. The camera's distance
   7157      * affects 3D transformations, for instance rotations around the X and Y
   7158      * axis. If the rotationX or rotationY properties are changed and this view is
   7159      * large (more than half the size of the screen), it is recommended to always
   7160      * use a camera distance that's greater than the height (X axis rotation) or
   7161      * the width (Y axis rotation) of this view.</p>
   7162      *
   7163      * <p>The distance of the camera from the view plane can have an affect on the
   7164      * perspective distortion of the view when it is rotated around the x or y axis.
   7165      * For example, a large distance will result in a large viewing angle, and there
   7166      * will not be much perspective distortion of the view as it rotates. A short
   7167      * distance may cause much more perspective distortion upon rotation, and can
   7168      * also result in some drawing artifacts if the rotated view ends up partially
   7169      * behind the camera (which is why the recommendation is to use a distance at
   7170      * least as far as the size of the view, if the view is to be rotated.)</p>
   7171      *
   7172      * <p>The distance is expressed in "depth pixels." The default distance depends
   7173      * on the screen density. For instance, on a medium density display, the
   7174      * default distance is 1280. On a high density display, the default distance
   7175      * is 1920.</p>
   7176      *
   7177      * <p>If you want to specify a distance that leads to visually consistent
   7178      * results across various densities, use the following formula:</p>
   7179      * <pre>
   7180      * float scale = context.getResources().getDisplayMetrics().density;
   7181      * view.setCameraDistance(distance * scale);
   7182      * </pre>
   7183      *
   7184      * <p>The density scale factor of a high density display is 1.5,
   7185      * and 1920 = 1280 * 1.5.</p>
   7186      *
   7187      * @param distance The distance in "depth pixels", if negative the opposite
   7188      *        value is used
   7189      *
   7190      * @see #setRotationX(float)
   7191      * @see #setRotationY(float)
   7192      */
   7193     public void setCameraDistance(float distance) {
   7194         invalidateParentCaches();
   7195         invalidate(false);
   7196 
   7197         ensureTransformationInfo();
   7198         final float dpi = mResources.getDisplayMetrics().densityDpi;
   7199         final TransformationInfo info = mTransformationInfo;
   7200         if (info.mCamera == null) {
   7201             info.mCamera = new Camera();
   7202             info.matrix3D = new Matrix();
   7203         }
   7204 
   7205         info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
   7206         info.mMatrixDirty = true;
   7207 
   7208         invalidate(false);
   7209     }
   7210 
   7211     /**
   7212      * The degrees that the view is rotated around the pivot point.
   7213      *
   7214      * @see #setRotation(float)
   7215      * @see #getPivotX()
   7216      * @see #getPivotY()
   7217      *
   7218      * @return The degrees of rotation.
   7219      */
   7220     public float getRotation() {
   7221         return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
   7222     }
   7223 
   7224     /**
   7225      * Sets the degrees that the view is rotated around the pivot point. Increasing values
   7226      * result in clockwise rotation.
   7227      *
   7228      * @param rotation The degrees of rotation.
   7229      *
   7230      * @see #getRotation()
   7231      * @see #getPivotX()
   7232      * @see #getPivotY()
   7233      * @see #setRotationX(float)
   7234      * @see #setRotationY(float)
   7235      *
   7236      * @attr ref android.R.styleable#View_rotation
   7237      */
   7238     public void setRotation(float rotation) {
   7239         ensureTransformationInfo();
   7240         final TransformationInfo info = mTransformationInfo;
   7241         if (info.mRotation != rotation) {
   7242             invalidateParentCaches();
   7243             // Double-invalidation is necessary to capture view's old and new areas
   7244             invalidate(false);
   7245             info.mRotation = rotation;
   7246             info.mMatrixDirty = true;
   7247             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7248             invalidate(false);
   7249         }
   7250     }
   7251 
   7252     /**
   7253      * The degrees that the view is rotated around the vertical axis through the pivot point.
   7254      *
   7255      * @see #getPivotX()
   7256      * @see #getPivotY()
   7257      * @see #setRotationY(float)
   7258      *
   7259      * @return The degrees of Y rotation.
   7260      */
   7261     public float getRotationY() {
   7262         return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
   7263     }
   7264 
   7265     /**
   7266      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
   7267      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
   7268      * down the y axis.
   7269      *
   7270      * When rotating large views, it is recommended to adjust the camera distance
   7271      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   7272      *
   7273      * @param rotationY The degrees of Y rotation.
   7274      *
   7275      * @see #getRotationY()
   7276      * @see #getPivotX()
   7277      * @see #getPivotY()
   7278      * @see #setRotation(float)
   7279      * @see #setRotationX(float)
   7280      * @see #setCameraDistance(float)
   7281      *
   7282      * @attr ref android.R.styleable#View_rotationY
   7283      */
   7284     public void setRotationY(float rotationY) {
   7285         ensureTransformationInfo();
   7286         final TransformationInfo info = mTransformationInfo;
   7287         if (info.mRotationY != rotationY) {
   7288             invalidateParentCaches();
   7289             // Double-invalidation is necessary to capture view's old and new areas
   7290             invalidate(false);
   7291             info.mRotationY = rotationY;
   7292             info.mMatrixDirty = true;
   7293             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7294             invalidate(false);
   7295         }
   7296     }
   7297 
   7298     /**
   7299      * The degrees that the view is rotated around the horizontal axis through the pivot point.
   7300      *
   7301      * @see #getPivotX()
   7302      * @see #getPivotY()
   7303      * @see #setRotationX(float)
   7304      *
   7305      * @return The degrees of X rotation.
   7306      */
   7307     public float getRotationX() {
   7308         return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
   7309     }
   7310 
   7311     /**
   7312      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
   7313      * Increasing values result in clockwise rotation from the viewpoint of looking down the
   7314      * x axis.
   7315      *
   7316      * When rotating large views, it is recommended to adjust the camera distance
   7317      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   7318      *
   7319      * @param rotationX The degrees of X rotation.
   7320      *
   7321      * @see #getRotationX()
   7322      * @see #getPivotX()
   7323      * @see #getPivotY()
   7324      * @see #setRotation(float)
   7325      * @see #setRotationY(float)
   7326      * @see #setCameraDistance(float)
   7327      *
   7328      * @attr ref android.R.styleable#View_rotationX
   7329      */
   7330     public void setRotationX(float rotationX) {
   7331         ensureTransformationInfo();
   7332         final TransformationInfo info = mTransformationInfo;
   7333         if (info.mRotationX != rotationX) {
   7334             invalidateParentCaches();
   7335             // Double-invalidation is necessary to capture view's old and new areas
   7336             invalidate(false);
   7337             info.mRotationX = rotationX;
   7338             info.mMatrixDirty = true;
   7339             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7340             invalidate(false);
   7341         }
   7342     }
   7343 
   7344     /**
   7345      * The amount that the view is scaled in x around the pivot point, as a proportion of
   7346      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
   7347      *
   7348      * <p>By default, this is 1.0f.
   7349      *
   7350      * @see #getPivotX()
   7351      * @see #getPivotY()
   7352      * @return The scaling factor.
   7353      */
   7354     public float getScaleX() {
   7355         return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
   7356     }
   7357 
   7358     /**
   7359      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
   7360      * the view's unscaled width. A value of 1 means that no scaling is applied.
   7361      *
   7362      * @param scaleX The scaling factor.
   7363      * @see #getPivotX()
   7364      * @see #getPivotY()
   7365      *
   7366      * @attr ref android.R.styleable#View_scaleX
   7367      */
   7368     public void setScaleX(float scaleX) {
   7369         ensureTransformationInfo();
   7370         final TransformationInfo info = mTransformationInfo;
   7371         if (info.mScaleX != scaleX) {
   7372             invalidateParentCaches();
   7373             // Double-invalidation is necessary to capture view's old and new areas
   7374             invalidate(false);
   7375             info.mScaleX = scaleX;
   7376             info.mMatrixDirty = true;
   7377             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7378             invalidate(false);
   7379         }
   7380     }
   7381 
   7382     /**
   7383      * The amount that the view is scaled in y around the pivot point, as a proportion of
   7384      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
   7385      *
   7386      * <p>By default, this is 1.0f.
   7387      *
   7388      * @see #getPivotX()
   7389      * @see #getPivotY()
   7390      * @return The scaling factor.
   7391      */
   7392     public float getScaleY() {
   7393         return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
   7394     }
   7395 
   7396     /**
   7397      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
   7398      * the view's unscaled width. A value of 1 means that no scaling is applied.
   7399      *
   7400      * @param scaleY The scaling factor.
   7401      * @see #getPivotX()
   7402      * @see #getPivotY()
   7403      *
   7404      * @attr ref android.R.styleable#View_scaleY
   7405      */
   7406     public void setScaleY(float scaleY) {
   7407         ensureTransformationInfo();
   7408         final TransformationInfo info = mTransformationInfo;
   7409         if (info.mScaleY != scaleY) {
   7410             invalidateParentCaches();
   7411             // Double-invalidation is necessary to capture view's old and new areas
   7412             invalidate(false);
   7413             info.mScaleY = scaleY;
   7414             info.mMatrixDirty = true;
   7415             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7416             invalidate(false);
   7417         }
   7418     }
   7419 
   7420     /**
   7421      * The x location of the point around which the view is {@link #setRotation(float) rotated}
   7422      * and {@link #setScaleX(float) scaled}.
   7423      *
   7424      * @see #getRotation()
   7425      * @see #getScaleX()
   7426      * @see #getScaleY()
   7427      * @see #getPivotY()
   7428      * @return The x location of the pivot point.
   7429      */
   7430     public float getPivotX() {
   7431         return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
   7432     }
   7433 
   7434     /**
   7435      * Sets the x location of the point around which the view is
   7436      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
   7437      * By default, the pivot point is centered on the object.
   7438      * Setting this property disables this behavior and causes the view to use only the
   7439      * explicitly set pivotX and pivotY values.
   7440      *
   7441      * @param pivotX The x location of the pivot point.
   7442      * @see #getRotation()
   7443      * @see #getScaleX()
   7444      * @see #getScaleY()
   7445      * @see #getPivotY()
   7446      *
   7447      * @attr ref android.R.styleable#View_transformPivotX
   7448      */
   7449     public void setPivotX(float pivotX) {
   7450         ensureTransformationInfo();
   7451         mPrivateFlags |= PIVOT_EXPLICITLY_SET;
   7452         final TransformationInfo info = mTransformationInfo;
   7453         if (info.mPivotX != pivotX) {
   7454             invalidateParentCaches();
   7455             // Double-invalidation is necessary to capture view's old and new areas
   7456             invalidate(false);
   7457             info.mPivotX = pivotX;
   7458             info.mMatrixDirty = true;
   7459             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7460             invalidate(false);
   7461         }
   7462     }
   7463 
   7464     /**
   7465      * The y location of the point around which the view is {@link #setRotation(float) rotated}
   7466      * and {@link #setScaleY(float) scaled}.
   7467      *
   7468      * @see #getRotation()
   7469      * @see #getScaleX()
   7470      * @see #getScaleY()
   7471      * @see #getPivotY()
   7472      * @return The y location of the pivot point.
   7473      */
   7474     public float getPivotY() {
   7475         return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
   7476     }
   7477 
   7478     /**
   7479      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
   7480      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
   7481      * Setting this property disables this behavior and causes the view to use only the
   7482      * explicitly set pivotX and pivotY values.
   7483      *
   7484      * @param pivotY The y location of the pivot point.
   7485      * @see #getRotation()
   7486      * @see #getScaleX()
   7487      * @see #getScaleY()
   7488      * @see #getPivotY()
   7489      *
   7490      * @attr ref android.R.styleable#View_transformPivotY
   7491      */
   7492     public void setPivotY(float pivotY) {
   7493         ensureTransformationInfo();
   7494         mPrivateFlags |= PIVOT_EXPLICITLY_SET;
   7495         final TransformationInfo info = mTransformationInfo;
   7496         if (info.mPivotY != pivotY) {
   7497             invalidateParentCaches();
   7498             // Double-invalidation is necessary to capture view's old and new areas
   7499             invalidate(false);
   7500             info.mPivotY = pivotY;
   7501             info.mMatrixDirty = true;
   7502             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7503             invalidate(false);
   7504         }
   7505     }
   7506 
   7507     /**
   7508      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
   7509      * completely transparent and 1 means the view is completely opaque.
   7510      *
   7511      * <p>By default this is 1.0f.
   7512      * @return The opacity of the view.
   7513      */
   7514     public float getAlpha() {
   7515         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
   7516     }
   7517 
   7518     /**
   7519      * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
   7520      * completely transparent and 1 means the view is completely opaque.</p>
   7521      *
   7522      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
   7523      * responsible for applying the opacity itself. Otherwise, calling this method is
   7524      * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
   7525      * setting a hardware layer.</p>
   7526      *
   7527      * @param alpha The opacity of the view.
   7528      *
   7529      * @see #setLayerType(int, android.graphics.Paint)
   7530      *
   7531      * @attr ref android.R.styleable#View_alpha
   7532      */
   7533     public void setAlpha(float alpha) {
   7534         ensureTransformationInfo();
   7535         mTransformationInfo.mAlpha = alpha;
   7536         invalidateParentCaches();
   7537         if (onSetAlpha((int) (alpha * 255))) {
   7538             mPrivateFlags |= ALPHA_SET;
   7539             // subclass is handling alpha - don't optimize rendering cache invalidation
   7540             invalidate(true);
   7541         } else {
   7542             mPrivateFlags &= ~ALPHA_SET;
   7543             invalidate(false);
   7544         }
   7545     }
   7546 
   7547     /**
   7548      * Faster version of setAlpha() which performs the same steps except there are
   7549      * no calls to invalidate(). The caller of this function should perform proper invalidation
   7550      * on the parent and this object. The return value indicates whether the subclass handles
   7551      * alpha (the return value for onSetAlpha()).
   7552      *
   7553      * @param alpha The new value for the alpha property
   7554      * @return true if the View subclass handles alpha (the return value for onSetAlpha())
   7555      */
   7556     boolean setAlphaNoInvalidation(float alpha) {
   7557         ensureTransformationInfo();
   7558         mTransformationInfo.mAlpha = alpha;
   7559         boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
   7560         if (subclassHandlesAlpha) {
   7561             mPrivateFlags |= ALPHA_SET;
   7562         } else {
   7563             mPrivateFlags &= ~ALPHA_SET;
   7564         }
   7565         return subclassHandlesAlpha;
   7566     }
   7567 
   7568     /**
   7569      * Top position of this view relative to its parent.
   7570      *
   7571      * @return The top of this view, in pixels.
   7572      */
   7573     @ViewDebug.CapturedViewProperty
   7574     public final int getTop() {
   7575         return mTop;
   7576     }
   7577 
   7578     /**
   7579      * Sets the top position of this view relative to its parent. This method is meant to be called
   7580      * by the layout system and should not generally be called otherwise, because the property
   7581      * may be changed at any time by the layout.
   7582      *
   7583      * @param top The top of this view, in pixels.
   7584      */
   7585     public final void setTop(int top) {
   7586         if (top != mTop) {
   7587             updateMatrix();
   7588             final boolean matrixIsIdentity = mTransformationInfo == null
   7589                     || mTransformationInfo.mMatrixIsIdentity;
   7590             if (matrixIsIdentity) {
   7591                 if (mAttachInfo != null) {
   7592                     int minTop;
   7593                     int yLoc;
   7594                     if (top < mTop) {
   7595                         minTop = top;
   7596                         yLoc = top - mTop;
   7597                     } else {
   7598                         minTop = mTop;
   7599                         yLoc = 0;
   7600                     }
   7601                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
   7602                 }
   7603             } else {
   7604                 // Double-invalidation is necessary to capture view's old and new areas
   7605                 invalidate(true);
   7606             }
   7607 
   7608             int width = mRight - mLeft;
   7609             int oldHeight = mBottom - mTop;
   7610 
   7611             mTop = top;
   7612 
   7613             onSizeChanged(width, mBottom - mTop, width, oldHeight);
   7614 
   7615             if (!matrixIsIdentity) {
   7616                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
   7617                     // A change in dimension means an auto-centered pivot point changes, too
   7618                     mTransformationInfo.mMatrixDirty = true;
   7619                 }
   7620                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7621                 invalidate(true);
   7622             }
   7623             mBackgroundSizeChanged = true;
   7624             invalidateParentIfNeeded();
   7625         }
   7626     }
   7627 
   7628     /**
   7629      * Bottom position of this view relative to its parent.
   7630      *
   7631      * @return The bottom of this view, in pixels.
   7632      */
   7633     @ViewDebug.CapturedViewProperty
   7634     public final int getBottom() {
   7635         return mBottom;
   7636     }
   7637 
   7638     /**
   7639      * True if this view has changed since the last time being drawn.
   7640      *
   7641      * @return The dirty state of this view.
   7642      */
   7643     public boolean isDirty() {
   7644         return (mPrivateFlags & DIRTY_MASK) != 0;
   7645     }
   7646 
   7647     /**
   7648      * Sets the bottom position of this view relative to its parent. This method is meant to be
   7649      * called by the layout system and should not generally be called otherwise, because the
   7650      * property may be changed at any time by the layout.
   7651      *
   7652      * @param bottom The bottom of this view, in pixels.
   7653      */
   7654     public final void setBottom(int bottom) {
   7655         if (bottom != mBottom) {
   7656             updateMatrix();
   7657             final boolean matrixIsIdentity = mTransformationInfo == null
   7658                     || mTransformationInfo.mMatrixIsIdentity;
   7659             if (matrixIsIdentity) {
   7660                 if (mAttachInfo != null) {
   7661                     int maxBottom;
   7662                     if (bottom < mBottom) {
   7663                         maxBottom = mBottom;
   7664                     } else {
   7665                         maxBottom = bottom;
   7666                     }
   7667                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
   7668                 }
   7669             } else {
   7670                 // Double-invalidation is necessary to capture view's old and new areas
   7671                 invalidate(true);
   7672             }
   7673 
   7674             int width = mRight - mLeft;
   7675             int oldHeight = mBottom - mTop;
   7676 
   7677             mBottom = bottom;
   7678 
   7679             onSizeChanged(width, mBottom - mTop, width, oldHeight);
   7680 
   7681             if (!matrixIsIdentity) {
   7682                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
   7683                     // A change in dimension means an auto-centered pivot point changes, too
   7684                     mTransformationInfo.mMatrixDirty = true;
   7685                 }
   7686                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7687                 invalidate(true);
   7688             }
   7689             mBackgroundSizeChanged = true;
   7690             invalidateParentIfNeeded();
   7691         }
   7692     }
   7693 
   7694     /**
   7695      * Left position of this view relative to its parent.
   7696      *
   7697      * @return The left edge of this view, in pixels.
   7698      */
   7699     @ViewDebug.CapturedViewProperty
   7700     public final int getLeft() {
   7701         return mLeft;
   7702     }
   7703 
   7704     /**
   7705      * Sets the left position of this view relative to its parent. This method is meant to be called
   7706      * by the layout system and should not generally be called otherwise, because the property
   7707      * may be changed at any time by the layout.
   7708      *
   7709      * @param left The bottom of this view, in pixels.
   7710      */
   7711     public final void setLeft(int left) {
   7712         if (left != mLeft) {
   7713             updateMatrix();
   7714             final boolean matrixIsIdentity = mTransformationInfo == null
   7715                     || mTransformationInfo.mMatrixIsIdentity;
   7716             if (matrixIsIdentity) {
   7717                 if (mAttachInfo != null) {
   7718                     int minLeft;
   7719                     int xLoc;
   7720                     if (left < mLeft) {
   7721                         minLeft = left;
   7722                         xLoc = left - mLeft;
   7723                     } else {
   7724                         minLeft = mLeft;
   7725                         xLoc = 0;
   7726                     }
   7727                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
   7728                 }
   7729             } else {
   7730                 // Double-invalidation is necessary to capture view's old and new areas
   7731                 invalidate(true);
   7732             }
   7733 
   7734             int oldWidth = mRight - mLeft;
   7735             int height = mBottom - mTop;
   7736 
   7737             mLeft = left;
   7738 
   7739             onSizeChanged(mRight - mLeft, height, oldWidth, height);
   7740 
   7741             if (!matrixIsIdentity) {
   7742                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
   7743                     // A change in dimension means an auto-centered pivot point changes, too
   7744                     mTransformationInfo.mMatrixDirty = true;
   7745                 }
   7746                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7747                 invalidate(true);
   7748             }
   7749             mBackgroundSizeChanged = true;
   7750             invalidateParentIfNeeded();
   7751         }
   7752     }
   7753 
   7754     /**
   7755      * Right position of this view relative to its parent.
   7756      *
   7757      * @return The right edge of this view, in pixels.
   7758      */
   7759     @ViewDebug.CapturedViewProperty
   7760     public final int getRight() {
   7761         return mRight;
   7762     }
   7763 
   7764     /**
   7765      * Sets the right position of this view relative to its parent. This method is meant to be called
   7766      * by the layout system and should not generally be called otherwise, because the property
   7767      * may be changed at any time by the layout.
   7768      *
   7769      * @param right The bottom of this view, in pixels.
   7770      */
   7771     public final void setRight(int right) {
   7772         if (right != mRight) {
   7773             updateMatrix();
   7774             final boolean matrixIsIdentity = mTransformationInfo == null
   7775                     || mTransformationInfo.mMatrixIsIdentity;
   7776             if (matrixIsIdentity) {
   7777                 if (mAttachInfo != null) {
   7778                     int maxRight;
   7779                     if (right < mRight) {
   7780                         maxRight = mRight;
   7781                     } else {
   7782                         maxRight = right;
   7783                     }
   7784                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
   7785                 }
   7786             } else {
   7787                 // Double-invalidation is necessary to capture view's old and new areas
   7788                 invalidate(true);
   7789             }
   7790 
   7791             int oldWidth = mRight - mLeft;
   7792             int height = mBottom - mTop;
   7793 
   7794             mRight = right;
   7795 
   7796             onSizeChanged(mRight - mLeft, height, oldWidth, height);
   7797 
   7798             if (!matrixIsIdentity) {
   7799                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
   7800                     // A change in dimension means an auto-centered pivot point changes, too
   7801                     mTransformationInfo.mMatrixDirty = true;
   7802                 }
   7803                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7804                 invalidate(true);
   7805             }
   7806             mBackgroundSizeChanged = true;
   7807             invalidateParentIfNeeded();
   7808         }
   7809     }
   7810 
   7811     /**
   7812      * The visual x position of this view, in pixels. This is equivalent to the
   7813      * {@link #setTranslationX(float) translationX} property plus the current
   7814      * {@link #getLeft() left} property.
   7815      *
   7816      * @return The visual x position of this view, in pixels.
   7817      */
   7818     public float getX() {
   7819         return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
   7820     }
   7821 
   7822     /**
   7823      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
   7824      * {@link #setTranslationX(float) translationX} property to be the difference between
   7825      * the x value passed in and the current {@link #getLeft() left} property.
   7826      *
   7827      * @param x The visual x position of this view, in pixels.
   7828      */
   7829     public void setX(float x) {
   7830         setTranslationX(x - mLeft);
   7831     }
   7832 
   7833     /**
   7834      * The visual y position of this view, in pixels. This is equivalent to the
   7835      * {@link #setTranslationY(float) translationY} property plus the current
   7836      * {@link #getTop() top} property.
   7837      *
   7838      * @return The visual y position of this view, in pixels.
   7839      */
   7840     public float getY() {
   7841         return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
   7842     }
   7843 
   7844     /**
   7845      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
   7846      * {@link #setTranslationY(float) translationY} property to be the difference between
   7847      * the y value passed in and the current {@link #getTop() top} property.
   7848      *
   7849      * @param y The visual y position of this view, in pixels.
   7850      */
   7851     public void setY(float y) {
   7852         setTranslationY(y - mTop);
   7853     }
   7854 
   7855 
   7856     /**
   7857      * The horizontal location of this view relative to its {@link #getLeft() left} position.
   7858      * This position is post-layout, in addition to wherever the object's
   7859      * layout placed it.
   7860      *
   7861      * @return The horizontal position of this view relative to its left position, in pixels.
   7862      */
   7863     public float getTranslationX() {
   7864         return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
   7865     }
   7866 
   7867     /**
   7868      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
   7869      * This effectively positions the object post-layout, in addition to wherever the object's
   7870      * layout placed it.
   7871      *
   7872      * @param translationX The horizontal position of this view relative to its left position,
   7873      * in pixels.
   7874      *
   7875      * @attr ref android.R.styleable#View_translationX
   7876      */
   7877     public void setTranslationX(float translationX) {
   7878         ensureTransformationInfo();
   7879         final TransformationInfo info = mTransformationInfo;
   7880         if (info.mTranslationX != translationX) {
   7881             invalidateParentCaches();
   7882             // Double-invalidation is necessary to capture view's old and new areas
   7883             invalidate(false);
   7884             info.mTranslationX = translationX;
   7885             info.mMatrixDirty = true;
   7886             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7887             invalidate(false);
   7888         }
   7889     }
   7890 
   7891     /**
   7892      * The horizontal location of this view relative to its {@link #getTop() top} position.
   7893      * This position is post-layout, in addition to wherever the object's
   7894      * layout placed it.
   7895      *
   7896      * @return The vertical position of this view relative to its top position,
   7897      * in pixels.
   7898      */
   7899     public float getTranslationY() {
   7900         return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
   7901     }
   7902 
   7903     /**
   7904      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
   7905      * This effectively positions the object post-layout, in addition to wherever the object's
   7906      * layout placed it.
   7907      *
   7908      * @param translationY The vertical position of this view relative to its top position,
   7909      * in pixels.
   7910      *
   7911      * @attr ref android.R.styleable#View_translationY
   7912      */
   7913     public void setTranslationY(float translationY) {
   7914         ensureTransformationInfo();
   7915         final TransformationInfo info = mTransformationInfo;
   7916         if (info.mTranslationY != translationY) {
   7917             invalidateParentCaches();
   7918             // Double-invalidation is necessary to capture view's old and new areas
   7919             invalidate(false);
   7920             info.mTranslationY = translationY;
   7921             info.mMatrixDirty = true;
   7922             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   7923             invalidate(false);
   7924         }
   7925     }
   7926 
   7927     /**
   7928      * @hide
   7929      */
   7930     public void setFastTranslationX(float x) {
   7931         ensureTransformationInfo();
   7932         final TransformationInfo info = mTransformationInfo;
   7933         info.mTranslationX = x;
   7934         info.mMatrixDirty = true;
   7935     }
   7936 
   7937     /**
   7938      * @hide
   7939      */
   7940     public void setFastTranslationY(float y) {
   7941         ensureTransformationInfo();
   7942         final TransformationInfo info = mTransformationInfo;
   7943         info.mTranslationY = y;
   7944         info.mMatrixDirty = true;
   7945     }
   7946 
   7947     /**
   7948      * @hide
   7949      */
   7950     public void setFastX(float x) {
   7951         ensureTransformationInfo();
   7952         final TransformationInfo info = mTransformationInfo;
   7953         info.mTranslationX = x - mLeft;
   7954         info.mMatrixDirty = true;
   7955     }
   7956 
   7957     /**
   7958      * @hide
   7959      */
   7960     public void setFastY(float y) {
   7961         ensureTransformationInfo();
   7962         final TransformationInfo info = mTransformationInfo;
   7963         info.mTranslationY = y - mTop;
   7964         info.mMatrixDirty = true;
   7965     }
   7966 
   7967     /**
   7968      * @hide
   7969      */
   7970     public void setFastScaleX(float x) {
   7971         ensureTransformationInfo();
   7972         final TransformationInfo info = mTransformationInfo;
   7973         info.mScaleX = x;
   7974         info.mMatrixDirty = true;
   7975     }
   7976 
   7977     /**
   7978      * @hide
   7979      */
   7980     public void setFastScaleY(float y) {
   7981         ensureTransformationInfo();
   7982         final TransformationInfo info = mTransformationInfo;
   7983         info.mScaleY = y;
   7984         info.mMatrixDirty = true;
   7985     }
   7986 
   7987     /**
   7988      * @hide
   7989      */
   7990     public void setFastAlpha(float alpha) {
   7991         ensureTransformationInfo();
   7992         mTransformationInfo.mAlpha = alpha;
   7993     }
   7994 
   7995     /**
   7996      * @hide
   7997      */
   7998     public void setFastRotationY(float y) {
   7999         ensureTransformationInfo();
   8000         final TransformationInfo info = mTransformationInfo;
   8001         info.mRotationY = y;
   8002         info.mMatrixDirty = true;
   8003     }
   8004 
   8005     /**
   8006      * Hit rectangle in parent's coordinates
   8007      *
   8008      * @param outRect The hit rectangle of the view.
   8009      */
   8010     public void getHitRect(Rect outRect) {
   8011         updateMatrix();
   8012         final TransformationInfo info = mTransformationInfo;
   8013         if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
   8014             outRect.set(mLeft, mTop, mRight, mBottom);
   8015         } else {
   8016             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
   8017             tmpRect.set(-info.mPivotX, -info.mPivotY,
   8018                     getWidth() - info.mPivotX, getHeight() - info.mPivotY);
   8019             info.mMatrix.mapRect(tmpRect);
   8020             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
   8021                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
   8022         }
   8023     }
   8024 
   8025     /**
   8026      * Determines whether the given point, in local coordinates is inside the view.
   8027      */
   8028     /*package*/ final boolean pointInView(float localX, float localY) {
   8029         return localX >= 0 && localX < (mRight - mLeft)
   8030                 && localY >= 0 && localY < (mBottom - mTop);
   8031     }
   8032 
   8033     /**
   8034      * Utility method to determine whether the given point, in local coordinates,
   8035      * is inside the view, where the area of the view is expanded by the slop factor.
   8036      * This method is called while processing touch-move events to determine if the event
   8037      * is still within the view.
   8038      */
   8039     private boolean pointInView(float localX, float localY, float slop) {
   8040         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
   8041                 localY < ((mBottom - mTop) + slop);
   8042     }
   8043 
   8044     /**
   8045      * When a view has focus and the user navigates away from it, the next view is searched for
   8046      * starting from the rectangle filled in by this method.
   8047      *
   8048      * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
   8049      * of the view.  However, if your view maintains some idea of internal selection,
   8050      * such as a cursor, or a selected row or column, you should override this method and
   8051      * fill in a more specific rectangle.
   8052      *
   8053      * @param r The rectangle to fill in, in this view's coordinates.
   8054      */
   8055     public void getFocusedRect(Rect r) {
   8056         getDrawingRect(r);
   8057     }
   8058 
   8059     /**
   8060      * If some part of this view is not clipped by any of its parents, then
   8061      * return that area in r in global (root) coordinates. To convert r to local
   8062      * coordinates (without taking possible View rotations into account), offset
   8063      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
   8064      * If the view is completely clipped or translated out, return false.
   8065      *
   8066      * @param r If true is returned, r holds the global coordinates of the
   8067      *        visible portion of this view.
   8068      * @param globalOffset If true is returned, globalOffset holds the dx,dy
   8069      *        between this view and its root. globalOffet may be null.
   8070      * @return true if r is non-empty (i.e. part of the view is visible at the
   8071      *         root level.
   8072      */
   8073     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
   8074         int width = mRight - mLeft;
   8075         int height = mBottom - mTop;
   8076         if (width > 0 && height > 0) {
   8077             r.set(0, 0, width, height);
   8078             if (globalOffset != null) {
   8079                 globalOffset.set(-mScrollX, -mScrollY);
   8080             }
   8081             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
   8082         }
   8083         return false;
   8084     }
   8085 
   8086     public final boolean getGlobalVisibleRect(Rect r) {
   8087         return getGlobalVisibleRect(r, null);
   8088     }
   8089 
   8090     public final boolean getLocalVisibleRect(Rect r) {
   8091         Point offset = new Point();
   8092         if (getGlobalVisibleRect(r, offset)) {
   8093             r.offset(-offset.x, -offset.y); // make r local
   8094             return true;
   8095         }
   8096         return false;
   8097     }
   8098 
   8099     /**
   8100      * Offset this view's vertical location by the specified number of pixels.
   8101      *
   8102      * @param offset the number of pixels to offset the view by
   8103      */
   8104     public void offsetTopAndBottom(int offset) {
   8105         if (offset != 0) {
   8106             updateMatrix();
   8107             final boolean matrixIsIdentity = mTransformationInfo == null
   8108                     || mTransformationInfo.mMatrixIsIdentity;
   8109             if (matrixIsIdentity) {
   8110                 final ViewParent p = mParent;
   8111                 if (p != null && mAttachInfo != null) {
   8112                     final Rect r = mAttachInfo.mTmpInvalRect;
   8113                     int minTop;
   8114                     int maxBottom;
   8115                     int yLoc;
   8116                     if (offset < 0) {
   8117                         minTop = mTop + offset;
   8118                         maxBottom = mBottom;
   8119                         yLoc = offset;
   8120                     } else {
   8121                         minTop = mTop;
   8122                         maxBottom = mBottom + offset;
   8123                         yLoc = 0;
   8124                     }
   8125                     r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
   8126                     p.invalidateChild(this, r);
   8127                 }
   8128             } else {
   8129                 invalidate(false);
   8130             }
   8131 
   8132             mTop += offset;
   8133             mBottom += offset;
   8134 
   8135             if (!matrixIsIdentity) {
   8136                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   8137                 invalidate(false);
   8138             }
   8139             invalidateParentIfNeeded();
   8140         }
   8141     }
   8142 
   8143     /**
   8144      * Offset this view's horizontal location by the specified amount of pixels.
   8145      *
   8146      * @param offset the numer of pixels to offset the view by
   8147      */
   8148     public void offsetLeftAndRight(int offset) {
   8149         if (offset != 0) {
   8150             updateMatrix();
   8151             final boolean matrixIsIdentity = mTransformationInfo == null
   8152                     || mTransformationInfo.mMatrixIsIdentity;
   8153             if (matrixIsIdentity) {
   8154                 final ViewParent p = mParent;
   8155                 if (p != null && mAttachInfo != null) {
   8156                     final Rect r = mAttachInfo.mTmpInvalRect;
   8157                     int minLeft;
   8158                     int maxRight;
   8159                     if (offset < 0) {
   8160                         minLeft = mLeft + offset;
   8161                         maxRight = mRight;
   8162                     } else {
   8163                         minLeft = mLeft;
   8164                         maxRight = mRight + offset;
   8165                     }
   8166                     r.set(0, 0, maxRight - minLeft, mBottom - mTop);
   8167                     p.invalidateChild(this, r);
   8168                 }
   8169             } else {
   8170                 invalidate(false);
   8171             }
   8172 
   8173             mLeft += offset;
   8174             mRight += offset;
   8175 
   8176             if (!matrixIsIdentity) {
   8177                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
   8178                 invalidate(false);
   8179             }
   8180             invalidateParentIfNeeded();
   8181         }
   8182     }
   8183 
   8184     /**
   8185      * Get the LayoutParams associated with this view. All views should have
   8186      * layout parameters. These supply parameters to the <i>parent</i> of this
   8187      * view specifying how it should be arranged. There are many subclasses of
   8188      * ViewGroup.LayoutParams, and these correspond to the different subclasses
   8189      * of ViewGroup that are responsible for arranging their children.
   8190      *
   8191      * This method may return null if this View is not attached to a parent
   8192      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
   8193      * was not invoked successfully. When a View is attached to a parent
   8194      * ViewGroup, this method must not return null.
   8195      *
   8196      * @return The LayoutParams associated with this view, or null if no
   8197      *         parameters have been set yet
   8198      */
   8199     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
   8200     public ViewGroup.LayoutParams getLayoutParams() {
   8201         return mLayoutParams;
   8202     }
   8203 
   8204     /**
   8205      * Set the layout parameters associated with this view. These supply
   8206      * parameters to the <i>parent</i> of this view specifying how it should be
   8207      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
   8208      * correspond to the different subclasses of ViewGroup that are responsible
   8209      * for arranging their children.
   8210      *
   8211      * @param params The layout parameters for this view, cannot be null
   8212      */
   8213     public void setLayoutParams(ViewGroup.LayoutParams params) {
   8214         if (params == null) {
   8215             throw new NullPointerException("Layout parameters cannot be null");
   8216         }
   8217         mLayoutParams = params;
   8218         requestLayout();
   8219     }
   8220 
   8221     /**
   8222      * Set the scrolled position of your view. This will cause a call to
   8223      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   8224      * invalidated.
   8225      * @param x the x position to scroll to
   8226      * @param y the y position to scroll to
   8227      */
   8228     public void scrollTo(int x, int y) {
   8229         if (mScrollX != x || mScrollY != y) {
   8230             int oldX = mScrollX;
   8231             int oldY = mScrollY;
   8232             mScrollX = x;
   8233             mScrollY = y;
   8234             invalidateParentCaches();
   8235             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
   8236             if (!awakenScrollBars()) {
   8237                 invalidate(true);
   8238             }
   8239         }
   8240     }
   8241 
   8242     /**
   8243      * Move the scrolled position of your view. This will cause a call to
   8244      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   8245      * invalidated.
   8246      * @param x the amount of pixels to scroll by horizontally
   8247      * @param y the amount of pixels to scroll by vertically
   8248      */
   8249     public void scrollBy(int x, int y) {
   8250         scrollTo(mScrollX + x, mScrollY + y);
   8251     }
   8252 
   8253     /**
   8254      * <p>Trigger the scrollbars to draw. When invoked this method starts an
   8255      * animation to fade the scrollbars out after a default delay. If a subclass
   8256      * provides animated scrolling, the start delay should equal the duration
   8257      * of the scrolling animation.</p>
   8258      *
   8259      * <p>The animation starts only if at least one of the scrollbars is
   8260      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
   8261      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   8262      * this method returns true, and false otherwise. If the animation is
   8263      * started, this method calls {@link #invalidate()}; in that case the
   8264      * caller should not call {@link #invalidate()}.</p>
   8265      *
   8266      * <p>This method should be invoked every time a subclass directly updates
   8267      * the scroll parameters.</p>
   8268      *
   8269      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
   8270      * and {@link #scrollTo(int, int)}.</p>
   8271      *
   8272      * @return true if the animation is played, false otherwise
   8273      *
   8274      * @see #awakenScrollBars(int)
   8275      * @see #scrollBy(int, int)
   8276      * @see #scrollTo(int, int)
   8277      * @see #isHorizontalScrollBarEnabled()
   8278      * @see #isVerticalScrollBarEnabled()
   8279      * @see #setHorizontalScrollBarEnabled(boolean)
   8280      * @see #setVerticalScrollBarEnabled(boolean)
   8281      */
   8282     protected boolean awakenScrollBars() {
   8283         return mScrollCache != null &&
   8284                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
   8285     }
   8286 
   8287     /**
   8288      * Trigger the scrollbars to draw.
   8289      * This method differs from awakenScrollBars() only in its default duration.
   8290      * initialAwakenScrollBars() will show the scroll bars for longer than
   8291      * usual to give the user more of a chance to notice them.
   8292      *
   8293      * @return true if the animation is played, false otherwise.
   8294      */
   8295     private boolean initialAwakenScrollBars() {
   8296         return mScrollCache != null &&
   8297                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
   8298     }
   8299 
   8300     /**
   8301      * <p>
   8302      * Trigger the scrollbars to draw. When invoked this method starts an
   8303      * animation to fade the scrollbars out after a fixed delay. If a subclass
   8304      * provides animated scrolling, the start delay should equal the duration of
   8305      * the scrolling animation.
   8306      * </p>
   8307      *
   8308      * <p>
   8309      * The animation starts only if at least one of the scrollbars is enabled,
   8310      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   8311      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   8312      * this method returns true, and false otherwise. If the animation is
   8313      * started, this method calls {@link #invalidate()}; in that case the caller
   8314      * should not call {@link #invalidate()}.
   8315      * </p>
   8316      *
   8317      * <p>
   8318      * This method should be invoked everytime a subclass directly updates the
   8319      * scroll parameters.
   8320      * </p>
   8321      *
   8322      * @param startDelay the delay, in milliseconds, after which the animation
   8323      *        should start; when the delay is 0, the animation starts
   8324      *        immediately
   8325      * @return true if the animation is played, false otherwise
   8326      *
   8327      * @see #scrollBy(int, int)
   8328      * @see #scrollTo(int, int)
   8329      * @see #isHorizontalScrollBarEnabled()
   8330      * @see #isVerticalScrollBarEnabled()
   8331      * @see #setHorizontalScrollBarEnabled(boolean)
   8332      * @see #setVerticalScrollBarEnabled(boolean)
   8333      */
   8334     protected boolean awakenScrollBars(int startDelay) {
   8335         return awakenScrollBars(startDelay, true);
   8336     }
   8337 
   8338     /**
   8339      * <p>
   8340      * Trigger the scrollbars to draw. When invoked this method starts an
   8341      * animation to fade the scrollbars out after a fixed delay. If a subclass
   8342      * provides animated scrolling, the start delay should equal the duration of
   8343      * the scrolling animation.
   8344      * </p>
   8345      *
   8346      * <p>
   8347      * The animation starts only if at least one of the scrollbars is enabled,
   8348      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   8349      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   8350      * this method returns true, and false otherwise. If the animation is
   8351      * started, this method calls {@link #invalidate()} if the invalidate parameter
   8352      * is set to true; in that case the caller
   8353      * should not call {@link #invalidate()}.
   8354      * </p>
   8355      *
   8356      * <p>
   8357      * This method should be invoked everytime a subclass directly updates the
   8358      * scroll parameters.
   8359      * </p>
   8360      *
   8361      * @param startDelay the delay, in milliseconds, after which the animation
   8362      *        should start; when the delay is 0, the animation starts
   8363      *        immediately
   8364      *
   8365      * @param invalidate Wheter this method should call invalidate
   8366      *
   8367      * @return true if the animation is played, false otherwise
   8368      *
   8369      * @see #scrollBy(int, int)
   8370      * @see #scrollTo(int, int)
   8371      * @see #isHorizontalScrollBarEnabled()
   8372      * @see #isVerticalScrollBarEnabled()
   8373      * @see #setHorizontalScrollBarEnabled(boolean)
   8374      * @see #setVerticalScrollBarEnabled(boolean)
   8375      */
   8376     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
   8377         final ScrollabilityCache scrollCache = mScrollCache;
   8378 
   8379         if (scrollCache == null || !scrollCache.fadeScrollBars) {
   8380             return false;
   8381         }
   8382 
   8383         if (scrollCache.scrollBar == null) {
   8384             scrollCache.scrollBar = new ScrollBarDrawable();
   8385         }
   8386 
   8387         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
   8388 
   8389             if (invalidate) {
   8390                 // Invalidate to show the scrollbars
   8391                 invalidate(true);
   8392             }
   8393 
   8394             if (scrollCache.state == ScrollabilityCache.OFF) {
   8395                 // FIXME: this is copied from WindowManagerService.
   8396                 // We should get this value from the system when it
   8397                 // is possible to do so.
   8398                 final int KEY_REPEAT_FIRST_DELAY = 750;
   8399                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
   8400             }
   8401 
   8402             // Tell mScrollCache when we should start fading. This may
   8403             // extend the fade start time if one was already scheduled
   8404             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
   8405             scrollCache.fadeStartTime = fadeStartTime;
   8406             scrollCache.state = ScrollabilityCache.ON;
   8407 
   8408             // Schedule our fader to run, unscheduling any old ones first
   8409             if (mAttachInfo != null) {
   8410                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
   8411                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
   8412             }
   8413 
   8414             return true;
   8415         }
   8416 
   8417         return false;
   8418     }
   8419 
   8420     /**
   8421      * Do not invalidate views which are not visible and which are not running an animation. They
   8422      * will not get drawn and they should not set dirty flags as if they will be drawn
   8423      */
   8424     private boolean skipInvalidate() {
   8425         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
   8426                 (!(mParent instanceof ViewGroup) ||
   8427                         !((ViewGroup) mParent).isViewTransitioning(this));
   8428     }
   8429     /**
   8430      * Mark the area defined by dirty as needing to be drawn. If the view is
   8431      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
   8432      * in the future. This must be called from a UI thread. To call from a non-UI
   8433      * thread, call {@link #postInvalidate()}.
   8434      *
   8435      * WARNING: This method is destructive to dirty.
   8436      * @param dirty the rectangle representing the bounds of the dirty region
   8437      */
   8438     public void invalidate(Rect dirty) {
   8439         if (ViewDebug.TRACE_HIERARCHY) {
   8440             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
   8441         }
   8442 
   8443         if (skipInvalidate()) {
   8444             return;
   8445         }
   8446         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
   8447                 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
   8448                 (mPrivateFlags & INVALIDATED) != INVALIDATED) {
   8449             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   8450             mPrivateFlags |= INVALIDATED;
   8451             mPrivateFlags |= DIRTY;
   8452             final ViewParent p = mParent;
   8453             final AttachInfo ai = mAttachInfo;
   8454             //noinspection PointlessBooleanExpression,ConstantConditions
   8455             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
   8456                 if (p != null && ai != null && ai.mHardwareAccelerated) {
   8457                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
   8458                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
   8459                     p.invalidateChild(this, null);
   8460                     return;
   8461                 }
   8462             }
   8463             if (p != null && ai != null) {
   8464                 final int scrollX = mScrollX;
   8465                 final int scrollY = mScrollY;
   8466                 final Rect r = ai.mTmpInvalRect;
   8467                 r.set(dirty.left - scrollX, dirty.top - scrollY,
   8468                         dirty.right - scrollX, dirty.bottom - scrollY);
   8469                 mParent.invalidateChild(this, r);
   8470             }
   8471         }
   8472     }
   8473 
   8474     /**
   8475      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
   8476      * The coordinates of the dirty rect are relative to the view.
   8477      * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
   8478      * will be called at some point in the future. This must be called from
   8479      * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
   8480      * @param l the left position of the dirty region
   8481      * @param t the top position of the dirty region
   8482      * @param r the right position of the dirty region
   8483      * @param b the bottom position of the dirty region
   8484      */
   8485     public void invalidate(int l, int t, int r, int b) {
   8486         if (ViewDebug.TRACE_HIERARCHY) {
   8487             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
   8488         }
   8489 
   8490         if (skipInvalidate()) {
   8491             return;
   8492         }
   8493         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
   8494                 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
   8495                 (mPrivateFlags & INVALIDATED) != INVALIDATED) {
   8496             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   8497             mPrivateFlags |= INVALIDATED;
   8498             mPrivateFlags |= DIRTY;
   8499             final ViewParent p = mParent;
   8500             final AttachInfo ai = mAttachInfo;
   8501             //noinspection PointlessBooleanExpression,ConstantConditions
   8502             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
   8503                 if (p != null && ai != null && ai.mHardwareAccelerated) {
   8504                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
   8505                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
   8506                     p.invalidateChild(this, null);
   8507                     return;
   8508                 }
   8509             }
   8510             if (p != null && ai != null && l < r && t < b) {
   8511                 final int scrollX = mScrollX;
   8512                 final int scrollY = mScrollY;
   8513                 final Rect tmpr = ai.mTmpInvalRect;
   8514                 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
   8515                 p.invalidateChild(this, tmpr);
   8516             }
   8517         }
   8518     }
   8519 
   8520     /**
   8521      * Invalidate the whole view. If the view is visible,
   8522      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
   8523      * the future. This must be called from a UI thread. To call from a non-UI thread,
   8524      * call {@link #postInvalidate()}.
   8525      */
   8526     public void invalidate() {
   8527         invalidate(true);
   8528     }
   8529 
   8530     /**
   8531      * This is where the invalidate() work actually happens. A full invalidate()
   8532      * causes the drawing cache to be invalidated, but this function can be called with
   8533      * invalidateCache set to false to skip that invalidation step for cases that do not
   8534      * need it (for example, a component that remains at the same dimensions with the same
   8535      * content).
   8536      *
   8537      * @param invalidateCache Whether the drawing cache for this view should be invalidated as
   8538      * well. This is usually true for a full invalidate, but may be set to false if the
   8539      * View's contents or dimensions have not changed.
   8540      */
   8541     void invalidate(boolean invalidateCache) {
   8542         if (ViewDebug.TRACE_HIERARCHY) {
   8543             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
   8544         }
   8545 
   8546         if (skipInvalidate()) {
   8547             return;
   8548         }
   8549         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
   8550                 (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
   8551                 (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
   8552             mLastIsOpaque = isOpaque();
   8553             mPrivateFlags &= ~DRAWN;
   8554             mPrivateFlags |= DIRTY;
   8555             if (invalidateCache) {
   8556                 mPrivateFlags |= INVALIDATED;
   8557                 mPrivateFlags &= ~DRAWING_CACHE_VALID;
   8558             }
   8559             final AttachInfo ai = mAttachInfo;
   8560             final ViewParent p = mParent;
   8561             //noinspection PointlessBooleanExpression,ConstantConditions
   8562             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
   8563                 if (p != null && ai != null && ai.mHardwareAccelerated) {
   8564                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
   8565                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
   8566                     p.invalidateChild(this, null);
   8567                     return;
   8568                 }
   8569             }
   8570 
   8571             if (p != null && ai != null) {
   8572                 final Rect r = ai.mTmpInvalRect;
   8573                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
   8574                 // Don't call invalidate -- we don't want to internally scroll
   8575                 // our own bounds
   8576                 p.invalidateChild(this, r);
   8577             }
   8578         }
   8579     }
   8580 
   8581     /**
   8582      * @hide
   8583      */
   8584     public void fastInvalidate() {
   8585         if (skipInvalidate()) {
   8586             return;
   8587         }
   8588         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
   8589             (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
   8590             (mPrivateFlags & INVALIDATED) != INVALIDATED) {
   8591             if (mParent instanceof View) {
   8592                 ((View) mParent).mPrivateFlags |= INVALIDATED;
   8593             }
   8594             mPrivateFlags &= ~DRAWN;
   8595             mPrivateFlags |= DIRTY;
   8596             mPrivateFlags |= INVALIDATED;
   8597             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   8598             if (mParent != null && mAttachInfo != null) {
   8599                 if (mAttachInfo.mHardwareAccelerated) {
   8600                     mParent.invalidateChild(this, null);
   8601                 } else {
   8602                     final Rect r = mAttachInfo.mTmpInvalRect;
   8603                     r.set(0, 0, mRight - mLeft, mBottom - mTop);
   8604                     // Don't call invalidate -- we don't want to internally scroll
   8605                     // our own bounds
   8606                     mParent.invalidateChild(this, r);
   8607                 }
   8608             }
   8609         }
   8610     }
   8611 
   8612     /**
   8613      * Used to indicate that the parent of this view should clear its caches. This functionality
   8614      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   8615      * which is necessary when various parent-managed properties of the view change, such as
   8616      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
   8617      * clears the parent caches and does not causes an invalidate event.
   8618      *
   8619      * @hide
   8620      */
   8621     protected void invalidateParentCaches() {
   8622         if (mParent instanceof View) {
   8623             ((View) mParent).mPrivateFlags |= INVALIDATED;
   8624         }
   8625     }
   8626 
   8627     /**
   8628      * Used to indicate that the parent of this view should be invalidated. This functionality
   8629      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   8630      * which is necessary when various parent-managed properties of the view change, such as
   8631      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
   8632      * an invalidation event to the parent.
   8633      *
   8634      * @hide
   8635      */
   8636     protected void invalidateParentIfNeeded() {
   8637         if (isHardwareAccelerated() && mParent instanceof View) {
   8638             ((View) mParent).invalidate(true);
   8639         }
   8640     }
   8641 
   8642     /**
   8643      * Indicates whether this View is opaque. An opaque View guarantees that it will
   8644      * draw all the pixels overlapping its bounds using a fully opaque color.
   8645      *
   8646      * Subclasses of View should override this method whenever possible to indicate
   8647      * whether an instance is opaque. Opaque Views are treated in a special way by
   8648      * the View hierarchy, possibly allowing it to perform optimizations during
   8649      * invalidate/draw passes.
   8650      *
   8651      * @return True if this View is guaranteed to be fully opaque, false otherwise.
   8652      */
   8653     @ViewDebug.ExportedProperty(category = "drawing")
   8654     public boolean isOpaque() {
   8655         return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
   8656                 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1)
   8657                         >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);
   8658     }
   8659 
   8660     /**
   8661      * @hide
   8662      */
   8663     protected void computeOpaqueFlags() {
   8664         // Opaque if:
   8665         //   - Has a background
   8666         //   - Background is opaque
   8667         //   - Doesn't have scrollbars or scrollbars are inside overlay
   8668 
   8669         if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
   8670             mPrivateFlags |= OPAQUE_BACKGROUND;
   8671         } else {
   8672             mPrivateFlags &= ~OPAQUE_BACKGROUND;
   8673         }
   8674 
   8675         final int flags = mViewFlags;
   8676         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
   8677                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
   8678             mPrivateFlags |= OPAQUE_SCROLLBARS;
   8679         } else {
   8680             mPrivateFlags &= ~OPAQUE_SCROLLBARS;
   8681         }
   8682     }
   8683 
   8684     /**
   8685      * @hide
   8686      */
   8687     protected boolean hasOpaqueScrollbars() {
   8688         return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
   8689     }
   8690 
   8691     /**
   8692      * @return A handler associated with the thread running the View. This
   8693      * handler can be used to pump events in the UI events queue.
   8694      */
   8695     public Handler getHandler() {
   8696         if (mAttachInfo != null) {
   8697             return mAttachInfo.mHandler;
   8698         }
   8699         return null;
   8700     }
   8701 
   8702     /**
   8703      * <p>Causes the Runnable to be added to the message queue.
   8704      * The runnable will be run on the user interface thread.</p>
   8705      *
   8706      * <p>This method can be invoked from outside of the UI thread
   8707      * only when this View is attached to a window.</p>
   8708      *
   8709      * @param action The Runnable that will be executed.
   8710      *
   8711      * @return Returns true if the Runnable was successfully placed in to the
   8712      *         message queue.  Returns false on failure, usually because the
   8713      *         looper processing the message queue is exiting.
   8714      */
   8715     public boolean post(Runnable action) {
   8716         Handler handler;
   8717         AttachInfo attachInfo = mAttachInfo;
   8718         if (attachInfo != null) {
   8719             handler = attachInfo.mHandler;
   8720         } else {
   8721             // Assume that post will succeed later
   8722             ViewRootImpl.getRunQueue().post(action);
   8723             return true;
   8724         }
   8725 
   8726         return handler.post(action);
   8727     }
   8728 
   8729     /**
   8730      * <p>Causes the Runnable to be added to the message queue, to be run
   8731      * after the specified amount of time elapses.
   8732      * The runnable will be run on the user interface thread.</p>
   8733      *
   8734      * <p>This method can be invoked from outside of the UI thread
   8735      * only when this View is attached to a window.</p>
   8736      *
   8737      * @param action The Runnable that will be executed.
   8738      * @param delayMillis The delay (in milliseconds) until the Runnable
   8739      *        will be executed.
   8740      *
   8741      * @return true if the Runnable was successfully placed in to the
   8742      *         message queue.  Returns false on failure, usually because the
   8743      *         looper processing the message queue is exiting.  Note that a
   8744      *         result of true does not mean the Runnable will be processed --
   8745      *         if the looper is quit before the delivery time of the message
   8746      *         occurs then the message will be dropped.
   8747      */
   8748     public boolean postDelayed(Runnable action, long delayMillis) {
   8749         Handler handler;
   8750         AttachInfo attachInfo = mAttachInfo;
   8751         if (attachInfo != null) {
   8752             handler = attachInfo.mHandler;
   8753         } else {
   8754             // Assume that post will succeed later
   8755             ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
   8756             return true;
   8757         }
   8758 
   8759         return handler.postDelayed(action, delayMillis);
   8760     }
   8761 
   8762     /**
   8763      * <p>Removes the specified Runnable from the message queue.</p>
   8764      *
   8765      * <p>This method can be invoked from outside of the UI thread
   8766      * only when this View is attached to a window.</p>
   8767      *
   8768      * @param action The Runnable to remove from the message handling queue
   8769      *
   8770      * @return true if this view could ask the Handler to remove the Runnable,
   8771      *         false otherwise. When the returned value is true, the Runnable
   8772      *         may or may not have been actually removed from the message queue
   8773      *         (for instance, if the Runnable was not in the queue already.)
   8774      */
   8775     public boolean removeCallbacks(Runnable action) {
   8776         Handler handler;
   8777         AttachInfo attachInfo = mAttachInfo;
   8778         if (attachInfo != null) {
   8779             handler = attachInfo.mHandler;
   8780         } else {
   8781             // Assume that post will succeed later
   8782             ViewRootImpl.getRunQueue().removeCallbacks(action);
   8783             return true;
   8784         }
   8785 
   8786         handler.removeCallbacks(action);
   8787         return true;
   8788     }
   8789 
   8790     /**
   8791      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
   8792      * Use this to invalidate the View from a non-UI thread.</p>
   8793      *
   8794      * <p>This method can be invoked from outside of the UI thread
   8795      * only when this View is attached to a window.</p>
   8796      *
   8797      * @see #invalidate()
   8798      */
   8799     public void postInvalidate() {
   8800         postInvalidateDelayed(0);
   8801     }
   8802 
   8803     /**
   8804      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   8805      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
   8806      *
   8807      * <p>This method can be invoked from outside of the UI thread
   8808      * only when this View is attached to a window.</p>
   8809      *
   8810      * @param left The left coordinate of the rectangle to invalidate.
   8811      * @param top The top coordinate of the rectangle to invalidate.
   8812      * @param right The right coordinate of the rectangle to invalidate.
   8813      * @param bottom The bottom coordinate of the rectangle to invalidate.
   8814      *
   8815      * @see #invalidate(int, int, int, int)
   8816      * @see #invalidate(Rect)
   8817      */
   8818     public void postInvalidate(int left, int top, int right, int bottom) {
   8819         postInvalidateDelayed(0, left, top, right, bottom);
   8820     }
   8821 
   8822     /**
   8823      * <p>Cause an invalidate to happen on a subsequent cycle through the event
   8824      * loop. Waits for the specified amount of time.</p>
   8825      *
   8826      * <p>This method can be invoked from outside of the UI thread
   8827      * only when this View is attached to a window.</p>
   8828      *
   8829      * @param delayMilliseconds the duration in milliseconds to delay the
   8830      *         invalidation by
   8831      */
   8832     public void postInvalidateDelayed(long delayMilliseconds) {
   8833         // We try only with the AttachInfo because there's no point in invalidating
   8834         // if we are not attached to our window
   8835         AttachInfo attachInfo = mAttachInfo;
   8836         if (attachInfo != null) {
   8837             Message msg = Message.obtain();
   8838             msg.what = AttachInfo.INVALIDATE_MSG;
   8839             msg.obj = this;
   8840             attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
   8841         }
   8842     }
   8843 
   8844     /**
   8845      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   8846      * through the event loop. Waits for the specified amount of time.</p>
   8847      *
   8848      * <p>This method can be invoked from outside of the UI thread
   8849      * only when this View is attached to a window.</p>
   8850      *
   8851      * @param delayMilliseconds the duration in milliseconds to delay the
   8852      *         invalidation by
   8853      * @param left The left coordinate of the rectangle to invalidate.
   8854      * @param top The top coordinate of the rectangle to invalidate.
   8855      * @param right The right coordinate of the rectangle to invalidate.
   8856      * @param bottom The bottom coordinate of the rectangle to invalidate.
   8857      */
   8858     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
   8859             int right, int bottom) {
   8860 
   8861         // We try only with the AttachInfo because there's no point in invalidating
   8862         // if we are not attached to our window
   8863         AttachInfo attachInfo = mAttachInfo;
   8864         if (attachInfo != null) {
   8865             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
   8866             info.target = this;
   8867             info.left = left;
   8868             info.top = top;
   8869             info.right = right;
   8870             info.bottom = bottom;
   8871 
   8872             final Message msg = Message.obtain();
   8873             msg.what = AttachInfo.INVALIDATE_RECT_MSG;
   8874             msg.obj = info;
   8875             attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
   8876         }
   8877     }
   8878 
   8879     /**
   8880      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
   8881      * This event is sent at most once every
   8882      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
   8883      */
   8884     private void postSendViewScrolledAccessibilityEventCallback() {
   8885         if (mSendViewScrolledAccessibilityEvent == null) {
   8886             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
   8887         }
   8888         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
   8889             mSendViewScrolledAccessibilityEvent.mIsPending = true;
   8890             postDelayed(mSendViewScrolledAccessibilityEvent,
   8891                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
   8892         }
   8893     }
   8894 
   8895     /**
   8896      * Called by a parent to request that a child update its values for mScrollX
   8897      * and mScrollY if necessary. This will typically be done if the child is
   8898      * animating a scroll using a {@link android.widget.Scroller Scroller}
   8899      * object.
   8900      */
   8901     public void computeScroll() {
   8902     }
   8903 
   8904     /**
   8905      * <p>Indicate whether the horizontal edges are faded when the view is
   8906      * scrolled horizontally.</p>
   8907      *
   8908      * @return true if the horizontal edges should are faded on scroll, false
   8909      *         otherwise
   8910      *
   8911      * @see #setHorizontalFadingEdgeEnabled(boolean)
   8912      * @attr ref android.R.styleable#View_requiresFadingEdge
   8913      */
   8914     public boolean isHorizontalFadingEdgeEnabled() {
   8915         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
   8916     }
   8917 
   8918     /**
   8919      * <p>Define whether the horizontal edges should be faded when this view
   8920      * is scrolled horizontally.</p>
   8921      *
   8922      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
   8923      *                                    be faded when the view is scrolled
   8924      *                                    horizontally
   8925      *
   8926      * @see #isHorizontalFadingEdgeEnabled()
   8927      * @attr ref android.R.styleable#View_requiresFadingEdge
   8928      */
   8929     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
   8930         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
   8931             if (horizontalFadingEdgeEnabled) {
   8932                 initScrollCache();
   8933             }
   8934 
   8935             mViewFlags ^= FADING_EDGE_HORIZONTAL;
   8936         }
   8937     }
   8938 
   8939     /**
   8940      * <p>Indicate whether the vertical edges are faded when the view is
   8941      * scrolled horizontally.</p>
   8942      *
   8943      * @return true if the vertical edges should are faded on scroll, false
   8944      *         otherwise
   8945      *
   8946      * @see #setVerticalFadingEdgeEnabled(boolean)
   8947      * @attr ref android.R.styleable#View_requiresFadingEdge
   8948      */
   8949     public boolean isVerticalFadingEdgeEnabled() {
   8950         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
   8951     }
   8952 
   8953     /**
   8954      * <p>Define whether the vertical edges should be faded when this view
   8955      * is scrolled vertically.</p>
   8956      *
   8957      * @param verticalFadingEdgeEnabled true if the vertical edges should
   8958      *                                  be faded when the view is scrolled
   8959      *                                  vertically
   8960      *
   8961      * @see #isVerticalFadingEdgeEnabled()
   8962      * @attr ref android.R.styleable#View_requiresFadingEdge
   8963      */
   8964     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
   8965         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
   8966             if (verticalFadingEdgeEnabled) {
   8967                 initScrollCache();
   8968             }
   8969 
   8970             mViewFlags ^= FADING_EDGE_VERTICAL;
   8971         }
   8972     }
   8973 
   8974     /**
   8975      * Returns the strength, or intensity, of the top faded edge. The strength is
   8976      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   8977      * returns 0.0 or 1.0 but no value in between.
   8978      *
   8979      * Subclasses should override this method to provide a smoother fade transition
   8980      * when scrolling occurs.
   8981      *
   8982      * @return the intensity of the top fade as a float between 0.0f and 1.0f
   8983      */
   8984     protected float getTopFadingEdgeStrength() {
   8985         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
   8986     }
   8987 
   8988     /**
   8989      * Returns the strength, or intensity, of the bottom faded edge. The strength is
   8990      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   8991      * returns 0.0 or 1.0 but no value in between.
   8992      *
   8993      * Subclasses should override this method to provide a smoother fade transition
   8994      * when scrolling occurs.
   8995      *
   8996      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
   8997      */
   8998     protected float getBottomFadingEdgeStrength() {
   8999         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
   9000                 computeVerticalScrollRange() ? 1.0f : 0.0f;
   9001     }
   9002 
   9003     /**
   9004      * Returns the strength, or intensity, of the left faded edge. The strength is
   9005      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   9006      * returns 0.0 or 1.0 but no value in between.
   9007      *
   9008      * Subclasses should override this method to provide a smoother fade transition
   9009      * when scrolling occurs.
   9010      *
   9011      * @return the intensity of the left fade as a float between 0.0f and 1.0f
   9012      */
   9013     protected float getLeftFadingEdgeStrength() {
   9014         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
   9015     }
   9016 
   9017     /**
   9018      * Returns the strength, or intensity, of the right faded edge. The strength is
   9019      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   9020      * returns 0.0 or 1.0 but no value in between.
   9021      *
   9022      * Subclasses should override this method to provide a smoother fade transition
   9023      * when scrolling occurs.
   9024      *
   9025      * @return the intensity of the right fade as a float between 0.0f and 1.0f
   9026      */
   9027     protected float getRightFadingEdgeStrength() {
   9028         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
   9029                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
   9030     }
   9031 
   9032     /**
   9033      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
   9034      * scrollbar is not drawn by default.</p>
   9035      *
   9036      * @return true if the horizontal scrollbar should be painted, false
   9037      *         otherwise
   9038      *
   9039      * @see #setHorizontalScrollBarEnabled(boolean)
   9040      */
   9041     public boolean isHorizontalScrollBarEnabled() {
   9042         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   9043     }
   9044 
   9045     /**
   9046      * <p>Define whether the horizontal scrollbar should be drawn or not. The
   9047      * scrollbar is not drawn by default.</p>
   9048      *
   9049      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
   9050      *                                   be painted
   9051      *
   9052      * @see #isHorizontalScrollBarEnabled()
   9053      */
   9054     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
   9055         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
   9056             mViewFlags ^= SCROLLBARS_HORIZONTAL;
   9057             computeOpaqueFlags();
   9058             resolvePadding();
   9059         }
   9060     }
   9061 
   9062     /**
   9063      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
   9064      * scrollbar is not drawn by default.</p>
   9065      *
   9066      * @return true if the vertical scrollbar should be painted, false
   9067      *         otherwise
   9068      *
   9069      * @see #setVerticalScrollBarEnabled(boolean)
   9070      */
   9071     public boolean isVerticalScrollBarEnabled() {
   9072         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
   9073     }
   9074 
   9075     /**
   9076      * <p>Define whether the vertical scrollbar should be drawn or not. The
   9077      * scrollbar is not drawn by default.</p>
   9078      *
   9079      * @param verticalScrollBarEnabled true if the vertical scrollbar should
   9080      *                                 be painted
   9081      *
   9082      * @see #isVerticalScrollBarEnabled()
   9083      */
   9084     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
   9085         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
   9086             mViewFlags ^= SCROLLBARS_VERTICAL;
   9087             computeOpaqueFlags();
   9088             resolvePadding();
   9089         }
   9090     }
   9091 
   9092     /**
   9093      * @hide
   9094      */
   9095     protected void recomputePadding() {
   9096         setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   9097     }
   9098 
   9099     /**
   9100      * Define whether scrollbars will fade when the view is not scrolling.
   9101      *
   9102      * @param fadeScrollbars wheter to enable fading
   9103      *
   9104      */
   9105     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
   9106         initScrollCache();
   9107         final ScrollabilityCache scrollabilityCache = mScrollCache;
   9108         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   9109         if (fadeScrollbars) {
   9110             scrollabilityCache.state = ScrollabilityCache.OFF;
   9111         } else {
   9112             scrollabilityCache.state = ScrollabilityCache.ON;
   9113         }
   9114     }
   9115 
   9116     /**
   9117      *
   9118      * Returns true if scrollbars will fade when this view is not scrolling
   9119      *
   9120      * @return true if scrollbar fading is enabled
   9121      */
   9122     public boolean isScrollbarFadingEnabled() {
   9123         return mScrollCache != null && mScrollCache.fadeScrollBars;
   9124     }
   9125 
   9126     /**
   9127      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
   9128      * inset. When inset, they add to the padding of the view. And the scrollbars
   9129      * can be drawn inside the padding area or on the edge of the view. For example,
   9130      * if a view has a background drawable and you want to draw the scrollbars
   9131      * inside the padding specified by the drawable, you can use
   9132      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
   9133      * appear at the edge of the view, ignoring the padding, then you can use
   9134      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
   9135      * @param style the style of the scrollbars. Should be one of
   9136      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
   9137      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
   9138      * @see #SCROLLBARS_INSIDE_OVERLAY
   9139      * @see #SCROLLBARS_INSIDE_INSET
   9140      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   9141      * @see #SCROLLBARS_OUTSIDE_INSET
   9142      */
   9143     public void setScrollBarStyle(int style) {
   9144         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
   9145             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
   9146             computeOpaqueFlags();
   9147             resolvePadding();
   9148         }
   9149     }
   9150 
   9151     /**
   9152      * <p>Returns the current scrollbar style.</p>
   9153      * @return the current scrollbar style
   9154      * @see #SCROLLBARS_INSIDE_OVERLAY
   9155      * @see #SCROLLBARS_INSIDE_INSET
   9156      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   9157      * @see #SCROLLBARS_OUTSIDE_INSET
   9158      */
   9159     @ViewDebug.ExportedProperty(mapping = {
   9160             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
   9161             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
   9162             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
   9163             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
   9164     })
   9165     public int getScrollBarStyle() {
   9166         return mViewFlags & SCROLLBARS_STYLE_MASK;
   9167     }
   9168 
   9169     /**
   9170      * <p>Compute the horizontal range that the horizontal scrollbar
   9171      * represents.</p>
   9172      *
   9173      * <p>The range is expressed in arbitrary units that must be the same as the
   9174      * units used by {@link #computeHorizontalScrollExtent()} and
   9175      * {@link #computeHorizontalScrollOffset()}.</p>
   9176      *
   9177      * <p>The default range is the drawing width of this view.</p>
   9178      *
   9179      * @return the total horizontal range represented by the horizontal
   9180      *         scrollbar
   9181      *
   9182      * @see #computeHorizontalScrollExtent()
   9183      * @see #computeHorizontalScrollOffset()
   9184      * @see android.widget.ScrollBarDrawable
   9185      */
   9186     protected int computeHorizontalScrollRange() {
   9187         return getWidth();
   9188     }
   9189 
   9190     /**
   9191      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
   9192      * within the horizontal range. This value is used to compute the position
   9193      * of the thumb within the scrollbar's track.</p>
   9194      *
   9195      * <p>The range is expressed in arbitrary units that must be the same as the
   9196      * units used by {@link #computeHorizontalScrollRange()} and
   9197      * {@link #computeHorizontalScrollExtent()}.</p>
   9198      *
   9199      * <p>The default offset is the scroll offset of this view.</p>
   9200      *
   9201      * @return the horizontal offset of the scrollbar's thumb
   9202      *
   9203      * @see #computeHorizontalScrollRange()
   9204      * @see #computeHorizontalScrollExtent()
   9205      * @see android.widget.ScrollBarDrawable
   9206      */
   9207     protected int computeHorizontalScrollOffset() {
   9208         return mScrollX;
   9209     }
   9210 
   9211     /**
   9212      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
   9213      * within the horizontal range. This value is used to compute the length
   9214      * of the thumb within the scrollbar's track.</p>
   9215      *
   9216      * <p>The range is expressed in arbitrary units that must be the same as the
   9217      * units used by {@link #computeHorizontalScrollRange()} and
   9218      * {@link #computeHorizontalScrollOffset()}.</p>
   9219      *
   9220      * <p>The default extent is the drawing width of this view.</p>
   9221      *
   9222      * @return the horizontal extent of the scrollbar's thumb
   9223      *
   9224      * @see #computeHorizontalScrollRange()
   9225      * @see #computeHorizontalScrollOffset()
   9226      * @see android.widget.ScrollBarDrawable
   9227      */
   9228     protected int computeHorizontalScrollExtent() {
   9229         return getWidth();
   9230     }
   9231 
   9232     /**
   9233      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
   9234      *
   9235      * <p>The range is expressed in arbitrary units that must be the same as the
   9236      * units used by {@link #computeVerticalScrollExtent()} and
   9237      * {@link #computeVerticalScrollOffset()}.</p>
   9238      *
   9239      * @return the total vertical range represented by the vertical scrollbar
   9240      *
   9241      * <p>The default range is the drawing height of this view.</p>
   9242      *
   9243      * @see #computeVerticalScrollExtent()
   9244      * @see #computeVerticalScrollOffset()
   9245      * @see android.widget.ScrollBarDrawable
   9246      */
   9247     protected int computeVerticalScrollRange() {
   9248         return getHeight();
   9249     }
   9250 
   9251     /**
   9252      * <p>Compute the vertical offset of the vertical scrollbar's thumb
   9253      * within the horizontal range. This value is used to compute the position
   9254      * of the thumb within the scrollbar's track.</p>
   9255      *
   9256      * <p>The range is expressed in arbitrary units that must be the same as the
   9257      * units used by {@link #computeVerticalScrollRange()} and
   9258      * {@link #computeVerticalScrollExtent()}.</p>
   9259      *
   9260      * <p>The default offset is the scroll offset of this view.</p>
   9261      *
   9262      * @return the vertical offset of the scrollbar's thumb
   9263      *
   9264      * @see #computeVerticalScrollRange()
   9265      * @see #computeVerticalScrollExtent()
   9266      * @see android.widget.ScrollBarDrawable
   9267      */
   9268     protected int computeVerticalScrollOffset() {
   9269         return mScrollY;
   9270     }
   9271 
   9272     /**
   9273      * <p>Compute the vertical extent of the horizontal scrollbar's thumb
   9274      * within the vertical range. This value is used to compute the length
   9275      * of the thumb within the scrollbar's track.</p>
   9276      *
   9277      * <p>The range is expressed in arbitrary units that must be the same as the
   9278      * units used by {@link #computeVerticalScrollRange()} and
   9279      * {@link #computeVerticalScrollOffset()}.</p>
   9280      *
   9281      * <p>The default extent is the drawing height of this view.</p>
   9282      *
   9283      * @return the vertical extent of the scrollbar's thumb
   9284      *
   9285      * @see #computeVerticalScrollRange()
   9286      * @see #computeVerticalScrollOffset()
   9287      * @see android.widget.ScrollBarDrawable
   9288      */
   9289     protected int computeVerticalScrollExtent() {
   9290         return getHeight();
   9291     }
   9292 
   9293     /**
   9294      * Check if this view can be scrolled horizontally in a certain direction.
   9295      *
   9296      * @param direction Negative to check scrolling left, positive to check scrolling right.
   9297      * @return true if this view can be scrolled in the specified direction, false otherwise.
   9298      */
   9299     public boolean canScrollHorizontally(int direction) {
   9300         final int offset = computeHorizontalScrollOffset();
   9301         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
   9302         if (range == 0) return false;
   9303         if (direction < 0) {
   9304             return offset > 0;
   9305         } else {
   9306             return offset < range - 1;
   9307         }
   9308     }
   9309 
   9310     /**
   9311      * Check if this view can be scrolled vertically in a certain direction.
   9312      *
   9313      * @param direction Negative to check scrolling up, positive to check scrolling down.
   9314      * @return true if this view can be scrolled in the specified direction, false otherwise.
   9315      */
   9316     public boolean canScrollVertically(int direction) {
   9317         final int offset = computeVerticalScrollOffset();
   9318         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
   9319         if (range == 0) return false;
   9320         if (direction < 0) {
   9321             return offset > 0;
   9322         } else {
   9323             return offset < range - 1;
   9324         }
   9325     }
   9326 
   9327     /**
   9328      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
   9329      * scrollbars are painted only if they have been awakened first.</p>
   9330      *
   9331      * @param canvas the canvas on which to draw the scrollbars
   9332      *
   9333      * @see #awakenScrollBars(int)
   9334      */
   9335     protected final void onDrawScrollBars(Canvas canvas) {
   9336         // scrollbars are drawn only when the animation is running
   9337         final ScrollabilityCache cache = mScrollCache;
   9338         if (cache != null) {
   9339 
   9340             int state = cache.state;
   9341 
   9342             if (state == ScrollabilityCache.OFF) {
   9343                 return;
   9344             }
   9345 
   9346             boolean invalidate = false;
   9347 
   9348             if (state == ScrollabilityCache.FADING) {
   9349                 // We're fading -- get our fade interpolation
   9350                 if (cache.interpolatorValues == null) {
   9351                     cache.interpolatorValues = new float[1];
   9352                 }
   9353 
   9354                 float[] values = cache.interpolatorValues;
   9355 
   9356                 // Stops the animation if we're done
   9357                 if (cache.scrollBarInterpolator.timeToValues(values) ==
   9358                         Interpolator.Result.FREEZE_END) {
   9359                     cache.state = ScrollabilityCache.OFF;
   9360                 } else {
   9361                     cache.scrollBar.setAlpha(Math.round(values[0]));
   9362                 }
   9363 
   9364                 // This will make the scroll bars inval themselves after
   9365                 // drawing. We only want this when we're fading so that
   9366                 // we prevent excessive redraws
   9367                 invalidate = true;
   9368             } else {
   9369                 // We're just on -- but we may have been fading before so
   9370                 // reset alpha
   9371                 cache.scrollBar.setAlpha(255);
   9372             }
   9373 
   9374 
   9375             final int viewFlags = mViewFlags;
   9376 
   9377             final boolean drawHorizontalScrollBar =
   9378                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   9379             final boolean drawVerticalScrollBar =
   9380                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
   9381                 && !isVerticalScrollBarHidden();
   9382 
   9383             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
   9384                 final int width = mRight - mLeft;
   9385                 final int height = mBottom - mTop;
   9386 
   9387                 final ScrollBarDrawable scrollBar = cache.scrollBar;
   9388 
   9389                 final int scrollX = mScrollX;
   9390                 final int scrollY = mScrollY;
   9391                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   9392 
   9393                 int left, top, right, bottom;
   9394 
   9395                 if (drawHorizontalScrollBar) {
   9396                     int size = scrollBar.getSize(false);
   9397                     if (size <= 0) {
   9398                         size = cache.scrollBarSize;
   9399                     }
   9400 
   9401                     scrollBar.setParameters(computeHorizontalScrollRange(),
   9402                                             computeHorizontalScrollOffset(),
   9403                                             computeHorizontalScrollExtent(), false);
   9404                     final int verticalScrollBarGap = drawVerticalScrollBar ?
   9405                             getVerticalScrollbarWidth() : 0;
   9406                     top = scrollY + height - size - (mUserPaddingBottom & inside);
   9407                     left = scrollX + (mPaddingLeft & inside);
   9408                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
   9409                     bottom = top + size;
   9410                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
   9411                     if (invalidate) {
   9412                         invalidate(left, top, right, bottom);
   9413                     }
   9414                 }
   9415 
   9416                 if (drawVerticalScrollBar) {
   9417                     int size = scrollBar.getSize(true);
   9418                     if (size <= 0) {
   9419                         size = cache.scrollBarSize;
   9420                     }
   9421 
   9422                     scrollBar.setParameters(computeVerticalScrollRange(),
   9423                                             computeVerticalScrollOffset(),
   9424                                             computeVerticalScrollExtent(), true);
   9425                     switch (mVerticalScrollbarPosition) {
   9426                         default:
   9427                         case SCROLLBAR_POSITION_DEFAULT:
   9428                         case SCROLLBAR_POSITION_RIGHT:
   9429                             left = scrollX + width - size - (mUserPaddingRight & inside);
   9430                             break;
   9431                         case SCROLLBAR_POSITION_LEFT:
   9432                             left = scrollX + (mUserPaddingLeft & inside);
   9433                             break;
   9434                     }
   9435                     top = scrollY + (mPaddingTop & inside);
   9436                     right = left + size;
   9437                     bottom = scrollY + height - (mUserPaddingBottom & inside);
   9438                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
   9439                     if (invalidate) {
   9440                         invalidate(left, top, right, bottom);
   9441                     }
   9442                 }
   9443             }
   9444         }
   9445     }
   9446 
   9447     /**
   9448      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
   9449      * FastScroller is visible.
   9450      * @return whether to temporarily hide the vertical scrollbar
   9451      * @hide
   9452      */
   9453     protected boolean isVerticalScrollBarHidden() {
   9454         return false;
   9455     }
   9456 
   9457     /**
   9458      * <p>Draw the horizontal scrollbar if
   9459      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
   9460      *
   9461      * @param canvas the canvas on which to draw the scrollbar
   9462      * @param scrollBar the scrollbar's drawable
   9463      *
   9464      * @see #isHorizontalScrollBarEnabled()
   9465      * @see #computeHorizontalScrollRange()
   9466      * @see #computeHorizontalScrollExtent()
   9467      * @see #computeHorizontalScrollOffset()
   9468      * @see android.widget.ScrollBarDrawable
   9469      * @hide
   9470      */
   9471     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
   9472             int l, int t, int r, int b) {
   9473         scrollBar.setBounds(l, t, r, b);
   9474         scrollBar.draw(canvas);
   9475     }
   9476 
   9477     /**
   9478      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
   9479      * returns true.</p>
   9480      *
   9481      * @param canvas the canvas on which to draw the scrollbar
   9482      * @param scrollBar the scrollbar's drawable
   9483      *
   9484      * @see #isVerticalScrollBarEnabled()
   9485      * @see #computeVerticalScrollRange()
   9486      * @see #computeVerticalScrollExtent()
   9487      * @see #computeVerticalScrollOffset()
   9488      * @see android.widget.ScrollBarDrawable
   9489      * @hide
   9490      */
   9491     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
   9492             int l, int t, int r, int b) {
   9493         scrollBar.setBounds(l, t, r, b);
   9494         scrollBar.draw(canvas);
   9495     }
   9496 
   9497     /**
   9498      * Implement this to do your drawing.
   9499      *
   9500      * @param canvas the canvas on which the background will be drawn
   9501      */
   9502     protected void onDraw(Canvas canvas) {
   9503     }
   9504 
   9505     /*
   9506      * Caller is responsible for calling requestLayout if necessary.
   9507      * (This allows addViewInLayout to not request a new layout.)
   9508      */
   9509     void assignParent(ViewParent parent) {
   9510         if (mParent == null) {
   9511             mParent = parent;
   9512         } else if (parent == null) {
   9513             mParent = null;
   9514         } else {
   9515             throw new RuntimeException("view " + this + " being added, but"
   9516                     + " it already has a parent");
   9517         }
   9518     }
   9519 
   9520     /**
   9521      * This is called when the view is attached to a window.  At this point it
   9522      * has a Surface and will start drawing.  Note that this function is
   9523      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
   9524      * however it may be called any time before the first onDraw -- including
   9525      * before or after {@link #onMeasure(int, int)}.
   9526      *
   9527      * @see #onDetachedFromWindow()
   9528      */
   9529     protected void onAttachedToWindow() {
   9530         if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
   9531             mParent.requestTransparentRegion(this);
   9532         }
   9533         if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
   9534             initialAwakenScrollBars();
   9535             mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
   9536         }
   9537         jumpDrawablesToCurrentState();
   9538         // Order is important here: LayoutDirection MUST be resolved before Padding
   9539         // and TextDirection
   9540         resolveLayoutDirectionIfNeeded();
   9541         resolvePadding();
   9542         resolveTextDirection();
   9543         if (isFocused()) {
   9544             InputMethodManager imm = InputMethodManager.peekInstance();
   9545             imm.focusIn(this);
   9546         }
   9547     }
   9548 
   9549     /**
   9550      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
   9551      * that the parent directionality can and will be resolved before its children.
   9552      */
   9553     private void resolveLayoutDirectionIfNeeded() {
   9554         // Do not resolve if it is not needed
   9555         if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) == LAYOUT_DIRECTION_RESOLVED) return;
   9556 
   9557         // Clear any previous layout direction resolution
   9558         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_RTL;
   9559 
   9560         // Reset also TextDirection as a change into LayoutDirection may impact the selected
   9561         // TextDirectionHeuristic
   9562         resetResolvedTextDirection();
   9563 
   9564         // Set resolved depending on layout direction
   9565         switch (getLayoutDirection()) {
   9566             case LAYOUT_DIRECTION_INHERIT:
   9567                 // We cannot do the resolution if there is no parent
   9568                 if (mParent == null) return;
   9569 
   9570                 // If this is root view, no need to look at parent's layout dir.
   9571                 if (mParent instanceof ViewGroup) {
   9572                     ViewGroup viewGroup = ((ViewGroup) mParent);
   9573 
   9574                     // Check if the parent view group can resolve
   9575                     if (! viewGroup.canResolveLayoutDirection()) {
   9576                         return;
   9577                     }
   9578                     if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   9579                         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
   9580                     }
   9581                 }
   9582                 break;
   9583             case LAYOUT_DIRECTION_RTL:
   9584                 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
   9585                 break;
   9586             case LAYOUT_DIRECTION_LOCALE:
   9587                 if(isLayoutDirectionRtl(Locale.getDefault())) {
   9588                     mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
   9589                 }
   9590                 break;
   9591             default:
   9592                 // Nothing to do, LTR by default
   9593         }
   9594 
   9595         // Set to resolved
   9596         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
   9597     }
   9598 
   9599     /**
   9600      * @hide
   9601      */
   9602     protected void resolvePadding() {
   9603         // If the user specified the absolute padding (either with android:padding or
   9604         // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
   9605         // use the default padding or the padding from the background drawable
   9606         // (stored at this point in mPadding*)
   9607         switch (getResolvedLayoutDirection()) {
   9608             case LAYOUT_DIRECTION_RTL:
   9609                 // Start user padding override Right user padding. Otherwise, if Right user
   9610                 // padding is not defined, use the default Right padding. If Right user padding
   9611                 // is defined, just use it.
   9612                 if (mUserPaddingStart >= 0) {
   9613                     mUserPaddingRight = mUserPaddingStart;
   9614                 } else if (mUserPaddingRight < 0) {
   9615                     mUserPaddingRight = mPaddingRight;
   9616                 }
   9617                 if (mUserPaddingEnd >= 0) {
   9618                     mUserPaddingLeft = mUserPaddingEnd;
   9619                 } else if (mUserPaddingLeft < 0) {
   9620                     mUserPaddingLeft = mPaddingLeft;
   9621                 }
   9622                 break;
   9623             case LAYOUT_DIRECTION_LTR:
   9624             default:
   9625                 // Start user padding override Left user padding. Otherwise, if Left user
   9626                 // padding is not defined, use the default left padding. If Left user padding
   9627                 // is defined, just use it.
   9628                 if (mUserPaddingStart >= 0) {
   9629                     mUserPaddingLeft = mUserPaddingStart;
   9630                 } else if (mUserPaddingLeft < 0) {
   9631                     mUserPaddingLeft = mPaddingLeft;
   9632                 }
   9633                 if (mUserPaddingEnd >= 0) {
   9634                     mUserPaddingRight = mUserPaddingEnd;
   9635                 } else if (mUserPaddingRight < 0) {
   9636                     mUserPaddingRight = mPaddingRight;
   9637                 }
   9638         }
   9639 
   9640         mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
   9641 
   9642         recomputePadding();
   9643     }
   9644 
   9645     /**
   9646      * Return true if layout direction resolution can be done
   9647      *
   9648      * @hide
   9649      */
   9650     protected boolean canResolveLayoutDirection() {
   9651         switch (getLayoutDirection()) {
   9652             case LAYOUT_DIRECTION_INHERIT:
   9653                 return (mParent != null);
   9654             default:
   9655                 return true;
   9656         }
   9657     }
   9658 
   9659     /**
   9660      * Reset the resolved layout direction.
   9661      *
   9662      * Subclasses need to override this method to clear cached information that depends on the
   9663      * resolved layout direction, or to inform child views that inherit their layout direction.
   9664      * Overrides must also call the superclass implementation at the start of their implementation.
   9665      *
   9666      * @hide
   9667      */
   9668     protected void resetResolvedLayoutDirection() {
   9669         // Reset the current View resolution
   9670         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
   9671     }
   9672 
   9673     /**
   9674      * Check if a Locale is corresponding to a RTL script.
   9675      *
   9676      * @param locale Locale to check
   9677      * @return true if a Locale is corresponding to a RTL script.
   9678      *
   9679      * @hide
   9680      */
   9681     protected static boolean isLayoutDirectionRtl(Locale locale) {
   9682         return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE ==
   9683                 LocaleUtil.getLayoutDirectionFromLocale(locale));
   9684     }
   9685 
   9686     /**
   9687      * This is called when the view is detached from a window.  At this point it
   9688      * no longer has a surface for drawing.
   9689      *
   9690      * @see #onAttachedToWindow()
   9691      */
   9692     protected void onDetachedFromWindow() {
   9693         mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
   9694 
   9695         removeUnsetPressCallback();
   9696         removeLongPressCallback();
   9697         removePerformClickCallback();
   9698         removeSendViewScrolledAccessibilityEventCallback();
   9699 
   9700         destroyDrawingCache();
   9701 
   9702         destroyLayer();
   9703 
   9704         if (mDisplayList != null) {
   9705             mDisplayList.invalidate();
   9706         }
   9707 
   9708         if (mAttachInfo != null) {
   9709             mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
   9710         }
   9711 
   9712         mCurrentAnimation = null;
   9713 
   9714         resetResolvedLayoutDirection();
   9715         resetResolvedTextDirection();
   9716     }
   9717 
   9718     /**
   9719      * @return The number of times this view has been attached to a window
   9720      */
   9721     protected int getWindowAttachCount() {
   9722         return mWindowAttachCount;
   9723     }
   9724 
   9725     /**
   9726      * Retrieve a unique token identifying the window this view is attached to.
   9727      * @return Return the window's token for use in
   9728      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
   9729      */
   9730     public IBinder getWindowToken() {
   9731         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
   9732     }
   9733 
   9734     /**
   9735      * Retrieve a unique token identifying the top-level "real" window of
   9736      * the window that this view is attached to.  That is, this is like
   9737      * {@link #getWindowToken}, except if the window this view in is a panel
   9738      * window (attached to another containing window), then the token of
   9739      * the containing window is returned instead.
   9740      *
   9741      * @return Returns the associated window token, either
   9742      * {@link #getWindowToken()} or the containing window's token.
   9743      */
   9744     public IBinder getApplicationWindowToken() {
   9745         AttachInfo ai = mAttachInfo;
   9746         if (ai != null) {
   9747             IBinder appWindowToken = ai.mPanelParentWindowToken;
   9748             if (appWindowToken == null) {
   9749                 appWindowToken = ai.mWindowToken;
   9750             }
   9751             return appWindowToken;
   9752         }
   9753         return null;
   9754     }
   9755 
   9756     /**
   9757      * Retrieve private session object this view hierarchy is using to
   9758      * communicate with the window manager.
   9759      * @return the session object to communicate with the window manager
   9760      */
   9761     /*package*/ IWindowSession getWindowSession() {
   9762         return mAttachInfo != null ? mAttachInfo.mSession : null;
   9763     }
   9764 
   9765     /**
   9766      * @param info the {@link android.view.View.AttachInfo} to associated with
   9767      *        this view
   9768      */
   9769     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
   9770         //System.out.println("Attached! " + this);
   9771         mAttachInfo = info;
   9772         mWindowAttachCount++;
   9773         // We will need to evaluate the drawable state at least once.
   9774         mPrivateFlags |= DRAWABLE_STATE_DIRTY;
   9775         if (mFloatingTreeObserver != null) {
   9776             info.mTreeObserver.merge(mFloatingTreeObserver);
   9777             mFloatingTreeObserver = null;
   9778         }
   9779         if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
   9780             mAttachInfo.mScrollContainers.add(this);
   9781             mPrivateFlags |= SCROLL_CONTAINER_ADDED;
   9782         }
   9783         performCollectViewAttributes(visibility);
   9784         onAttachedToWindow();
   9785 
   9786         ListenerInfo li = mListenerInfo;
   9787         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   9788                 li != null ? li.mOnAttachStateChangeListeners : null;
   9789         if (listeners != null && listeners.size() > 0) {
   9790             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   9791             // perform the dispatching. The iterator is a safe guard against listeners that
   9792             // could mutate the list by calling the various add/remove methods. This prevents
   9793             // the array from being modified while we iterate it.
   9794             for (OnAttachStateChangeListener listener : listeners) {
   9795                 listener.onViewAttachedToWindow(this);
   9796             }
   9797         }
   9798 
   9799         int vis = info.mWindowVisibility;
   9800         if (vis != GONE) {
   9801             onWindowVisibilityChanged(vis);
   9802         }
   9803         if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
   9804             // If nobody has evaluated the drawable state yet, then do it now.
   9805             refreshDrawableState();
   9806         }
   9807     }
   9808 
   9809     void dispatchDetachedFromWindow() {
   9810         AttachInfo info = mAttachInfo;
   9811         if (info != null) {
   9812             int vis = info.mWindowVisibility;
   9813             if (vis != GONE) {
   9814                 onWindowVisibilityChanged(GONE);
   9815             }
   9816         }
   9817 
   9818         onDetachedFromWindow();
   9819 
   9820         ListenerInfo li = mListenerInfo;
   9821         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   9822                 li != null ? li.mOnAttachStateChangeListeners : null;
   9823         if (listeners != null && listeners.size() > 0) {
   9824             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   9825             // perform the dispatching. The iterator is a safe guard against listeners that
   9826             // could mutate the list by calling the various add/remove methods. This prevents
   9827             // the array from being modified while we iterate it.
   9828             for (OnAttachStateChangeListener listener : listeners) {
   9829                 listener.onViewDetachedFromWindow(this);
   9830             }
   9831         }
   9832 
   9833         if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
   9834             mAttachInfo.mScrollContainers.remove(this);
   9835             mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
   9836         }
   9837 
   9838         mAttachInfo = null;
   9839     }
   9840 
   9841     /**
   9842      * Store this view hierarchy's frozen state into the given container.
   9843      *
   9844      * @param container The SparseArray in which to save the view's state.
   9845      *
   9846      * @see #restoreHierarchyState(android.util.SparseArray)
   9847      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   9848      * @see #onSaveInstanceState()
   9849      */
   9850     public void saveHierarchyState(SparseArray<Parcelable> container) {
   9851         dispatchSaveInstanceState(container);
   9852     }
   9853 
   9854     /**
   9855      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
   9856      * this view and its children. May be overridden to modify how freezing happens to a
   9857      * view's children; for example, some views may want to not store state for their children.
   9858      *
   9859      * @param container The SparseArray in which to save the view's state.
   9860      *
   9861      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   9862      * @see #saveHierarchyState(android.util.SparseArray)
   9863      * @see #onSaveInstanceState()
   9864      */
   9865     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
   9866         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
   9867             mPrivateFlags &= ~SAVE_STATE_CALLED;
   9868             Parcelable state = onSaveInstanceState();
   9869             if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
   9870                 throw new IllegalStateException(
   9871                         "Derived class did not call super.onSaveInstanceState()");
   9872             }
   9873             if (state != null) {
   9874                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
   9875                 // + ": " + state);
   9876                 container.put(mID, state);
   9877             }
   9878         }
   9879     }
   9880 
   9881     /**
   9882      * Hook allowing a view to generate a representation of its internal state
   9883      * that can later be used to create a new instance with that same state.
   9884      * This state should only contain information that is not persistent or can
   9885      * not be reconstructed later. For example, you will never store your
   9886      * current position on screen because that will be computed again when a
   9887      * new instance of the view is placed in its view hierarchy.
   9888      * <p>
   9889      * Some examples of things you may store here: the current cursor position
   9890      * in a text view (but usually not the text itself since that is stored in a
   9891      * content provider or other persistent storage), the currently selected
   9892      * item in a list view.
   9893      *
   9894      * @return Returns a Parcelable object containing the view's current dynamic
   9895      *         state, or null if there is nothing interesting to save. The
   9896      *         default implementation returns null.
   9897      * @see #onRestoreInstanceState(android.os.Parcelable)
   9898      * @see #saveHierarchyState(android.util.SparseArray)
   9899      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   9900      * @see #setSaveEnabled(boolean)
   9901      */
   9902     protected Parcelable onSaveInstanceState() {
   9903         mPrivateFlags |= SAVE_STATE_CALLED;
   9904         return BaseSavedState.EMPTY_STATE;
   9905     }
   9906 
   9907     /**
   9908      * Restore this view hierarchy's frozen state from the given container.
   9909      *
   9910      * @param container The SparseArray which holds previously frozen states.
   9911      *
   9912      * @see #saveHierarchyState(android.util.SparseArray)
   9913      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   9914      * @see #onRestoreInstanceState(android.os.Parcelable)
   9915      */
   9916     public void restoreHierarchyState(SparseArray<Parcelable> container) {
   9917         dispatchRestoreInstanceState(container);
   9918     }
   9919 
   9920     /**
   9921      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
   9922      * state for this view and its children. May be overridden to modify how restoring
   9923      * happens to a view's children; for example, some views may want to not store state
   9924      * for their children.
   9925      *
   9926      * @param container The SparseArray which holds previously saved state.
   9927      *
   9928      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   9929      * @see #restoreHierarchyState(android.util.SparseArray)
   9930      * @see #onRestoreInstanceState(android.os.Parcelable)
   9931      */
   9932     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
   9933         if (mID != NO_ID) {
   9934             Parcelable state = container.get(mID);
   9935             if (state != null) {
   9936                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
   9937                 // + ": " + state);
   9938                 mPrivateFlags &= ~SAVE_STATE_CALLED;
   9939                 onRestoreInstanceState(state);
   9940                 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
   9941                     throw new IllegalStateException(
   9942                             "Derived class did not call super.onRestoreInstanceState()");
   9943                 }
   9944             }
   9945         }
   9946     }
   9947 
   9948     /**
   9949      * Hook allowing a view to re-apply a representation of its internal state that had previously
   9950      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
   9951      * null state.
   9952      *
   9953      * @param state The frozen state that had previously been returned by
   9954      *        {@link #onSaveInstanceState}.
   9955      *
   9956      * @see #onSaveInstanceState()
   9957      * @see #restoreHierarchyState(android.util.SparseArray)
   9958      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   9959      */
   9960     protected void onRestoreInstanceState(Parcelable state) {
   9961         mPrivateFlags |= SAVE_STATE_CALLED;
   9962         if (state != BaseSavedState.EMPTY_STATE && state != null) {
   9963             throw new IllegalArgumentException("Wrong state class, expecting View State but "
   9964                     + "received " + state.getClass().toString() + " instead. This usually happens "
   9965                     + "when two views of different type have the same id in the same hierarchy. "
   9966                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
   9967                     + "other views do not use the same id.");
   9968         }
   9969     }
   9970 
   9971     /**
   9972      * <p>Return the time at which the drawing of the view hierarchy started.</p>
   9973      *
   9974      * @return the drawing start time in milliseconds
   9975      */
   9976     public long getDrawingTime() {
   9977         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
   9978     }
   9979 
   9980     /**
   9981      * <p>Enables or disables the duplication of the parent's state into this view. When
   9982      * duplication is enabled, this view gets its drawable state from its parent rather
   9983      * than from its own internal properties.</p>
   9984      *
   9985      * <p>Note: in the current implementation, setting this property to true after the
   9986      * view was added to a ViewGroup might have no effect at all. This property should
   9987      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
   9988      *
   9989      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
   9990      * property is enabled, an exception will be thrown.</p>
   9991      *
   9992      * <p>Note: if the child view uses and updates additionnal states which are unknown to the
   9993      * parent, these states should not be affected by this method.</p>
   9994      *
   9995      * @param enabled True to enable duplication of the parent's drawable state, false
   9996      *                to disable it.
   9997      *
   9998      * @see #getDrawableState()
   9999      * @see #isDuplicateParentStateEnabled()
   10000      */
   10001     public void setDuplicateParentStateEnabled(boolean enabled) {
   10002         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
   10003     }
   10004 
   10005     /**
   10006      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
   10007      *
   10008      * @return True if this view's drawable state is duplicated from the parent,
   10009      *         false otherwise
   10010      *
   10011      * @see #getDrawableState()
   10012      * @see #setDuplicateParentStateEnabled(boolean)
   10013      */
   10014     public boolean isDuplicateParentStateEnabled() {
   10015         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
   10016     }
   10017 
   10018     /**
   10019      * <p>Specifies the type of layer backing this view. The layer can be
   10020      * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
   10021      * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
   10022      *
   10023      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   10024      * instance that controls how the layer is composed on screen. The following
   10025      * properties of the paint are taken into account when composing the layer:</p>
   10026      * <ul>
   10027      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   10028      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   10029      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   10030      * </ul>
   10031      *
   10032      * <p>If this view has an alpha value set to < 1.0 by calling
   10033      * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
   10034      * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
   10035      * equivalent to setting a hardware layer on this view and providing a paint with
   10036      * the desired alpha value.<p>
   10037      *
   10038      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
   10039      * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
   10040      * for more information on when and how to use layers.</p>
   10041      *
   10042      * @param layerType The ype of layer to use with this view, must be one of
   10043      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   10044      *        {@link #LAYER_TYPE_HARDWARE}
   10045      * @param paint The paint used to compose the layer. This argument is optional
   10046      *        and can be null. It is ignored when the layer type is
   10047      *        {@link #LAYER_TYPE_NONE}
   10048      *
   10049      * @see #getLayerType()
   10050      * @see #LAYER_TYPE_NONE
   10051      * @see #LAYER_TYPE_SOFTWARE
   10052      * @see #LAYER_TYPE_HARDWARE
   10053      * @see #setAlpha(float)
   10054      *
   10055      * @attr ref android.R.styleable#View_layerType
   10056      */
   10057     public void setLayerType(int layerType, Paint paint) {
   10058         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
   10059             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
   10060                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
   10061         }
   10062 
   10063         if (layerType == mLayerType) {
   10064             if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
   10065                 mLayerPaint = paint == null ? new Paint() : paint;
   10066                 invalidateParentCaches();
   10067                 invalidate(true);
   10068             }
   10069             return;
   10070         }
   10071 
   10072         // Destroy any previous software drawing cache if needed
   10073         switch (mLayerType) {
   10074             case LAYER_TYPE_HARDWARE:
   10075                 destroyLayer();
   10076                 // fall through - non-accelerated views may use software layer mechanism instead
   10077             case LAYER_TYPE_SOFTWARE:
   10078                 destroyDrawingCache();
   10079                 break;
   10080             default:
   10081                 break;
   10082         }
   10083 
   10084         mLayerType = layerType;
   10085         final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
   10086         mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
   10087         mLocalDirtyRect = layerDisabled ? null : new Rect();
   10088 
   10089         invalidateParentCaches();
   10090         invalidate(true);
   10091     }
   10092 
   10093     /**
   10094      * Indicates whether this view has a static layer. A view with layer type
   10095      * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
   10096      * dynamic.
   10097      */
   10098     boolean hasStaticLayer() {
   10099         return mLayerType == LAYER_TYPE_NONE;
   10100     }
   10101 
   10102     /**
   10103      * Indicates what type of layer is currently associated with this view. By default
   10104      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
   10105      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
   10106      * for more information on the different types of layers.
   10107      *
   10108      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   10109      *         {@link #LAYER_TYPE_HARDWARE}
   10110      *
   10111      * @see #setLayerType(int, android.graphics.Paint)
   10112      * @see #buildLayer()
   10113      * @see #LAYER_TYPE_NONE
   10114      * @see #LAYER_TYPE_SOFTWARE
   10115      * @see #LAYER_TYPE_HARDWARE
   10116      */
   10117     public int getLayerType() {
   10118         return mLayerType;
   10119     }
   10120 
   10121     /**
   10122      * Forces this view's layer to be created and this view to be rendered
   10123      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
   10124      * invoking this method will have no effect.
   10125      *
   10126      * This method can for instance be used to render a view into its layer before
   10127      * starting an animation. If this view is complex, rendering into the layer
   10128      * before starting the animation will avoid skipping frames.
   10129      *
   10130      * @throws IllegalStateException If this view is not attached to a window
   10131      *
   10132      * @see #setLayerType(int, android.graphics.Paint)
   10133      */
   10134     public void buildLayer() {
   10135         if (mLayerType == LAYER_TYPE_NONE) return;
   10136 
   10137         if (mAttachInfo == null) {
   10138             throw new IllegalStateException("This view must be attached to a window first");
   10139         }
   10140 
   10141         switch (mLayerType) {
   10142             case LAYER_TYPE_HARDWARE:
   10143                 if (mAttachInfo.mHardwareRenderer != null &&
   10144                         mAttachInfo.mHardwareRenderer.isEnabled() &&
   10145                         mAttachInfo.mHardwareRenderer.validate()) {
   10146                     getHardwareLayer();
   10147                 }
   10148                 break;
   10149             case LAYER_TYPE_SOFTWARE:
   10150                 buildDrawingCache(true);
   10151                 break;
   10152         }
   10153     }
   10154 
   10155     /**
   10156      * <p>Returns a hardware layer that can be used to draw this view again
   10157      * without executing its draw method.</p>
   10158      *
   10159      * @return A HardwareLayer ready to render, or null if an error occurred.
   10160      */
   10161     HardwareLayer getHardwareLayer() {
   10162         if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
   10163                 !mAttachInfo.mHardwareRenderer.isEnabled()) {
   10164             return null;
   10165         }
   10166 
   10167         final int width = mRight - mLeft;
   10168         final int height = mBottom - mTop;
   10169 
   10170         if (width == 0 || height == 0) {
   10171             return null;
   10172         }
   10173 
   10174         if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
   10175             if (mHardwareLayer == null) {
   10176                 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
   10177                         width, height, isOpaque());
   10178                 mLocalDirtyRect.setEmpty();
   10179             } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
   10180                 mHardwareLayer.resize(width, height);
   10181                 mLocalDirtyRect.setEmpty();
   10182             }
   10183 
   10184             // The layer is not valid if the underlying GPU resources cannot be allocated
   10185             if (!mHardwareLayer.isValid()) {
   10186                 return null;
   10187             }
   10188 
   10189             HardwareCanvas currentCanvas = mAttachInfo.mHardwareCanvas;
   10190             final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
   10191 
   10192             // Make sure all the GPU resources have been properly allocated
   10193             if (canvas == null) {
   10194                 mHardwareLayer.end(currentCanvas);
   10195                 return null;
   10196             }
   10197 
   10198             mAttachInfo.mHardwareCanvas = canvas;
   10199             try {
   10200                 canvas.setViewport(width, height);
   10201                 canvas.onPreDraw(mLocalDirtyRect);
   10202                 mLocalDirtyRect.setEmpty();
   10203 
   10204                 final int restoreCount = canvas.save();
   10205 
   10206                 computeScroll();
   10207                 canvas.translate(-mScrollX, -mScrollY);
   10208 
   10209                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
   10210 
   10211                 // Fast path for layouts with no backgrounds
   10212                 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
   10213                     mPrivateFlags &= ~DIRTY_MASK;
   10214                     dispatchDraw(canvas);
   10215                 } else {
   10216                     draw(canvas);
   10217                 }
   10218 
   10219                 canvas.restoreToCount(restoreCount);
   10220             } finally {
   10221                 canvas.onPostDraw();
   10222                 mHardwareLayer.end(currentCanvas);
   10223                 mAttachInfo.mHardwareCanvas = currentCanvas;
   10224             }
   10225         }
   10226 
   10227         return mHardwareLayer;
   10228     }
   10229 
   10230     /**
   10231      * Destroys this View's hardware layer if possible.
   10232      *
   10233      * @return True if the layer was destroyed, false otherwise.
   10234      *
   10235      * @see #setLayerType(int, android.graphics.Paint)
   10236      * @see #LAYER_TYPE_HARDWARE
   10237      */
   10238     boolean destroyLayer() {
   10239         if (mHardwareLayer != null) {
   10240             mHardwareLayer.destroy();
   10241             mHardwareLayer = null;
   10242 
   10243             invalidate(true);
   10244             invalidateParentCaches();
   10245 
   10246             return true;
   10247         }
   10248         return false;
   10249     }
   10250 
   10251     /**
   10252      * Destroys all hardware rendering resources. This method is invoked
   10253      * when the system needs to reclaim resources. Upon execution of this
   10254      * method, you should free any OpenGL resources created by the view.
   10255      *
   10256      * Note: you <strong>must</strong> call
   10257      * <code>super.destroyHardwareResources()</code> when overriding
   10258      * this method.
   10259      *
   10260      * @hide
   10261      */
   10262     protected void destroyHardwareResources() {
   10263         destroyLayer();
   10264     }
   10265 
   10266     /**
   10267      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
   10268      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
   10269      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
   10270      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
   10271      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
   10272      * null.</p>
   10273      *
   10274      * <p>Enabling the drawing cache is similar to
   10275      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
   10276      * acceleration is turned off. When hardware acceleration is turned on, enabling the
   10277      * drawing cache has no effect on rendering because the system uses a different mechanism
   10278      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
   10279      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
   10280      * for information on how to enable software and hardware layers.</p>
   10281      *
   10282      * <p>This API can be used to manually generate
   10283      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
   10284      * {@link #getDrawingCache()}.</p>
   10285      *
   10286      * @param enabled true to enable the drawing cache, false otherwise
   10287      *
   10288      * @see #isDrawingCacheEnabled()
   10289      * @see #getDrawingCache()
   10290      * @see #buildDrawingCache()
   10291      * @see #setLayerType(int, android.graphics.Paint)
   10292      */
   10293     public void setDrawingCacheEnabled(boolean enabled) {
   10294         mCachingFailed = false;
   10295         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
   10296     }
   10297 
   10298     /**
   10299      * <p>Indicates whether the drawing cache is enabled for this view.</p>
   10300      *
   10301      * @return true if the drawing cache is enabled
   10302      *
   10303      * @see #setDrawingCacheEnabled(boolean)
   10304      * @see #getDrawingCache()
   10305      */
   10306     @ViewDebug.ExportedProperty(category = "drawing")
   10307     public boolean isDrawingCacheEnabled() {
   10308         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
   10309     }
   10310 
   10311     /**
   10312      * Debugging utility which recursively outputs the dirty state of a view and its
   10313      * descendants.
   10314      *
   10315      * @hide
   10316      */
   10317     @SuppressWarnings({"UnusedDeclaration"})
   10318     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
   10319         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
   10320                 ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
   10321                 (mPrivateFlags & View.DRAWING_CACHE_VALID) +
   10322                 ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
   10323         if (clear) {
   10324             mPrivateFlags &= clearMask;
   10325         }
   10326         if (this instanceof ViewGroup) {
   10327             ViewGroup parent = (ViewGroup) this;
   10328             final int count = parent.getChildCount();
   10329             for (int i = 0; i < count; i++) {
   10330                 final View child = parent.getChildAt(i);
   10331                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
   10332             }
   10333         }
   10334     }
   10335 
   10336     /**
   10337      * This method is used by ViewGroup to cause its children to restore or recreate their
   10338      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
   10339      * to recreate its own display list, which would happen if it went through the normal
   10340      * draw/dispatchDraw mechanisms.
   10341      *
   10342      * @hide
   10343      */
   10344     protected void dispatchGetDisplayList() {}
   10345 
   10346     /**
   10347      * A view that is not attached or hardware accelerated cannot create a display list.
   10348      * This method checks these conditions and returns the appropriate result.
   10349      *
   10350      * @return true if view has the ability to create a display list, false otherwise.
   10351      *
   10352      * @hide
   10353      */
   10354     public boolean canHaveDisplayList() {
   10355         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
   10356     }
   10357 
   10358     /**
   10359      * <p>Returns a display list that can be used to draw this view again
   10360      * without executing its draw method.</p>
   10361      *
   10362      * @return A DisplayList ready to replay, or null if caching is not enabled.
   10363      *
   10364      * @hide
   10365      */
   10366     public DisplayList getDisplayList() {
   10367         if (!canHaveDisplayList()) {
   10368             return null;
   10369         }
   10370 
   10371         if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
   10372                 mDisplayList == null || !mDisplayList.isValid() ||
   10373                 mRecreateDisplayList)) {
   10374             // Don't need to recreate the display list, just need to tell our
   10375             // children to restore/recreate theirs
   10376             if (mDisplayList != null && mDisplayList.isValid() &&
   10377                     !mRecreateDisplayList) {
   10378                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
   10379                 mPrivateFlags &= ~DIRTY_MASK;
   10380                 dispatchGetDisplayList();
   10381 
   10382                 return mDisplayList;
   10383             }
   10384 
   10385             // If we got here, we're recreating it. Mark it as such to ensure that
   10386             // we copy in child display lists into ours in drawChild()
   10387             mRecreateDisplayList = true;
   10388             if (mDisplayList == null) {
   10389                 mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
   10390                 // If we're creating a new display list, make sure our parent gets invalidated
   10391                 // since they will need to recreate their display list to account for this
   10392                 // new child display list.
   10393                 invalidateParentCaches();
   10394             }
   10395 
   10396             final HardwareCanvas canvas = mDisplayList.start();
   10397             int restoreCount = 0;
   10398             try {
   10399                 int width = mRight - mLeft;
   10400                 int height = mBottom - mTop;
   10401 
   10402                 canvas.setViewport(width, height);
   10403                 // The dirty rect should always be null for a display list
   10404                 canvas.onPreDraw(null);
   10405 
   10406                 computeScroll();
   10407 
   10408                 restoreCount = canvas.save();
   10409                 canvas.translate(-mScrollX, -mScrollY);
   10410                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
   10411                 mPrivateFlags &= ~DIRTY_MASK;
   10412 
   10413                 // Fast path for layouts with no backgrounds
   10414                 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
   10415                     dispatchDraw(canvas);
   10416                 } else {
   10417                     draw(canvas);
   10418                 }
   10419             } finally {
   10420                 canvas.restoreToCount(restoreCount);
   10421                 canvas.onPostDraw();
   10422 
   10423                 mDisplayList.end();
   10424             }
   10425         } else {
   10426             mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
   10427             mPrivateFlags &= ~DIRTY_MASK;
   10428         }
   10429 
   10430         return mDisplayList;
   10431     }
   10432 
   10433     /**
   10434      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
   10435      *
   10436      * @return A non-scaled bitmap representing this view or null if cache is disabled.
   10437      *
   10438      * @see #getDrawingCache(boolean)
   10439      */
   10440     public Bitmap getDrawingCache() {
   10441         return getDrawingCache(false);
   10442     }
   10443 
   10444     /**
   10445      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
   10446      * is null when caching is disabled. If caching is enabled and the cache is not ready,
   10447      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
   10448      * draw from the cache when the cache is enabled. To benefit from the cache, you must
   10449      * request the drawing cache by calling this method and draw it on screen if the
   10450      * returned bitmap is not null.</p>
   10451      *
   10452      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   10453      * this method will create a bitmap of the same size as this view. Because this bitmap
   10454      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   10455      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   10456      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   10457      * size than the view. This implies that your application must be able to handle this
   10458      * size.</p>
   10459      *
   10460      * @param autoScale Indicates whether the generated bitmap should be scaled based on
   10461      *        the current density of the screen when the application is in compatibility
   10462      *        mode.
   10463      *
   10464      * @return A bitmap representing this view or null if cache is disabled.
   10465      *
   10466      * @see #setDrawingCacheEnabled(boolean)
   10467      * @see #isDrawingCacheEnabled()
   10468      * @see #buildDrawingCache(boolean)
   10469      * @see #destroyDrawingCache()
   10470      */
   10471     public Bitmap getDrawingCache(boolean autoScale) {
   10472         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
   10473             return null;
   10474         }
   10475         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
   10476             buildDrawingCache(autoScale);
   10477         }
   10478         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
   10479     }
   10480 
   10481     /**
   10482      * <p>Frees the resources used by the drawing cache. If you call
   10483      * {@link #buildDrawingCache()} manually without calling
   10484      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   10485      * should cleanup the cache with this method afterwards.</p>
   10486      *
   10487      * @see #setDrawingCacheEnabled(boolean)
   10488      * @see #buildDrawingCache()
   10489      * @see #getDrawingCache()
   10490      */
   10491     public void destroyDrawingCache() {
   10492         if (mDrawingCache != null) {
   10493             mDrawingCache.recycle();
   10494             mDrawingCache = null;
   10495         }
   10496         if (mUnscaledDrawingCache != null) {
   10497             mUnscaledDrawingCache.recycle();
   10498             mUnscaledDrawingCache = null;
   10499         }
   10500     }
   10501 
   10502     /**
   10503      * Setting a solid background color for the drawing cache's bitmaps will improve
   10504      * performance and memory usage. Note, though that this should only be used if this
   10505      * view will always be drawn on top of a solid color.
   10506      *
   10507      * @param color The background color to use for the drawing cache's bitmap
   10508      *
   10509      * @see #setDrawingCacheEnabled(boolean)
   10510      * @see #buildDrawingCache()
   10511      * @see #getDrawingCache()
   10512      */
   10513     public void setDrawingCacheBackgroundColor(int color) {
   10514         if (color != mDrawingCacheBackgroundColor) {
   10515             mDrawingCacheBackgroundColor = color;
   10516             mPrivateFlags &= ~DRAWING_CACHE_VALID;
   10517         }
   10518     }
   10519 
   10520     /**
   10521      * @see #setDrawingCacheBackgroundColor(int)
   10522      *
   10523      * @return The background color to used for the drawing cache's bitmap
   10524      */
   10525     public int getDrawingCacheBackgroundColor() {
   10526         return mDrawingCacheBackgroundColor;
   10527     }
   10528 
   10529     /**
   10530      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
   10531      *
   10532      * @see #buildDrawingCache(boolean)
   10533      */
   10534     public void buildDrawingCache() {
   10535         buildDrawingCache(false);
   10536     }
   10537 
   10538     /**
   10539      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
   10540      *
   10541      * <p>If you call {@link #buildDrawingCache()} manually without calling
   10542      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   10543      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
   10544      *
   10545      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   10546      * this method will create a bitmap of the same size as this view. Because this bitmap
   10547      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   10548      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   10549      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   10550      * size than the view. This implies that your application must be able to handle this
   10551      * size.</p>
   10552      *
   10553      * <p>You should avoid calling this method when hardware acceleration is enabled. If
   10554      * you do not need the drawing cache bitmap, calling this method will increase memory
   10555      * usage and cause the view to be rendered in software once, thus negatively impacting
   10556      * performance.</p>
   10557      *
   10558      * @see #getDrawingCache()
   10559      * @see #destroyDrawingCache()
   10560      */
   10561     public void buildDrawingCache(boolean autoScale) {
   10562         if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
   10563                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
   10564             mCachingFailed = false;
   10565 
   10566             if (ViewDebug.TRACE_HIERARCHY) {
   10567                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
   10568             }
   10569 
   10570             int width = mRight - mLeft;
   10571             int height = mBottom - mTop;
   10572 
   10573             final AttachInfo attachInfo = mAttachInfo;
   10574             final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
   10575 
   10576             if (autoScale && scalingRequired) {
   10577                 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
   10578                 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
   10579             }
   10580 
   10581             final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
   10582             final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
   10583             final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
   10584 
   10585             if (width <= 0 || height <= 0 ||
   10586                      // Projected bitmap size in bytes
   10587                     (width * height * (opaque && !use32BitCache ? 2 : 4) >
   10588                             ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
   10589                 destroyDrawingCache();
   10590                 mCachingFailed = true;
   10591                 return;
   10592             }
   10593 
   10594             boolean clear = true;
   10595             Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
   10596 
   10597             if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
   10598                 Bitmap.Config quality;
   10599                 if (!opaque) {
   10600                     // Never pick ARGB_4444 because it looks awful
   10601                     // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
   10602                     switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
   10603                         case DRAWING_CACHE_QUALITY_AUTO:
   10604                             quality = Bitmap.Config.ARGB_8888;
   10605                             break;
   10606                         case DRAWING_CACHE_QUALITY_LOW:
   10607                             quality = Bitmap.Config.ARGB_8888;
   10608                             break;
   10609                         case DRAWING_CACHE_QUALITY_HIGH:
   10610                             quality = Bitmap.Config.ARGB_8888;
   10611                             break;
   10612                         default:
   10613                             quality = Bitmap.Config.ARGB_8888;
   10614                             break;
   10615                     }
   10616                 } else {
   10617                     // Optimization for translucent windows
   10618                     // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
   10619                     quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
   10620                 }
   10621 
   10622                 // Try to cleanup memory
   10623                 if (bitmap != null) bitmap.recycle();
   10624 
   10625                 try {
   10626                     bitmap = Bitmap.createBitmap(width, height, quality);
   10627                     bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
   10628                     if (autoScale) {
   10629                         mDrawingCache = bitmap;
   10630                     } else {
   10631                         mUnscaledDrawingCache = bitmap;
   10632                     }
   10633                     if (opaque && use32BitCache) bitmap.setHasAlpha(false);
   10634                 } catch (OutOfMemoryError e) {
   10635                     // If there is not enough memory to create the bitmap cache, just
   10636                     // ignore the issue as bitmap caches are not required to draw the
   10637                     // view hierarchy
   10638                     if (autoScale) {
   10639                         mDrawingCache = null;
   10640                     } else {
   10641                         mUnscaledDrawingCache = null;
   10642                     }
   10643                     mCachingFailed = true;
   10644                     return;
   10645                 }
   10646 
   10647                 clear = drawingCacheBackgroundColor != 0;
   10648             }
   10649 
   10650             Canvas canvas;
   10651             if (attachInfo != null) {
   10652                 canvas = attachInfo.mCanvas;
   10653                 if (canvas == null) {
   10654                     canvas = new Canvas();
   10655                 }
   10656                 canvas.setBitmap(bitmap);
   10657                 // Temporarily clobber the cached Canvas in case one of our children
   10658                 // is also using a drawing cache. Without this, the children would
   10659                 // steal the canvas by attaching their own bitmap to it and bad, bad
   10660                 // thing would happen (invisible views, corrupted drawings, etc.)
   10661                 attachInfo.mCanvas = null;
   10662             } else {
   10663                 // This case should hopefully never or seldom happen
   10664                 canvas = new Canvas(bitmap);
   10665             }
   10666 
   10667             if (clear) {
   10668                 bitmap.eraseColor(drawingCacheBackgroundColor);
   10669             }
   10670 
   10671             computeScroll();
   10672             final int restoreCount = canvas.save();
   10673 
   10674             if (autoScale && scalingRequired) {
   10675                 final float scale = attachInfo.mApplicationScale;
   10676                 canvas.scale(scale, scale);
   10677             }
   10678 
   10679             canvas.translate(-mScrollX, -mScrollY);
   10680 
   10681             mPrivateFlags |= DRAWN;
   10682             if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
   10683                     mLayerType != LAYER_TYPE_NONE) {
   10684                 mPrivateFlags |= DRAWING_CACHE_VALID;
   10685             }
   10686 
   10687             // Fast path for layouts with no backgrounds
   10688             if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
   10689                 if (ViewDebug.TRACE_HIERARCHY) {
   10690                     ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
   10691                 }
   10692                 mPrivateFlags &= ~DIRTY_MASK;
   10693                 dispatchDraw(canvas);
   10694             } else {
   10695                 draw(canvas);
   10696             }
   10697 
   10698             canvas.restoreToCount(restoreCount);
   10699             canvas.setBitmap(null);
   10700 
   10701             if (attachInfo != null) {
   10702                 // Restore the cached Canvas for our siblings
   10703                 attachInfo.mCanvas = canvas;
   10704             }
   10705         }
   10706     }
   10707 
   10708     /**
   10709      * Create a snapshot of the view into a bitmap.  We should probably make
   10710      * some form of this public, but should think about the API.
   10711      */
   10712     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
   10713         int width = mRight - mLeft;
   10714         int height = mBottom - mTop;
   10715 
   10716         final AttachInfo attachInfo = mAttachInfo;
   10717         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
   10718         width = (int) ((width * scale) + 0.5f);
   10719         height = (int) ((height * scale) + 0.5f);
   10720 
   10721         Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
   10722         if (bitmap == null) {
   10723             throw new OutOfMemoryError();
   10724         }
   10725 
   10726         Resources resources = getResources();
   10727         if (resources != null) {
   10728             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
   10729         }
   10730 
   10731         Canvas canvas;
   10732         if (attachInfo != null) {
   10733             canvas = attachInfo.mCanvas;
   10734             if (canvas == null) {
   10735                 canvas = new Canvas();
   10736             }
   10737             canvas.setBitmap(bitmap);
   10738             // Temporarily clobber the cached Canvas in case one of our children
   10739             // is also using a drawing cache. Without this, the children would
   10740             // steal the canvas by attaching their own bitmap to it and bad, bad
   10741             // things would happen (invisible views, corrupted drawings, etc.)
   10742             attachInfo.mCanvas = null;
   10743         } else {
   10744             // This case should hopefully never or seldom happen
   10745             canvas = new Canvas(bitmap);
   10746         }
   10747 
   10748         if ((backgroundColor & 0xff000000) != 0) {
   10749             bitmap.eraseColor(backgroundColor);
   10750         }
   10751 
   10752         computeScroll();
   10753         final int restoreCount = canvas.save();
   10754         canvas.scale(scale, scale);
   10755         canvas.translate(-mScrollX, -mScrollY);
   10756 
   10757         // Temporarily remove the dirty mask
   10758         int flags = mPrivateFlags;
   10759         mPrivateFlags &= ~DIRTY_MASK;
   10760 
   10761         // Fast path for layouts with no backgrounds
   10762         if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
   10763             dispatchDraw(canvas);
   10764         } else {
   10765             draw(canvas);
   10766         }
   10767 
   10768         mPrivateFlags = flags;
   10769 
   10770         canvas.restoreToCount(restoreCount);
   10771         canvas.setBitmap(null);
   10772 
   10773         if (attachInfo != null) {
   10774             // Restore the cached Canvas for our siblings
   10775             attachInfo.mCanvas = canvas;
   10776         }
   10777 
   10778         return bitmap;
   10779     }
   10780 
   10781     /**
   10782      * Indicates whether this View is currently in edit mode. A View is usually
   10783      * in edit mode when displayed within a developer tool. For instance, if
   10784      * this View is being drawn by a visual user interface builder, this method
   10785      * should return true.
   10786      *
   10787      * Subclasses should check the return value of this method to provide
   10788      * different behaviors if their normal behavior might interfere with the
   10789      * host environment. For instance: the class spawns a thread in its
   10790      * constructor, the drawing code relies on device-specific features, etc.
   10791      *
   10792      * This method is usually checked in the drawing code of custom widgets.
   10793      *
   10794      * @return True if this View is in edit mode, false otherwise.
   10795      */
   10796     public boolean isInEditMode() {
   10797         return false;
   10798     }
   10799 
   10800     /**
   10801      * If the View draws content inside its padding and enables fading edges,
   10802      * it needs to support padding offsets. Padding offsets are added to the
   10803      * fading edges to extend the length of the fade so that it covers pixels
   10804      * drawn inside the padding.
   10805      *
   10806      * Subclasses of this class should override this method if they need
   10807      * to draw content inside the padding.
   10808      *
   10809      * @return True if padding offset must be applied, false otherwise.
   10810      *
   10811      * @see #getLeftPaddingOffset()
   10812      * @see #getRightPaddingOffset()
   10813      * @see #getTopPaddingOffset()
   10814      * @see #getBottomPaddingOffset()
   10815      *
   10816      * @since CURRENT
   10817      */
   10818     protected boolean isPaddingOffsetRequired() {
   10819         return false;
   10820     }
   10821 
   10822     /**
   10823      * Amount by which to extend the left fading region. Called only when
   10824      * {@link #isPaddingOffsetRequired()} returns true.
   10825      *
   10826      * @return The left padding offset in pixels.
   10827      *
   10828      * @see #isPaddingOffsetRequired()
   10829      *
   10830      * @since CURRENT
   10831      */
   10832     protected int getLeftPaddingOffset() {
   10833         return 0;
   10834     }
   10835 
   10836     /**
   10837      * Amount by which to extend the right fading region. Called only when
   10838      * {@link #isPaddingOffsetRequired()} returns true.
   10839      *
   10840      * @return The right padding offset in pixels.
   10841      *
   10842      * @see #isPaddingOffsetRequired()
   10843      *
   10844      * @since CURRENT
   10845      */
   10846     protected int getRightPaddingOffset() {
   10847         return 0;
   10848     }
   10849 
   10850     /**
   10851      * Amount by which to extend the top fading region. Called only when
   10852      * {@link #isPaddingOffsetRequired()} returns true.
   10853      *
   10854      * @return The top padding offset in pixels.
   10855      *
   10856      * @see #isPaddingOffsetRequired()
   10857      *
   10858      * @since CURRENT
   10859      */
   10860     protected int getTopPaddingOffset() {
   10861         return 0;
   10862     }
   10863 
   10864     /**
   10865      * Amount by which to extend the bottom fading region. Called only when
   10866      * {@link #isPaddingOffsetRequired()} returns true.
   10867      *
   10868      * @return The bottom padding offset in pixels.
   10869      *
   10870      * @see #isPaddingOffsetRequired()
   10871      *
   10872      * @since CURRENT
   10873      */
   10874     protected int getBottomPaddingOffset() {
   10875         return 0;
   10876     }
   10877 
   10878     /**
   10879      * @hide
   10880      * @param offsetRequired
   10881      */
   10882     protected int getFadeTop(boolean offsetRequired) {
   10883         int top = mPaddingTop;
   10884         if (offsetRequired) top += getTopPaddingOffset();
   10885         return top;
   10886     }
   10887 
   10888     /**
   10889      * @hide
   10890      * @param offsetRequired
   10891      */
   10892     protected int getFadeHeight(boolean offsetRequired) {
   10893         int padding = mPaddingTop;
   10894         if (offsetRequired) padding += getTopPaddingOffset();
   10895         return mBottom - mTop - mPaddingBottom - padding;
   10896     }
   10897 
   10898     /**
   10899      * <p>Indicates whether this view is attached to an hardware accelerated
   10900      * window or not.</p>
   10901      *
   10902      * <p>Even if this method returns true, it does not mean that every call
   10903      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
   10904      * accelerated {@link android.graphics.Canvas}. For instance, if this view
   10905      * is drawn onto an offscren {@link android.graphics.Bitmap} and its
   10906      * window is hardware accelerated,
   10907      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
   10908      * return false, and this method will return true.</p>
   10909      *
   10910      * @return True if the view is attached to a window and the window is
   10911      *         hardware accelerated; false in any other case.
   10912      */
   10913     public boolean isHardwareAccelerated() {
   10914         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
   10915     }
   10916 
   10917     /**
   10918      * Manually render this view (and all of its children) to the given Canvas.
   10919      * The view must have already done a full layout before this function is
   10920      * called.  When implementing a view, implement
   10921      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
   10922      * If you do need to override this method, call the superclass version.
   10923      *
   10924      * @param canvas The Canvas to which the View is rendered.
   10925      */
   10926     public void draw(Canvas canvas) {
   10927         if (ViewDebug.TRACE_HIERARCHY) {
   10928             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
   10929         }
   10930 
   10931         final int privateFlags = mPrivateFlags;
   10932         final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
   10933                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
   10934         mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
   10935 
   10936         /*
   10937          * Draw traversal performs several drawing steps which must be executed
   10938          * in the appropriate order:
   10939          *
   10940          *      1. Draw the background
   10941          *      2. If necessary, save the canvas' layers to prepare for fading
   10942          *      3. Draw view's content
   10943          *      4. Draw children
   10944          *      5. If necessary, draw the fading edges and restore layers
   10945          *      6. Draw decorations (scrollbars for instance)
   10946          */
   10947 
   10948         // Step 1, draw the background, if needed
   10949         int saveCount;
   10950 
   10951         if (!dirtyOpaque) {
   10952             final Drawable background = mBGDrawable;
   10953             if (background != null) {
   10954                 final int scrollX = mScrollX;
   10955                 final int scrollY = mScrollY;
   10956 
   10957                 if (mBackgroundSizeChanged) {
   10958                     background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
   10959                     mBackgroundSizeChanged = false;
   10960                 }
   10961 
   10962                 if ((scrollX | scrollY) == 0) {
   10963                     background.draw(canvas);
   10964                 } else {
   10965                     canvas.translate(scrollX, scrollY);
   10966                     background.draw(canvas);
   10967                     canvas.translate(-scrollX, -scrollY);
   10968                 }
   10969             }
   10970         }
   10971 
   10972         // skip step 2 & 5 if possible (common case)
   10973         final int viewFlags = mViewFlags;
   10974         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
   10975         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
   10976         if (!verticalEdges && !horizontalEdges) {
   10977             // Step 3, draw the content
   10978             if (!dirtyOpaque) onDraw(canvas);
   10979 
   10980             // Step 4, draw the children
   10981             dispatchDraw(canvas);
   10982 
   10983             // Step 6, draw decorations (scrollbars)
   10984             onDrawScrollBars(canvas);
   10985 
   10986             // we're done...
   10987             return;
   10988         }
   10989 
   10990         /*
   10991          * Here we do the full fledged routine...
   10992          * (this is an uncommon case where speed matters less,
   10993          * this is why we repeat some of the tests that have been
   10994          * done above)
   10995          */
   10996 
   10997         boolean drawTop = false;
   10998         boolean drawBottom = false;
   10999         boolean drawLeft = false;
   11000         boolean drawRight = false;
   11001 
   11002         float topFadeStrength = 0.0f;
   11003         float bottomFadeStrength = 0.0f;
   11004         float leftFadeStrength = 0.0f;
   11005         float rightFadeStrength = 0.0f;
   11006 
   11007         // Step 2, save the canvas' layers
   11008         int paddingLeft = mPaddingLeft;
   11009 
   11010         final boolean offsetRequired = isPaddingOffsetRequired();
   11011         if (offsetRequired) {
   11012             paddingLeft += getLeftPaddingOffset();
   11013         }
   11014 
   11015         int left = mScrollX + paddingLeft;
   11016         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
   11017         int top = mScrollY + getFadeTop(offsetRequired);
   11018         int bottom = top + getFadeHeight(offsetRequired);
   11019 
   11020         if (offsetRequired) {
   11021             right += getRightPaddingOffset();
   11022             bottom += getBottomPaddingOffset();
   11023         }
   11024 
   11025         final ScrollabilityCache scrollabilityCache = mScrollCache;
   11026         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
   11027         int length = (int) fadeHeight;
   11028 
   11029         // clip the fade length if top and bottom fades overlap
   11030         // overlapping fades produce odd-looking artifacts
   11031         if (verticalEdges && (top + length > bottom - length)) {
   11032             length = (bottom - top) / 2;
   11033         }
   11034 
   11035         // also clip horizontal fades if necessary
   11036         if (horizontalEdges && (left + length > right - length)) {
   11037             length = (right - left) / 2;
   11038         }
   11039 
   11040         if (verticalEdges) {
   11041             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
   11042             drawTop = topFadeStrength * fadeHeight > 1.0f;
   11043             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
   11044             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
   11045         }
   11046 
   11047         if (horizontalEdges) {
   11048             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
   11049             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
   11050             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
   11051             drawRight = rightFadeStrength * fadeHeight > 1.0f;
   11052         }
   11053 
   11054         saveCount = canvas.getSaveCount();
   11055 
   11056         int solidColor = getSolidColor();
   11057         if (solidColor == 0) {
   11058             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
   11059 
   11060             if (drawTop) {
   11061                 canvas.saveLayer(left, top, right, top + length, null, flags);
   11062             }
   11063 
   11064             if (drawBottom) {
   11065                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
   11066             }
   11067 
   11068             if (drawLeft) {
   11069                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
   11070             }
   11071 
   11072             if (drawRight) {
   11073                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
   11074             }
   11075         } else {
   11076             scrollabilityCache.setFadeColor(solidColor);
   11077         }
   11078 
   11079         // Step 3, draw the content
   11080         if (!dirtyOpaque) onDraw(canvas);
   11081 
   11082         // Step 4, draw the children
   11083         dispatchDraw(canvas);
   11084 
   11085         // Step 5, draw the fade effect and restore layers
   11086         final Paint p = scrollabilityCache.paint;
   11087         final Matrix matrix = scrollabilityCache.matrix;
   11088         final Shader fade = scrollabilityCache.shader;
   11089 
   11090         if (drawTop) {
   11091             matrix.setScale(1, fadeHeight * topFadeStrength);
   11092             matrix.postTranslate(left, top);
   11093             fade.setLocalMatrix(matrix);
   11094             canvas.drawRect(left, top, right, top + length, p);
   11095         }
   11096 
   11097         if (drawBottom) {
   11098             matrix.setScale(1, fadeHeight * bottomFadeStrength);
   11099             matrix.postRotate(180);
   11100             matrix.postTranslate(left, bottom);
   11101             fade.setLocalMatrix(matrix);
   11102             canvas.drawRect(left, bottom - length, right, bottom, p);
   11103         }
   11104 
   11105         if (drawLeft) {
   11106             matrix.setScale(1, fadeHeight * leftFadeStrength);
   11107             matrix.postRotate(-90);
   11108             matrix.postTranslate(left, top);
   11109             fade.setLocalMatrix(matrix);
   11110             canvas.drawRect(left, top, left + length, bottom, p);
   11111         }
   11112 
   11113         if (drawRight) {
   11114             matrix.setScale(1, fadeHeight * rightFadeStrength);
   11115             matrix.postRotate(90);
   11116             matrix.postTranslate(right, top);
   11117             fade.setLocalMatrix(matrix);
   11118             canvas.drawRect(right - length, top, right, bottom, p);
   11119         }
   11120 
   11121         canvas.restoreToCount(saveCount);
   11122 
   11123         // Step 6, draw decorations (scrollbars)
   11124         onDrawScrollBars(canvas);
   11125     }
   11126 
   11127     /**
   11128      * Override this if your view is known to always be drawn on top of a solid color background,
   11129      * and needs to draw fading edges. Returning a non-zero color enables the view system to
   11130      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
   11131      * should be set to 0xFF.
   11132      *
   11133      * @see #setVerticalFadingEdgeEnabled(boolean)
   11134      * @see #setHorizontalFadingEdgeEnabled(boolean)
   11135      *
   11136      * @return The known solid color background for this view, or 0 if the color may vary
   11137      */
   11138     @ViewDebug.ExportedProperty(category = "drawing")
   11139     public int getSolidColor() {
   11140         return 0;
   11141     }
   11142 
   11143     /**
   11144      * Build a human readable string representation of the specified view flags.
   11145      *
   11146      * @param flags the view flags to convert to a string
   11147      * @return a String representing the supplied flags
   11148      */
   11149     private static String printFlags(int flags) {
   11150         String output = "";
   11151         int numFlags = 0;
   11152         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
   11153             output += "TAKES_FOCUS";
   11154             numFlags++;
   11155         }
   11156 
   11157         switch (flags & VISIBILITY_MASK) {
   11158         case INVISIBLE:
   11159             if (numFlags > 0) {
   11160                 output += " ";
   11161             }
   11162             output += "INVISIBLE";
   11163             // USELESS HERE numFlags++;
   11164             break;
   11165         case GONE:
   11166             if (numFlags > 0) {
   11167                 output += " ";
   11168             }
   11169             output += "GONE";
   11170             // USELESS HERE numFlags++;
   11171             break;
   11172         default:
   11173             break;
   11174         }
   11175         return output;
   11176     }
   11177 
   11178     /**
   11179      * Build a human readable string representation of the specified private
   11180      * view flags.
   11181      *
   11182      * @param privateFlags the private view flags to convert to a string
   11183      * @return a String representing the supplied flags
   11184      */
   11185     private static String printPrivateFlags(int privateFlags) {
   11186         String output = "";
   11187         int numFlags = 0;
   11188 
   11189         if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
   11190             output += "WANTS_FOCUS";
   11191             numFlags++;
   11192         }
   11193 
   11194         if ((privateFlags & FOCUSED) == FOCUSED) {
   11195             if (numFlags > 0) {
   11196                 output += " ";
   11197             }
   11198             output += "FOCUSED";
   11199             numFlags++;
   11200         }
   11201 
   11202         if ((privateFlags & SELECTED) == SELECTED) {
   11203             if (numFlags > 0) {
   11204                 output += " ";
   11205             }
   11206             output += "SELECTED";
   11207             numFlags++;
   11208         }
   11209 
   11210         if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
   11211             if (numFlags > 0) {
   11212                 output += " ";
   11213             }
   11214             output += "IS_ROOT_NAMESPACE";
   11215             numFlags++;
   11216         }
   11217 
   11218         if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
   11219             if (numFlags > 0) {
   11220                 output += " ";
   11221             }
   11222             output += "HAS_BOUNDS";
   11223             numFlags++;
   11224         }
   11225 
   11226         if ((privateFlags & DRAWN) == DRAWN) {
   11227             if (numFlags > 0) {
   11228                 output += " ";
   11229             }
   11230             output += "DRAWN";
   11231             // USELESS HERE numFlags++;
   11232         }
   11233         return output;
   11234     }
   11235 
   11236     /**
   11237      * <p>Indicates whether or not this view's layout will be requested during
   11238      * the next hierarchy layout pass.</p>
   11239      *
   11240      * @return true if the layout will be forced during next layout pass
   11241      */
   11242     public boolean isLayoutRequested() {
   11243         return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
   11244     }
   11245 
   11246     /**
   11247      * Assign a size and position to a view and all of its
   11248      * descendants
   11249      *
   11250      * <p>This is the second phase of the layout mechanism.
   11251      * (The first is measuring). In this phase, each parent calls
   11252      * layout on all of its children to position them.
   11253      * This is typically done using the child measurements
   11254      * that were stored in the measure pass().</p>
   11255      *
   11256      * <p>Derived classes should not override this method.
   11257      * Derived classes with children should override
   11258      * onLayout. In that method, they should
   11259      * call layout on each of their children.</p>
   11260      *
   11261      * @param l Left position, relative to parent
   11262      * @param t Top position, relative to parent
   11263      * @param r Right position, relative to parent
   11264      * @param b Bottom position, relative to parent
   11265      */
   11266     @SuppressWarnings({"unchecked"})
   11267     public void layout(int l, int t, int r, int b) {
   11268         int oldL = mLeft;
   11269         int oldT = mTop;
   11270         int oldB = mBottom;
   11271         int oldR = mRight;
   11272         boolean changed = setFrame(l, t, r, b);
   11273         if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
   11274             if (ViewDebug.TRACE_HIERARCHY) {
   11275                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
   11276             }
   11277 
   11278             onLayout(changed, l, t, r, b);
   11279             mPrivateFlags &= ~LAYOUT_REQUIRED;
   11280 
   11281             ListenerInfo li = mListenerInfo;
   11282             if (li != null && li.mOnLayoutChangeListeners != null) {
   11283                 ArrayList<OnLayoutChangeListener> listenersCopy =
   11284                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
   11285                 int numListeners = listenersCopy.size();
   11286                 for (int i = 0; i < numListeners; ++i) {
   11287                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
   11288                 }
   11289             }
   11290         }
   11291         mPrivateFlags &= ~FORCE_LAYOUT;
   11292     }
   11293 
   11294     /**
   11295      * Called from layout when this view should
   11296      * assign a size and position to each of its children.
   11297      *
   11298      * Derived classes with children should override
   11299      * this method and call layout on each of
   11300      * their children.
   11301      * @param changed This is a new size or position for this view
   11302      * @param left Left position, relative to parent
   11303      * @param top Top position, relative to parent
   11304      * @param right Right position, relative to parent
   11305      * @param bottom Bottom position, relative to parent
   11306      */
   11307     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   11308     }
   11309 
   11310     /**
   11311      * Assign a size and position to this view.
   11312      *
   11313      * This is called from layout.
   11314      *
   11315      * @param left Left position, relative to parent
   11316      * @param top Top position, relative to parent
   11317      * @param right Right position, relative to parent
   11318      * @param bottom Bottom position, relative to parent
   11319      * @return true if the new size and position are different than the
   11320      *         previous ones
   11321      * {@hide}
   11322      */
   11323     protected boolean setFrame(int left, int top, int right, int bottom) {
   11324         boolean changed = false;
   11325 
   11326         if (DBG) {
   11327             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
   11328                     + right + "," + bottom + ")");
   11329         }
   11330 
   11331         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
   11332             changed = true;
   11333 
   11334             // Remember our drawn bit
   11335             int drawn = mPrivateFlags & DRAWN;
   11336 
   11337             int oldWidth = mRight - mLeft;
   11338             int oldHeight = mBottom - mTop;
   11339             int newWidth = right - left;
   11340             int newHeight = bottom - top;
   11341             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
   11342 
   11343             // Invalidate our old position
   11344             invalidate(sizeChanged);
   11345 
   11346             mLeft = left;
   11347             mTop = top;
   11348             mRight = right;
   11349             mBottom = bottom;
   11350 
   11351             mPrivateFlags |= HAS_BOUNDS;
   11352 
   11353 
   11354             if (sizeChanged) {
   11355                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
   11356                     // A change in dimension means an auto-centered pivot point changes, too
   11357                     if (mTransformationInfo != null) {
   11358                         mTransformationInfo.mMatrixDirty = true;
   11359                     }
   11360                 }
   11361                 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
   11362             }
   11363 
   11364             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
   11365                 // If we are visible, force the DRAWN bit to on so that
   11366                 // this invalidate will go through (at least to our parent).
   11367                 // This is because someone may have invalidated this view
   11368                 // before this call to setFrame came in, thereby clearing
   11369                 // the DRAWN bit.
   11370                 mPrivateFlags |= DRAWN;
   11371                 invalidate(sizeChanged);
   11372                 // parent display list may need to be recreated based on a change in the bounds
   11373                 // of any child
   11374                 invalidateParentCaches();
   11375             }
   11376 
   11377             // Reset drawn bit to original value (invalidate turns it off)
   11378             mPrivateFlags |= drawn;
   11379 
   11380             mBackgroundSizeChanged = true;
   11381         }
   11382         return changed;
   11383     }
   11384 
   11385     /**
   11386      * Finalize inflating a view from XML.  This is called as the last phase
   11387      * of inflation, after all child views have been added.
   11388      *
   11389      * <p>Even if the subclass overrides onFinishInflate, they should always be
   11390      * sure to call the super method, so that we get called.
   11391      */
   11392     protected void onFinishInflate() {
   11393     }
   11394 
   11395     /**
   11396      * Returns the resources associated with this view.
   11397      *
   11398      * @return Resources object.
   11399      */
   11400     public Resources getResources() {
   11401         return mResources;
   11402     }
   11403 
   11404     /**
   11405      * Invalidates the specified Drawable.
   11406      *
   11407      * @param drawable the drawable to invalidate
   11408      */
   11409     public void invalidateDrawable(Drawable drawable) {
   11410         if (verifyDrawable(drawable)) {
   11411             final Rect dirty = drawable.getBounds();
   11412             final int scrollX = mScrollX;
   11413             final int scrollY = mScrollY;
   11414 
   11415             invalidate(dirty.left + scrollX, dirty.top + scrollY,
   11416                     dirty.right + scrollX, dirty.bottom + scrollY);
   11417         }
   11418     }
   11419 
   11420     /**
   11421      * Schedules an action on a drawable to occur at a specified time.
   11422      *
   11423      * @param who the recipient of the action
   11424      * @param what the action to run on the drawable
   11425      * @param when the time at which the action must occur. Uses the
   11426      *        {@link SystemClock#uptimeMillis} timebase.
   11427      */
   11428     public void scheduleDrawable(Drawable who, Runnable what, long when) {
   11429         if (verifyDrawable(who) && what != null) {
   11430             if (mAttachInfo != null) {
   11431                 mAttachInfo.mHandler.postAtTime(what, who, when);
   11432             } else {
   11433                 ViewRootImpl.getRunQueue().postDelayed(what, when - SystemClock.uptimeMillis());
   11434             }
   11435         }
   11436     }
   11437 
   11438     /**
   11439      * Cancels a scheduled action on a drawable.
   11440      *
   11441      * @param who the recipient of the action
   11442      * @param what the action to cancel
   11443      */
   11444     public void unscheduleDrawable(Drawable who, Runnable what) {
   11445         if (verifyDrawable(who) && what != null) {
   11446             if (mAttachInfo != null) {
   11447                 mAttachInfo.mHandler.removeCallbacks(what, who);
   11448             } else {
   11449                 ViewRootImpl.getRunQueue().removeCallbacks(what);
   11450             }
   11451         }
   11452     }
   11453 
   11454     /**
   11455      * Unschedule any events associated with the given Drawable.  This can be
   11456      * used when selecting a new Drawable into a view, so that the previous
   11457      * one is completely unscheduled.
   11458      *
   11459      * @param who The Drawable to unschedule.
   11460      *
   11461      * @see #drawableStateChanged
   11462      */
   11463     public void unscheduleDrawable(Drawable who) {
   11464         if (mAttachInfo != null) {
   11465             mAttachInfo.mHandler.removeCallbacksAndMessages(who);
   11466         }
   11467     }
   11468 
   11469     /**
   11470     * Return the layout direction of a given Drawable.
   11471     *
   11472     * @param who the Drawable to query
   11473     *
   11474     * @hide
   11475     */
   11476     public int getResolvedLayoutDirection(Drawable who) {
   11477         return (who == mBGDrawable) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
   11478     }
   11479 
   11480     /**
   11481      * If your view subclass is displaying its own Drawable objects, it should
   11482      * override this function and return true for any Drawable it is
   11483      * displaying.  This allows animations for those drawables to be
   11484      * scheduled.
   11485      *
   11486      * <p>Be sure to call through to the super class when overriding this
   11487      * function.
   11488      *
   11489      * @param who The Drawable to verify.  Return true if it is one you are
   11490      *            displaying, else return the result of calling through to the
   11491      *            super class.
   11492      *
   11493      * @return boolean If true than the Drawable is being displayed in the
   11494      *         view; else false and it is not allowed to animate.
   11495      *
   11496      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
   11497      * @see #drawableStateChanged()
   11498      */
   11499     protected boolean verifyDrawable(Drawable who) {
   11500         return who == mBGDrawable;
   11501     }
   11502 
   11503     /**
   11504      * This function is called whenever the state of the view changes in such
   11505      * a way that it impacts the state of drawables being shown.
   11506      *
   11507      * <p>Be sure to call through to the superclass when overriding this
   11508      * function.
   11509      *
   11510      * @see Drawable#setState(int[])
   11511      */
   11512     protected void drawableStateChanged() {
   11513         Drawable d = mBGDrawable;
   11514         if (d != null && d.isStateful()) {
   11515             d.setState(getDrawableState());
   11516         }
   11517     }
   11518 
   11519     /**
   11520      * Call this to force a view to update its drawable state. This will cause
   11521      * drawableStateChanged to be called on this view. Views that are interested
   11522      * in the new state should call getDrawableState.
   11523      *
   11524      * @see #drawableStateChanged
   11525      * @see #getDrawableState
   11526      */
   11527     public void refreshDrawableState() {
   11528         mPrivateFlags |= DRAWABLE_STATE_DIRTY;
   11529         drawableStateChanged();
   11530 
   11531         ViewParent parent = mParent;
   11532         if (parent != null) {
   11533             parent.childDrawableStateChanged(this);
   11534         }
   11535     }
   11536 
   11537     /**
   11538      * Return an array of resource IDs of the drawable states representing the
   11539      * current state of the view.
   11540      *
   11541      * @return The current drawable state
   11542      *
   11543      * @see Drawable#setState(int[])
   11544      * @see #drawableStateChanged()
   11545      * @see #onCreateDrawableState(int)
   11546      */
   11547     public final int[] getDrawableState() {
   11548         if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
   11549             return mDrawableState;
   11550         } else {
   11551             mDrawableState = onCreateDrawableState(0);
   11552             mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
   11553             return mDrawableState;
   11554         }
   11555     }
   11556 
   11557     /**
   11558      * Generate the new {@link android.graphics.drawable.Drawable} state for
   11559      * this view. This is called by the view
   11560      * system when the cached Drawable state is determined to be invalid.  To
   11561      * retrieve the current state, you should use {@link #getDrawableState}.
   11562      *
   11563      * @param extraSpace if non-zero, this is the number of extra entries you
   11564      * would like in the returned array in which you can place your own
   11565      * states.
   11566      *
   11567      * @return Returns an array holding the current {@link Drawable} state of
   11568      * the view.
   11569      *
   11570      * @see #mergeDrawableStates(int[], int[])
   11571      */
   11572     protected int[] onCreateDrawableState(int extraSpace) {
   11573         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
   11574                 mParent instanceof View) {
   11575             return ((View) mParent).onCreateDrawableState(extraSpace);
   11576         }
   11577 
   11578         int[] drawableState;
   11579 
   11580         int privateFlags = mPrivateFlags;
   11581 
   11582         int viewStateIndex = 0;
   11583         if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
   11584         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
   11585         if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
   11586         if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
   11587         if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
   11588         if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
   11589         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
   11590                 HardwareRenderer.isAvailable()) {
   11591             // This is set if HW acceleration is requested, even if the current
   11592             // process doesn't allow it.  This is just to allow app preview
   11593             // windows to better match their app.
   11594             viewStateIndex |= VIEW_STATE_ACCELERATED;
   11595         }
   11596         if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
   11597 
   11598         final int privateFlags2 = mPrivateFlags2;
   11599         if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
   11600         if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
   11601 
   11602         drawableState = VIEW_STATE_SETS[viewStateIndex];
   11603 
   11604         //noinspection ConstantIfStatement
   11605         if (false) {
   11606             Log.i("View", "drawableStateIndex=" + viewStateIndex);
   11607             Log.i("View", toString()
   11608                     + " pressed=" + ((privateFlags & PRESSED) != 0)
   11609                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
   11610                     + " fo=" + hasFocus()
   11611                     + " sl=" + ((privateFlags & SELECTED) != 0)
   11612                     + " wf=" + hasWindowFocus()
   11613                     + ": " + Arrays.toString(drawableState));
   11614         }
   11615 
   11616         if (extraSpace == 0) {
   11617             return drawableState;
   11618         }
   11619 
   11620         final int[] fullState;
   11621         if (drawableState != null) {
   11622             fullState = new int[drawableState.length + extraSpace];
   11623             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
   11624         } else {
   11625             fullState = new int[extraSpace];
   11626         }
   11627 
   11628         return fullState;
   11629     }
   11630 
   11631     /**
   11632      * Merge your own state values in <var>additionalState</var> into the base
   11633      * state values <var>baseState</var> that were returned by
   11634      * {@link #onCreateDrawableState(int)}.
   11635      *
   11636      * @param baseState The base state values returned by
   11637      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
   11638      * own additional state values.
   11639      *
   11640      * @param additionalState The additional state values you would like
   11641      * added to <var>baseState</var>; this array is not modified.
   11642      *
   11643      * @return As a convenience, the <var>baseState</var> array you originally
   11644      * passed into the function is returned.
   11645      *
   11646      * @see #onCreateDrawableState(int)
   11647      */
   11648     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
   11649         final int N = baseState.length;
   11650         int i = N - 1;
   11651         while (i >= 0 && baseState[i] == 0) {
   11652             i--;
   11653         }
   11654         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
   11655         return baseState;
   11656     }
   11657 
   11658     /**
   11659      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
   11660      * on all Drawable objects associated with this view.
   11661      */
   11662     public void jumpDrawablesToCurrentState() {
   11663         if (mBGDrawable != null) {
   11664             mBGDrawable.jumpToCurrentState();
   11665         }
   11666     }
   11667 
   11668     /**
   11669      * Sets the background color for this view.
   11670      * @param color the color of the background
   11671      */
   11672     @RemotableViewMethod
   11673     public void setBackgroundColor(int color) {
   11674         if (mBGDrawable instanceof ColorDrawable) {
   11675             ((ColorDrawable) mBGDrawable).setColor(color);
   11676         } else {
   11677             setBackgroundDrawable(new ColorDrawable(color));
   11678         }
   11679     }
   11680 
   11681     /**
   11682      * Set the background to a given resource. The resource should refer to
   11683      * a Drawable object or 0 to remove the background.
   11684      * @param resid The identifier of the resource.
   11685      * @attr ref android.R.styleable#View_background
   11686      */
   11687     @RemotableViewMethod
   11688     public void setBackgroundResource(int resid) {
   11689         if (resid != 0 && resid == mBackgroundResource) {
   11690             return;
   11691         }
   11692 
   11693         Drawable d= null;
   11694         if (resid != 0) {
   11695             d = mResources.getDrawable(resid);
   11696         }
   11697         setBackgroundDrawable(d);
   11698 
   11699         mBackgroundResource = resid;
   11700     }
   11701 
   11702     /**
   11703      * Set the background to a given Drawable, or remove the background. If the
   11704      * background has padding, this View's padding is set to the background's
   11705      * padding. However, when a background is removed, this View's padding isn't
   11706      * touched. If setting the padding is desired, please use
   11707      * {@link #setPadding(int, int, int, int)}.
   11708      *
   11709      * @param d The Drawable to use as the background, or null to remove the
   11710      *        background
   11711      */
   11712     public void setBackgroundDrawable(Drawable d) {
   11713         if (d == mBGDrawable) {
   11714             return;
   11715         }
   11716 
   11717         boolean requestLayout = false;
   11718 
   11719         mBackgroundResource = 0;
   11720 
   11721         /*
   11722          * Regardless of whether we're setting a new background or not, we want
   11723          * to clear the previous drawable.
   11724          */
   11725         if (mBGDrawable != null) {
   11726             mBGDrawable.setCallback(null);
   11727             unscheduleDrawable(mBGDrawable);
   11728         }
   11729 
   11730         if (d != null) {
   11731             Rect padding = sThreadLocal.get();
   11732             if (padding == null) {
   11733                 padding = new Rect();
   11734                 sThreadLocal.set(padding);
   11735             }
   11736             if (d.getPadding(padding)) {
   11737                 switch (d.getResolvedLayoutDirectionSelf()) {
   11738                     case LAYOUT_DIRECTION_RTL:
   11739                         setPadding(padding.right, padding.top, padding.left, padding.bottom);
   11740                         break;
   11741                     case LAYOUT_DIRECTION_LTR:
   11742                     default:
   11743                         setPadding(padding.left, padding.top, padding.right, padding.bottom);
   11744                 }
   11745             }
   11746 
   11747             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
   11748             // if it has a different minimum size, we should layout again
   11749             if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
   11750                     mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
   11751                 requestLayout = true;
   11752             }
   11753 
   11754             d.setCallback(this);
   11755             if (d.isStateful()) {
   11756                 d.setState(getDrawableState());
   11757             }
   11758             d.setVisible(getVisibility() == VISIBLE, false);
   11759             mBGDrawable = d;
   11760 
   11761             if ((mPrivateFlags & SKIP_DRAW) != 0) {
   11762                 mPrivateFlags &= ~SKIP_DRAW;
   11763                 mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
   11764                 requestLayout = true;
   11765             }
   11766         } else {
   11767             /* Remove the background */
   11768             mBGDrawable = null;
   11769 
   11770             if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
   11771                 /*
   11772                  * This view ONLY drew the background before and we're removing
   11773                  * the background, so now it won't draw anything
   11774                  * (hence we SKIP_DRAW)
   11775                  */
   11776                 mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
   11777                 mPrivateFlags |= SKIP_DRAW;
   11778             }
   11779 
   11780             /*
   11781              * When the background is set, we try to apply its padding to this
   11782              * View. When the background is removed, we don't touch this View's
   11783              * padding. This is noted in the Javadocs. Hence, we don't need to
   11784              * requestLayout(), the invalidate() below is sufficient.
   11785              */
   11786 
   11787             // The old background's minimum size could have affected this
   11788             // View's layout, so let's requestLayout
   11789             requestLayout = true;
   11790         }
   11791 
   11792         computeOpaqueFlags();
   11793 
   11794         if (requestLayout) {
   11795             requestLayout();
   11796         }
   11797 
   11798         mBackgroundSizeChanged = true;
   11799         invalidate(true);
   11800     }
   11801 
   11802     /**
   11803      * Gets the background drawable
   11804      * @return The drawable used as the background for this view, if any.
   11805      */
   11806     public Drawable getBackground() {
   11807         return mBGDrawable;
   11808     }
   11809 
   11810     /**
   11811      * Sets the padding. The view may add on the space required to display
   11812      * the scrollbars, depending on the style and visibility of the scrollbars.
   11813      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
   11814      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
   11815      * from the values set in this call.
   11816      *
   11817      * @attr ref android.R.styleable#View_padding
   11818      * @attr ref android.R.styleable#View_paddingBottom
   11819      * @attr ref android.R.styleable#View_paddingLeft
   11820      * @attr ref android.R.styleable#View_paddingRight
   11821      * @attr ref android.R.styleable#View_paddingTop
   11822      * @param left the left padding in pixels
   11823      * @param top the top padding in pixels
   11824      * @param right the right padding in pixels
   11825      * @param bottom the bottom padding in pixels
   11826      */
   11827     public void setPadding(int left, int top, int right, int bottom) {
   11828         boolean changed = false;
   11829 
   11830         mUserPaddingRelative = false;
   11831 
   11832         mUserPaddingLeft = left;
   11833         mUserPaddingRight = right;
   11834         mUserPaddingBottom = bottom;
   11835 
   11836         final int viewFlags = mViewFlags;
   11837 
   11838         // Common case is there are no scroll bars.
   11839         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
   11840             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
   11841                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
   11842                         ? 0 : getVerticalScrollbarWidth();
   11843                 switch (mVerticalScrollbarPosition) {
   11844                     case SCROLLBAR_POSITION_DEFAULT:
   11845                         if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   11846                             left += offset;
   11847                         } else {
   11848                             right += offset;
   11849                         }
   11850                         break;
   11851                     case SCROLLBAR_POSITION_RIGHT:
   11852                         right += offset;
   11853                         break;
   11854                     case SCROLLBAR_POSITION_LEFT:
   11855                         left += offset;
   11856                         break;
   11857                 }
   11858             }
   11859             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
   11860                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
   11861                         ? 0 : getHorizontalScrollbarHeight();
   11862             }
   11863         }
   11864 
   11865         if (mPaddingLeft != left) {
   11866             changed = true;
   11867             mPaddingLeft = left;
   11868         }
   11869         if (mPaddingTop != top) {
   11870             changed = true;
   11871             mPaddingTop = top;
   11872         }
   11873         if (mPaddingRight != right) {
   11874             changed = true;
   11875             mPaddingRight = right;
   11876         }
   11877         if (mPaddingBottom != bottom) {
   11878             changed = true;
   11879             mPaddingBottom = bottom;
   11880         }
   11881 
   11882         if (changed) {
   11883             requestLayout();
   11884         }
   11885     }
   11886 
   11887     /**
   11888      * Sets the relative padding. The view may add on the space required to display
   11889      * the scrollbars, depending on the style and visibility of the scrollbars.
   11890      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
   11891      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
   11892      * from the values set in this call.
   11893      *
   11894      * @attr ref android.R.styleable#View_padding
   11895      * @attr ref android.R.styleable#View_paddingBottom
   11896      * @attr ref android.R.styleable#View_paddingStart
   11897      * @attr ref android.R.styleable#View_paddingEnd
   11898      * @attr ref android.R.styleable#View_paddingTop
   11899      * @param start the start padding in pixels
   11900      * @param top the top padding in pixels
   11901      * @param end the end padding in pixels
   11902      * @param bottom the bottom padding in pixels
   11903      *
   11904      * @hide
   11905      */
   11906     public void setPaddingRelative(int start, int top, int end, int bottom) {
   11907         mUserPaddingRelative = true;
   11908 
   11909         mUserPaddingStart = start;
   11910         mUserPaddingEnd = end;
   11911 
   11912         switch(getResolvedLayoutDirection()) {
   11913             case LAYOUT_DIRECTION_RTL:
   11914                 setPadding(end, top, start, bottom);
   11915                 break;
   11916             case LAYOUT_DIRECTION_LTR:
   11917             default:
   11918                 setPadding(start, top, end, bottom);
   11919         }
   11920     }
   11921 
   11922     /**
   11923      * Returns the top padding of this view.
   11924      *
   11925      * @return the top padding in pixels
   11926      */
   11927     public int getPaddingTop() {
   11928         return mPaddingTop;
   11929     }
   11930 
   11931     /**
   11932      * Returns the bottom padding of this view. If there are inset and enabled
   11933      * scrollbars, this value may include the space required to display the
   11934      * scrollbars as well.
   11935      *
   11936      * @return the bottom padding in pixels
   11937      */
   11938     public int getPaddingBottom() {
   11939         return mPaddingBottom;
   11940     }
   11941 
   11942     /**
   11943      * Returns the left padding of this view. If there are inset and enabled
   11944      * scrollbars, this value may include the space required to display the
   11945      * scrollbars as well.
   11946      *
   11947      * @return the left padding in pixels
   11948      */
   11949     public int getPaddingLeft() {
   11950         return mPaddingLeft;
   11951     }
   11952 
   11953     /**
   11954      * Returns the start padding of this view. If there are inset and enabled
   11955      * scrollbars, this value may include the space required to display the
   11956      * scrollbars as well.
   11957      *
   11958      * @return the start padding in pixels
   11959      *
   11960      * @hide
   11961      */
   11962     public int getPaddingStart() {
   11963         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   11964                 mPaddingRight : mPaddingLeft;
   11965     }
   11966 
   11967     /**
   11968      * Returns the right padding of this view. If there are inset and enabled
   11969      * scrollbars, this value may include the space required to display the
   11970      * scrollbars as well.
   11971      *
   11972      * @return the right padding in pixels
   11973      */
   11974     public int getPaddingRight() {
   11975         return mPaddingRight;
   11976     }
   11977 
   11978     /**
   11979      * Returns the end padding of this view. If there are inset and enabled
   11980      * scrollbars, this value may include the space required to display the
   11981      * scrollbars as well.
   11982      *
   11983      * @return the end padding in pixels
   11984      *
   11985      * @hide
   11986      */
   11987     public int getPaddingEnd() {
   11988         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   11989                 mPaddingLeft : mPaddingRight;
   11990     }
   11991 
   11992     /**
   11993      * Return if the padding as been set thru relative values
   11994      * {@link #setPaddingRelative(int, int, int, int)} or thru
   11995      * @attr ref android.R.styleable#View_paddingStart or
   11996      * @attr ref android.R.styleable#View_paddingEnd
   11997      *
   11998      * @return true if the padding is relative or false if it is not.
   11999      *
   12000      * @hide
   12001      */
   12002     public boolean isPaddingRelative() {
   12003         return mUserPaddingRelative;
   12004     }
   12005 
   12006     /**
   12007      * Changes the selection state of this view. A view can be selected or not.
   12008      * Note that selection is not the same as focus. Views are typically
   12009      * selected in the context of an AdapterView like ListView or GridView;
   12010      * the selected view is the view that is highlighted.
   12011      *
   12012      * @param selected true if the view must be selected, false otherwise
   12013      */
   12014     public void setSelected(boolean selected) {
   12015         if (((mPrivateFlags & SELECTED) != 0) != selected) {
   12016             mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
   12017             if (!selected) resetPressedState();
   12018             invalidate(true);
   12019             refreshDrawableState();
   12020             dispatchSetSelected(selected);
   12021         }
   12022     }
   12023 
   12024     /**
   12025      * Dispatch setSelected to all of this View's children.
   12026      *
   12027      * @see #setSelected(boolean)
   12028      *
   12029      * @param selected The new selected state
   12030      */
   12031     protected void dispatchSetSelected(boolean selected) {
   12032     }
   12033 
   12034     /**
   12035      * Indicates the selection state of this view.
   12036      *
   12037      * @return true if the view is selected, false otherwise
   12038      */
   12039     @ViewDebug.ExportedProperty
   12040     public boolean isSelected() {
   12041         return (mPrivateFlags & SELECTED) != 0;
   12042     }
   12043 
   12044     /**
   12045      * Changes the activated state of this view. A view can be activated or not.
   12046      * Note that activation is not the same as selection.  Selection is
   12047      * a transient property, representing the view (hierarchy) the user is
   12048      * currently interacting with.  Activation is a longer-term state that the
   12049      * user can move views in and out of.  For example, in a list view with
   12050      * single or multiple selection enabled, the views in the current selection
   12051      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
   12052      * here.)  The activated state is propagated down to children of the view it
   12053      * is set on.
   12054      *
   12055      * @param activated true if the view must be activated, false otherwise
   12056      */
   12057     public void setActivated(boolean activated) {
   12058         if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
   12059             mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
   12060             invalidate(true);
   12061             refreshDrawableState();
   12062             dispatchSetActivated(activated);
   12063         }
   12064     }
   12065 
   12066     /**
   12067      * Dispatch setActivated to all of this View's children.
   12068      *
   12069      * @see #setActivated(boolean)
   12070      *
   12071      * @param activated The new activated state
   12072      */
   12073     protected void dispatchSetActivated(boolean activated) {
   12074     }
   12075 
   12076     /**
   12077      * Indicates the activation state of this view.
   12078      *
   12079      * @return true if the view is activated, false otherwise
   12080      */
   12081     @ViewDebug.ExportedProperty
   12082     public boolean isActivated() {
   12083         return (mPrivateFlags & ACTIVATED) != 0;
   12084     }
   12085 
   12086     /**
   12087      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
   12088      * observer can be used to get notifications when global events, like
   12089      * layout, happen.
   12090      *
   12091      * The returned ViewTreeObserver observer is not guaranteed to remain
   12092      * valid for the lifetime of this View. If the caller of this method keeps
   12093      * a long-lived reference to ViewTreeObserver, it should always check for
   12094      * the return value of {@link ViewTreeObserver#isAlive()}.
   12095      *
   12096      * @return The ViewTreeObserver for this view's hierarchy.
   12097      */
   12098     public ViewTreeObserver getViewTreeObserver() {
   12099         if (mAttachInfo != null) {
   12100             return mAttachInfo.mTreeObserver;
   12101         }
   12102         if (mFloatingTreeObserver == null) {
   12103             mFloatingTreeObserver = new ViewTreeObserver();
   12104         }
   12105         return mFloatingTreeObserver;
   12106     }
   12107 
   12108     /**
   12109      * <p>Finds the topmost view in the current view hierarchy.</p>
   12110      *
   12111      * @return the topmost view containing this view
   12112      */
   12113     public View getRootView() {
   12114         if (mAttachInfo != null) {
   12115             final View v = mAttachInfo.mRootView;
   12116             if (v != null) {
   12117                 return v;
   12118             }
   12119         }
   12120 
   12121         View parent = this;
   12122 
   12123         while (parent.mParent != null && parent.mParent instanceof View) {
   12124             parent = (View) parent.mParent;
   12125         }
   12126 
   12127         return parent;
   12128     }
   12129 
   12130     /**
   12131      * <p>Computes the coordinates of this view on the screen. The argument
   12132      * must be an array of two integers. After the method returns, the array
   12133      * contains the x and y location in that order.</p>
   12134      *
   12135      * @param location an array of two integers in which to hold the coordinates
   12136      */
   12137     public void getLocationOnScreen(int[] location) {
   12138         getLocationInWindow(location);
   12139 
   12140         final AttachInfo info = mAttachInfo;
   12141         if (info != null) {
   12142             location[0] += info.mWindowLeft;
   12143             location[1] += info.mWindowTop;
   12144         }
   12145     }
   12146 
   12147     /**
   12148      * <p>Computes the coordinates of this view in its window. The argument
   12149      * must be an array of two integers. After the method returns, the array
   12150      * contains the x and y location in that order.</p>
   12151      *
   12152      * @param location an array of two integers in which to hold the coordinates
   12153      */
   12154     public void getLocationInWindow(int[] location) {
   12155         // When the view is not attached to a window, this method does not make sense
   12156         if (mAttachInfo == null) return;
   12157 
   12158         if (location == null || location.length < 2) {
   12159             throw new IllegalArgumentException("location must be an array of two integers");
   12160         }
   12161 
   12162         float[] position = mAttachInfo.mTmpTransformLocation;
   12163         position[0] = position[1] = 0.0f;
   12164 
   12165         if (!hasIdentityMatrix()) {
   12166             getMatrix().mapPoints(position);
   12167         }
   12168 
   12169         position[0] += mLeft;
   12170         position[1] += mTop;
   12171 
   12172         ViewParent viewParent = mParent;
   12173         while (viewParent instanceof View) {
   12174             final View view = (View) viewParent;
   12175 
   12176             position[0] -= view.mScrollX;
   12177             position[1] -= view.mScrollY;
   12178 
   12179             if (!view.hasIdentityMatrix()) {
   12180                 view.getMatrix().mapPoints(position);
   12181             }
   12182 
   12183             position[0] += view.mLeft;
   12184             position[1] += view.mTop;
   12185 
   12186             viewParent = view.mParent;
   12187         }
   12188 
   12189         if (viewParent instanceof ViewRootImpl) {
   12190             // *cough*
   12191             final ViewRootImpl vr = (ViewRootImpl) viewParent;
   12192             position[1] -= vr.mCurScrollY;
   12193         }
   12194 
   12195         location[0] = (int) (position[0] + 0.5f);
   12196         location[1] = (int) (position[1] + 0.5f);
   12197     }
   12198 
   12199     /**
   12200      * {@hide}
   12201      * @param id the id of the view to be found
   12202      * @return the view of the specified id, null if cannot be found
   12203      */
   12204     protected View findViewTraversal(int id) {
   12205         if (id == mID) {
   12206             return this;
   12207         }
   12208         return null;
   12209     }
   12210 
   12211     /**
   12212      * {@hide}
   12213      * @param tag the tag of the view to be found
   12214      * @return the view of specified tag, null if cannot be found
   12215      */
   12216     protected View findViewWithTagTraversal(Object tag) {
   12217         if (tag != null && tag.equals(mTag)) {
   12218             return this;
   12219         }
   12220         return null;
   12221     }
   12222 
   12223     /**
   12224      * {@hide}
   12225      * @param predicate The predicate to evaluate.
   12226      * @param childToSkip If not null, ignores this child during the recursive traversal.
   12227      * @return The first view that matches the predicate or null.
   12228      */
   12229     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
   12230         if (predicate.apply(this)) {
   12231             return this;
   12232         }
   12233         return null;
   12234     }
   12235 
   12236     /**
   12237      * Look for a child view with the given id.  If this view has the given
   12238      * id, return this view.
   12239      *
   12240      * @param id The id to search for.
   12241      * @return The view that has the given id in the hierarchy or null
   12242      */
   12243     public final View findViewById(int id) {
   12244         if (id < 0) {
   12245             return null;
   12246         }
   12247         return findViewTraversal(id);
   12248     }
   12249 
   12250     /**
   12251      * Finds a view by its unuque and stable accessibility id.
   12252      *
   12253      * @param accessibilityId The searched accessibility id.
   12254      * @return The found view.
   12255      */
   12256     final View findViewByAccessibilityId(int accessibilityId) {
   12257         if (accessibilityId < 0) {
   12258             return null;
   12259         }
   12260         return findViewByAccessibilityIdTraversal(accessibilityId);
   12261     }
   12262 
   12263     /**
   12264      * Performs the traversal to find a view by its unuque and stable accessibility id.
   12265      *
   12266      * <strong>Note:</strong>This method does not stop at the root namespace
   12267      * boundary since the user can touch the screen at an arbitrary location
   12268      * potentially crossing the root namespace bounday which will send an
   12269      * accessibility event to accessibility services and they should be able
   12270      * to obtain the event source. Also accessibility ids are guaranteed to be
   12271      * unique in the window.
   12272      *
   12273      * @param accessibilityId The accessibility id.
   12274      * @return The found view.
   12275      */
   12276     View findViewByAccessibilityIdTraversal(int accessibilityId) {
   12277         if (getAccessibilityViewId() == accessibilityId) {
   12278             return this;
   12279         }
   12280         return null;
   12281     }
   12282 
   12283     /**
   12284      * Look for a child view with the given tag.  If this view has the given
   12285      * tag, return this view.
   12286      *
   12287      * @param tag The tag to search for, using "tag.equals(getTag())".
   12288      * @return The View that has the given tag in the hierarchy or null
   12289      */
   12290     public final View findViewWithTag(Object tag) {
   12291         if (tag == null) {
   12292             return null;
   12293         }
   12294         return findViewWithTagTraversal(tag);
   12295     }
   12296 
   12297     /**
   12298      * {@hide}
   12299      * Look for a child view that matches the specified predicate.
   12300      * If this view matches the predicate, return this view.
   12301      *
   12302      * @param predicate The predicate to evaluate.
   12303      * @return The first view that matches the predicate or null.
   12304      */
   12305     public final View findViewByPredicate(Predicate<View> predicate) {
   12306         return findViewByPredicateTraversal(predicate, null);
   12307     }
   12308 
   12309     /**
   12310      * {@hide}
   12311      * Look for a child view that matches the specified predicate,
   12312      * starting with the specified view and its descendents and then
   12313      * recusively searching the ancestors and siblings of that view
   12314      * until this view is reached.
   12315      *
   12316      * This method is useful in cases where the predicate does not match
   12317      * a single unique view (perhaps multiple views use the same id)
   12318      * and we are trying to find the view that is "closest" in scope to the
   12319      * starting view.
   12320      *
   12321      * @param start The view to start from.
   12322      * @param predicate The predicate to evaluate.
   12323      * @return The first view that matches the predicate or null.
   12324      */
   12325     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
   12326         View childToSkip = null;
   12327         for (;;) {
   12328             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
   12329             if (view != null || start == this) {
   12330                 return view;
   12331             }
   12332 
   12333             ViewParent parent = start.getParent();
   12334             if (parent == null || !(parent instanceof View)) {
   12335                 return null;
   12336             }
   12337 
   12338             childToSkip = start;
   12339             start = (View) parent;
   12340         }
   12341     }
   12342 
   12343     /**
   12344      * Sets the identifier for this view. The identifier does not have to be
   12345      * unique in this view's hierarchy. The identifier should be a positive
   12346      * number.
   12347      *
   12348      * @see #NO_ID
   12349      * @see #getId()
   12350      * @see #findViewById(int)
   12351      *
   12352      * @param id a number used to identify the view
   12353      *
   12354      * @attr ref android.R.styleable#View_id
   12355      */
   12356     public void setId(int id) {
   12357         mID = id;
   12358     }
   12359 
   12360     /**
   12361      * {@hide}
   12362      *
   12363      * @param isRoot true if the view belongs to the root namespace, false
   12364      *        otherwise
   12365      */
   12366     public void setIsRootNamespace(boolean isRoot) {
   12367         if (isRoot) {
   12368             mPrivateFlags |= IS_ROOT_NAMESPACE;
   12369         } else {
   12370             mPrivateFlags &= ~IS_ROOT_NAMESPACE;
   12371         }
   12372     }
   12373 
   12374     /**
   12375      * {@hide}
   12376      *
   12377      * @return true if the view belongs to the root namespace, false otherwise
   12378      */
   12379     public boolean isRootNamespace() {
   12380         return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
   12381     }
   12382 
   12383     /**
   12384      * Returns this view's identifier.
   12385      *
   12386      * @return a positive integer used to identify the view or {@link #NO_ID}
   12387      *         if the view has no ID
   12388      *
   12389      * @see #setId(int)
   12390      * @see #findViewById(int)
   12391      * @attr ref android.R.styleable#View_id
   12392      */
   12393     @ViewDebug.CapturedViewProperty
   12394     public int getId() {
   12395         return mID;
   12396     }
   12397 
   12398     /**
   12399      * Returns this view's tag.
   12400      *
   12401      * @return the Object stored in this view as a tag
   12402      *
   12403      * @see #setTag(Object)
   12404      * @see #getTag(int)
   12405      */
   12406     @ViewDebug.ExportedProperty
   12407     public Object getTag() {
   12408         return mTag;
   12409     }
   12410 
   12411     /**
   12412      * Sets the tag associated with this view. A tag can be used to mark
   12413      * a view in its hierarchy and does not have to be unique within the
   12414      * hierarchy. Tags can also be used to store data within a view without
   12415      * resorting to another data structure.
   12416      *
   12417      * @param tag an Object to tag the view with
   12418      *
   12419      * @see #getTag()
   12420      * @see #setTag(int, Object)
   12421      */
   12422     public void setTag(final Object tag) {
   12423         mTag = tag;
   12424     }
   12425 
   12426     /**
   12427      * Returns the tag associated with this view and the specified key.
   12428      *
   12429      * @param key The key identifying the tag
   12430      *
   12431      * @return the Object stored in this view as a tag
   12432      *
   12433      * @see #setTag(int, Object)
   12434      * @see #getTag()
   12435      */
   12436     public Object getTag(int key) {
   12437         if (mKeyedTags != null) return mKeyedTags.get(key);
   12438         return null;
   12439     }
   12440 
   12441     /**
   12442      * Sets a tag associated with this view and a key. A tag can be used
   12443      * to mark a view in its hierarchy and does not have to be unique within
   12444      * the hierarchy. Tags can also be used to store data within a view
   12445      * without resorting to another data structure.
   12446      *
   12447      * The specified key should be an id declared in the resources of the
   12448      * application to ensure it is unique (see the <a
   12449      * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
   12450      * Keys identified as belonging to
   12451      * the Android framework or not associated with any package will cause
   12452      * an {@link IllegalArgumentException} to be thrown.
   12453      *
   12454      * @param key The key identifying the tag
   12455      * @param tag An Object to tag the view with
   12456      *
   12457      * @throws IllegalArgumentException If they specified key is not valid
   12458      *
   12459      * @see #setTag(Object)
   12460      * @see #getTag(int)
   12461      */
   12462     public void setTag(int key, final Object tag) {
   12463         // If the package id is 0x00 or 0x01, it's either an undefined package
   12464         // or a framework id
   12465         if ((key >>> 24) < 2) {
   12466             throw new IllegalArgumentException("The key must be an application-specific "
   12467                     + "resource id.");
   12468         }
   12469 
   12470         setKeyedTag(key, tag);
   12471     }
   12472 
   12473     /**
   12474      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
   12475      * framework id.
   12476      *
   12477      * @hide
   12478      */
   12479     public void setTagInternal(int key, Object tag) {
   12480         if ((key >>> 24) != 0x1) {
   12481             throw new IllegalArgumentException("The key must be a framework-specific "
   12482                     + "resource id.");
   12483         }
   12484 
   12485         setKeyedTag(key, tag);
   12486     }
   12487 
   12488     private void setKeyedTag(int key, Object tag) {
   12489         if (mKeyedTags == null) {
   12490             mKeyedTags = new SparseArray<Object>();
   12491         }
   12492 
   12493         mKeyedTags.put(key, tag);
   12494     }
   12495 
   12496     /**
   12497      * @param consistency The type of consistency. See ViewDebug for more information.
   12498      *
   12499      * @hide
   12500      */
   12501     protected boolean dispatchConsistencyCheck(int consistency) {
   12502         return onConsistencyCheck(consistency);
   12503     }
   12504 
   12505     /**
   12506      * Method that subclasses should implement to check their consistency. The type of
   12507      * consistency check is indicated by the bit field passed as a parameter.
   12508      *
   12509      * @param consistency The type of consistency. See ViewDebug for more information.
   12510      *
   12511      * @throws IllegalStateException if the view is in an inconsistent state.
   12512      *
   12513      * @hide
   12514      */
   12515     protected boolean onConsistencyCheck(int consistency) {
   12516         boolean result = true;
   12517 
   12518         final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
   12519         final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
   12520 
   12521         if (checkLayout) {
   12522             if (getParent() == null) {
   12523                 result = false;
   12524                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
   12525                         "View " + this + " does not have a parent.");
   12526             }
   12527 
   12528             if (mAttachInfo == null) {
   12529                 result = false;
   12530                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
   12531                         "View " + this + " is not attached to a window.");
   12532             }
   12533         }
   12534 
   12535         if (checkDrawing) {
   12536             // Do not check the DIRTY/DRAWN flags because views can call invalidate()
   12537             // from their draw() method
   12538 
   12539             if ((mPrivateFlags & DRAWN) != DRAWN &&
   12540                     (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
   12541                 result = false;
   12542                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
   12543                         "View " + this + " was invalidated but its drawing cache is valid.");
   12544             }
   12545         }
   12546 
   12547         return result;
   12548     }
   12549 
   12550     /**
   12551      * Prints information about this view in the log output, with the tag
   12552      * {@link #VIEW_LOG_TAG}.
   12553      *
   12554      * @hide
   12555      */
   12556     public void debug() {
   12557         debug(0);
   12558     }
   12559 
   12560     /**
   12561      * Prints information about this view in the log output, with the tag
   12562      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
   12563      * indentation defined by the <code>depth</code>.
   12564      *
   12565      * @param depth the indentation level
   12566      *
   12567      * @hide
   12568      */
   12569     protected void debug(int depth) {
   12570         String output = debugIndent(depth - 1);
   12571 
   12572         output += "+ " + this;
   12573         int id = getId();
   12574         if (id != -1) {
   12575             output += " (id=" + id + ")";
   12576         }
   12577         Object tag = getTag();
   12578         if (tag != null) {
   12579             output += " (tag=" + tag + ")";
   12580         }
   12581         Log.d(VIEW_LOG_TAG, output);
   12582 
   12583         if ((mPrivateFlags & FOCUSED) != 0) {
   12584             output = debugIndent(depth) + " FOCUSED";
   12585             Log.d(VIEW_LOG_TAG, output);
   12586         }
   12587 
   12588         output = debugIndent(depth);
   12589         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
   12590                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
   12591                 + "} ";
   12592         Log.d(VIEW_LOG_TAG, output);
   12593 
   12594         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
   12595                 || mPaddingBottom != 0) {
   12596             output = debugIndent(depth);
   12597             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
   12598                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
   12599             Log.d(VIEW_LOG_TAG, output);
   12600         }
   12601 
   12602         output = debugIndent(depth);
   12603         output += "mMeasureWidth=" + mMeasuredWidth +
   12604                 " mMeasureHeight=" + mMeasuredHeight;
   12605         Log.d(VIEW_LOG_TAG, output);
   12606 
   12607         output = debugIndent(depth);
   12608         if (mLayoutParams == null) {
   12609             output += "BAD! no layout params";
   12610         } else {
   12611             output = mLayoutParams.debug(output);
   12612         }
   12613         Log.d(VIEW_LOG_TAG, output);
   12614 
   12615         output = debugIndent(depth);
   12616         output += "flags={";
   12617         output += View.printFlags(mViewFlags);
   12618         output += "}";
   12619         Log.d(VIEW_LOG_TAG, output);
   12620 
   12621         output = debugIndent(depth);
   12622         output += "privateFlags={";
   12623         output += View.printPrivateFlags(mPrivateFlags);
   12624         output += "}";
   12625         Log.d(VIEW_LOG_TAG, output);
   12626     }
   12627 
   12628     /**
   12629      * Creates an string of whitespaces used for indentation.
   12630      *
   12631      * @param depth the indentation level
   12632      * @return a String containing (depth * 2 + 3) * 2 white spaces
   12633      *
   12634      * @hide
   12635      */
   12636     protected static String debugIndent(int depth) {
   12637         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
   12638         for (int i = 0; i < (depth * 2) + 3; i++) {
   12639             spaces.append(' ').append(' ');
   12640         }
   12641         return spaces.toString();
   12642     }
   12643 
   12644     /**
   12645      * <p>Return the offset of the widget's text baseline from the widget's top
   12646      * boundary. If this widget does not support baseline alignment, this
   12647      * method returns -1. </p>
   12648      *
   12649      * @return the offset of the baseline within the widget's bounds or -1
   12650      *         if baseline alignment is not supported
   12651      */
   12652     @ViewDebug.ExportedProperty(category = "layout")
   12653     public int getBaseline() {
   12654         return -1;
   12655     }
   12656 
   12657     /**
   12658      * Call this when something has changed which has invalidated the
   12659      * layout of this view. This will schedule a layout pass of the view
   12660      * tree.
   12661      */
   12662     public void requestLayout() {
   12663         if (ViewDebug.TRACE_HIERARCHY) {
   12664             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
   12665         }
   12666 
   12667         mPrivateFlags |= FORCE_LAYOUT;
   12668         mPrivateFlags |= INVALIDATED;
   12669 
   12670         if (mParent != null) {
   12671             if (mLayoutParams != null) {
   12672                 mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
   12673             }
   12674             if (!mParent.isLayoutRequested()) {
   12675                 mParent.requestLayout();
   12676             }
   12677         }
   12678     }
   12679 
   12680     /**
   12681      * Forces this view to be laid out during the next layout pass.
   12682      * This method does not call requestLayout() or forceLayout()
   12683      * on the parent.
   12684      */
   12685     public void forceLayout() {
   12686         mPrivateFlags |= FORCE_LAYOUT;
   12687         mPrivateFlags |= INVALIDATED;
   12688     }
   12689 
   12690     /**
   12691      * <p>
   12692      * This is called to find out how big a view should be. The parent
   12693      * supplies constraint information in the width and height parameters.
   12694      * </p>
   12695      *
   12696      * <p>
   12697      * The actual mesurement work of a view is performed in
   12698      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
   12699      * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
   12700      * </p>
   12701      *
   12702      *
   12703      * @param widthMeasureSpec Horizontal space requirements as imposed by the
   12704      *        parent
   12705      * @param heightMeasureSpec Vertical space requirements as imposed by the
   12706      *        parent
   12707      *
   12708      * @see #onMeasure(int, int)
   12709      */
   12710     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
   12711         if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
   12712                 widthMeasureSpec != mOldWidthMeasureSpec ||
   12713                 heightMeasureSpec != mOldHeightMeasureSpec) {
   12714 
   12715             // first clears the measured dimension flag
   12716             mPrivateFlags &= ~MEASURED_DIMENSION_SET;
   12717 
   12718             if (ViewDebug.TRACE_HIERARCHY) {
   12719                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
   12720             }
   12721 
   12722             // measure ourselves, this should set the measured dimension flag back
   12723             onMeasure(widthMeasureSpec, heightMeasureSpec);
   12724 
   12725             // flag not set, setMeasuredDimension() was not invoked, we raise
   12726             // an exception to warn the developer
   12727             if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
   12728                 throw new IllegalStateException("onMeasure() did not set the"
   12729                         + " measured dimension by calling"
   12730                         + " setMeasuredDimension()");
   12731             }
   12732 
   12733             mPrivateFlags |= LAYOUT_REQUIRED;
   12734         }
   12735 
   12736         mOldWidthMeasureSpec = widthMeasureSpec;
   12737         mOldHeightMeasureSpec = heightMeasureSpec;
   12738     }
   12739 
   12740     /**
   12741      * <p>
   12742      * Measure the view and its content to determine the measured width and the
   12743      * measured height. This method is invoked by {@link #measure(int, int)} and
   12744      * should be overriden by subclasses to provide accurate and efficient
   12745      * measurement of their contents.
   12746      * </p>
   12747      *
   12748      * <p>
   12749      * <strong>CONTRACT:</strong> When overriding this method, you
   12750      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
   12751      * measured width and height of this view. Failure to do so will trigger an
   12752      * <code>IllegalStateException</code>, thrown by
   12753      * {@link #measure(int, int)}. Calling the superclass'
   12754      * {@link #onMeasure(int, int)} is a valid use.
   12755      * </p>
   12756      *
   12757      * <p>
   12758      * The base class implementation of measure defaults to the background size,
   12759      * unless a larger size is allowed by the MeasureSpec. Subclasses should
   12760      * override {@link #onMeasure(int, int)} to provide better measurements of
   12761      * their content.
   12762      * </p>
   12763      *
   12764      * <p>
   12765      * If this method is overridden, it is the subclass's responsibility to make
   12766      * sure the measured height and width are at least the view's minimum height
   12767      * and width ({@link #getSuggestedMinimumHeight()} and
   12768      * {@link #getSuggestedMinimumWidth()}).
   12769      * </p>
   12770      *
   12771      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
   12772      *                         The requirements are encoded with
   12773      *                         {@link android.view.View.MeasureSpec}.
   12774      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
   12775      *                         The requirements are encoded with
   12776      *                         {@link android.view.View.MeasureSpec}.
   12777      *
   12778      * @see #getMeasuredWidth()
   12779      * @see #getMeasuredHeight()
   12780      * @see #setMeasuredDimension(int, int)
   12781      * @see #getSuggestedMinimumHeight()
   12782      * @see #getSuggestedMinimumWidth()
   12783      * @see android.view.View.MeasureSpec#getMode(int)
   12784      * @see android.view.View.MeasureSpec#getSize(int)
   12785      */
   12786     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   12787         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
   12788                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
   12789     }
   12790 
   12791     /**
   12792      * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
   12793      * measured width and measured height. Failing to do so will trigger an
   12794      * exception at measurement time.</p>
   12795      *
   12796      * @param measuredWidth The measured width of this view.  May be a complex
   12797      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   12798      * {@link #MEASURED_STATE_TOO_SMALL}.
   12799      * @param measuredHeight The measured height of this view.  May be a complex
   12800      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   12801      * {@link #MEASURED_STATE_TOO_SMALL}.
   12802      */
   12803     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
   12804         mMeasuredWidth = measuredWidth;
   12805         mMeasuredHeight = measuredHeight;
   12806 
   12807         mPrivateFlags |= MEASURED_DIMENSION_SET;
   12808     }
   12809 
   12810     /**
   12811      * Merge two states as returned by {@link #getMeasuredState()}.
   12812      * @param curState The current state as returned from a view or the result
   12813      * of combining multiple views.
   12814      * @param newState The new view state to combine.
   12815      * @return Returns a new integer reflecting the combination of the two
   12816      * states.
   12817      */
   12818     public static int combineMeasuredStates(int curState, int newState) {
   12819         return curState | newState;
   12820     }
   12821 
   12822     /**
   12823      * Version of {@link #resolveSizeAndState(int, int, int)}
   12824      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
   12825      */
   12826     public static int resolveSize(int size, int measureSpec) {
   12827         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
   12828     }
   12829 
   12830     /**
   12831      * Utility to reconcile a desired size and state, with constraints imposed
   12832      * by a MeasureSpec.  Will take the desired size, unless a different size
   12833      * is imposed by the constraints.  The returned value is a compound integer,
   12834      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
   12835      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
   12836      * size is smaller than the size the view wants to be.
   12837      *
   12838      * @param size How big the view wants to be
   12839      * @param measureSpec Constraints imposed by the parent
   12840      * @return Size information bit mask as defined by
   12841      * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   12842      */
   12843     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
   12844         int result = size;
   12845         int specMode = MeasureSpec.getMode(measureSpec);
   12846         int specSize =  MeasureSpec.getSize(measureSpec);
   12847         switch (specMode) {
   12848         case MeasureSpec.UNSPECIFIED:
   12849             result = size;
   12850             break;
   12851         case MeasureSpec.AT_MOST:
   12852             if (specSize < size) {
   12853                 result = specSize | MEASURED_STATE_TOO_SMALL;
   12854             } else {
   12855                 result = size;
   12856             }
   12857             break;
   12858         case MeasureSpec.EXACTLY:
   12859             result = specSize;
   12860             break;
   12861         }
   12862         return result | (childMeasuredState&MEASURED_STATE_MASK);
   12863     }
   12864 
   12865     /**
   12866      * Utility to return a default size. Uses the supplied size if the
   12867      * MeasureSpec imposed no constraints. Will get larger if allowed
   12868      * by the MeasureSpec.
   12869      *
   12870      * @param size Default size for this view
   12871      * @param measureSpec Constraints imposed by the parent
   12872      * @return The size this view should be.
   12873      */
   12874     public static int getDefaultSize(int size, int measureSpec) {
   12875         int result = size;
   12876         int specMode = MeasureSpec.getMode(measureSpec);
   12877         int specSize = MeasureSpec.getSize(measureSpec);
   12878 
   12879         switch (specMode) {
   12880         case MeasureSpec.UNSPECIFIED:
   12881             result = size;
   12882             break;
   12883         case MeasureSpec.AT_MOST:
   12884         case MeasureSpec.EXACTLY:
   12885             result = specSize;
   12886             break;
   12887         }
   12888         return result;
   12889     }
   12890 
   12891     /**
   12892      * Returns the suggested minimum height that the view should use. This
   12893      * returns the maximum of the view's minimum height
   12894      * and the background's minimum height
   12895      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
   12896      * <p>
   12897      * When being used in {@link #onMeasure(int, int)}, the caller should still
   12898      * ensure the returned height is within the requirements of the parent.
   12899      *
   12900      * @return The suggested minimum height of the view.
   12901      */
   12902     protected int getSuggestedMinimumHeight() {
   12903         int suggestedMinHeight = mMinHeight;
   12904 
   12905         if (mBGDrawable != null) {
   12906             final int bgMinHeight = mBGDrawable.getMinimumHeight();
   12907             if (suggestedMinHeight < bgMinHeight) {
   12908                 suggestedMinHeight = bgMinHeight;
   12909             }
   12910         }
   12911 
   12912         return suggestedMinHeight;
   12913     }
   12914 
   12915     /**
   12916      * Returns the suggested minimum width that the view should use. This
   12917      * returns the maximum of the view's minimum width)
   12918      * and the background's minimum width
   12919      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
   12920      * <p>
   12921      * When being used in {@link #onMeasure(int, int)}, the caller should still
   12922      * ensure the returned width is within the requirements of the parent.
   12923      *
   12924      * @return The suggested minimum width of the view.
   12925      */
   12926     protected int getSuggestedMinimumWidth() {
   12927         int suggestedMinWidth = mMinWidth;
   12928 
   12929         if (mBGDrawable != null) {
   12930             final int bgMinWidth = mBGDrawable.getMinimumWidth();
   12931             if (suggestedMinWidth < bgMinWidth) {
   12932                 suggestedMinWidth = bgMinWidth;
   12933             }
   12934         }
   12935 
   12936         return suggestedMinWidth;
   12937     }
   12938 
   12939     /**
   12940      * Sets the minimum height of the view. It is not guaranteed the view will
   12941      * be able to achieve this minimum height (for example, if its parent layout
   12942      * constrains it with less available height).
   12943      *
   12944      * @param minHeight The minimum height the view will try to be.
   12945      */
   12946     public void setMinimumHeight(int minHeight) {
   12947         mMinHeight = minHeight;
   12948     }
   12949 
   12950     /**
   12951      * Sets the minimum width of the view. It is not guaranteed the view will
   12952      * be able to achieve this minimum width (for example, if its parent layout
   12953      * constrains it with less available width).
   12954      *
   12955      * @param minWidth The minimum width the view will try to be.
   12956      */
   12957     public void setMinimumWidth(int minWidth) {
   12958         mMinWidth = minWidth;
   12959     }
   12960 
   12961     /**
   12962      * Get the animation currently associated with this view.
   12963      *
   12964      * @return The animation that is currently playing or
   12965      *         scheduled to play for this view.
   12966      */
   12967     public Animation getAnimation() {
   12968         return mCurrentAnimation;
   12969     }
   12970 
   12971     /**
   12972      * Start the specified animation now.
   12973      *
   12974      * @param animation the animation to start now
   12975      */
   12976     public void startAnimation(Animation animation) {
   12977         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
   12978         setAnimation(animation);
   12979         invalidateParentCaches();
   12980         invalidate(true);
   12981     }
   12982 
   12983     /**
   12984      * Cancels any animations for this view.
   12985      */
   12986     public void clearAnimation() {
   12987         if (mCurrentAnimation != null) {
   12988             mCurrentAnimation.detach();
   12989         }
   12990         mCurrentAnimation = null;
   12991         invalidateParentIfNeeded();
   12992     }
   12993 
   12994     /**
   12995      * Sets the next animation to play for this view.
   12996      * If you want the animation to play immediately, use
   12997      * startAnimation. This method provides allows fine-grained
   12998      * control over the start time and invalidation, but you
   12999      * must make sure that 1) the animation has a start time set, and
   13000      * 2) the view will be invalidated when the animation is supposed to
   13001      * start.
   13002      *
   13003      * @param animation The next animation, or null.
   13004      */
   13005     public void setAnimation(Animation animation) {
   13006         mCurrentAnimation = animation;
   13007         if (animation != null) {
   13008             animation.reset();
   13009         }
   13010     }
   13011 
   13012     /**
   13013      * Invoked by a parent ViewGroup to notify the start of the animation
   13014      * currently associated with this view. If you override this method,
   13015      * always call super.onAnimationStart();
   13016      *
   13017      * @see #setAnimation(android.view.animation.Animation)
   13018      * @see #getAnimation()
   13019      */
   13020     protected void onAnimationStart() {
   13021         mPrivateFlags |= ANIMATION_STARTED;
   13022     }
   13023 
   13024     /**
   13025      * Invoked by a parent ViewGroup to notify the end of the animation
   13026      * currently associated with this view. If you override this method,
   13027      * always call super.onAnimationEnd();
   13028      *
   13029      * @see #setAnimation(android.view.animation.Animation)
   13030      * @see #getAnimation()
   13031      */
   13032     protected void onAnimationEnd() {
   13033         mPrivateFlags &= ~ANIMATION_STARTED;
   13034     }
   13035 
   13036     /**
   13037      * Invoked if there is a Transform that involves alpha. Subclass that can
   13038      * draw themselves with the specified alpha should return true, and then
   13039      * respect that alpha when their onDraw() is called. If this returns false
   13040      * then the view may be redirected to draw into an offscreen buffer to
   13041      * fulfill the request, which will look fine, but may be slower than if the
   13042      * subclass handles it internally. The default implementation returns false.
   13043      *
   13044      * @param alpha The alpha (0..255) to apply to the view's drawing
   13045      * @return true if the view can draw with the specified alpha.
   13046      */
   13047     protected boolean onSetAlpha(int alpha) {
   13048         return false;
   13049     }
   13050 
   13051     /**
   13052      * This is used by the RootView to perform an optimization when
   13053      * the view hierarchy contains one or several SurfaceView.
   13054      * SurfaceView is always considered transparent, but its children are not,
   13055      * therefore all View objects remove themselves from the global transparent
   13056      * region (passed as a parameter to this function).
   13057      *
   13058      * @param region The transparent region for this ViewAncestor (window).
   13059      *
   13060      * @return Returns true if the effective visibility of the view at this
   13061      * point is opaque, regardless of the transparent region; returns false
   13062      * if it is possible for underlying windows to be seen behind the view.
   13063      *
   13064      * {@hide}
   13065      */
   13066     public boolean gatherTransparentRegion(Region region) {
   13067         final AttachInfo attachInfo = mAttachInfo;
   13068         if (region != null && attachInfo != null) {
   13069             final int pflags = mPrivateFlags;
   13070             if ((pflags & SKIP_DRAW) == 0) {
   13071                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
   13072                 // remove it from the transparent region.
   13073                 final int[] location = attachInfo.mTransparentLocation;
   13074                 getLocationInWindow(location);
   13075                 region.op(location[0], location[1], location[0] + mRight - mLeft,
   13076                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
   13077             } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
   13078                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
   13079                 // exists, so we remove the background drawable's non-transparent
   13080                 // parts from this transparent region.
   13081                 applyDrawableToTransparentRegion(mBGDrawable, region);
   13082             }
   13083         }
   13084         return true;
   13085     }
   13086 
   13087     /**
   13088      * Play a sound effect for this view.
   13089      *
   13090      * <p>The framework will play sound effects for some built in actions, such as
   13091      * clicking, but you may wish to play these effects in your widget,
   13092      * for instance, for internal navigation.
   13093      *
   13094      * <p>The sound effect will only be played if sound effects are enabled by the user, and
   13095      * {@link #isSoundEffectsEnabled()} is true.
   13096      *
   13097      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
   13098      */
   13099     public void playSoundEffect(int soundConstant) {
   13100         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
   13101             return;
   13102         }
   13103         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
   13104     }
   13105 
   13106     /**
   13107      * BZZZTT!!1!
   13108      *
   13109      * <p>Provide haptic feedback to the user for this view.
   13110      *
   13111      * <p>The framework will provide haptic feedback for some built in actions,
   13112      * such as long presses, but you may wish to provide feedback for your
   13113      * own widget.
   13114      *
   13115      * <p>The feedback will only be performed if
   13116      * {@link #isHapticFeedbackEnabled()} is true.
   13117      *
   13118      * @param feedbackConstant One of the constants defined in
   13119      * {@link HapticFeedbackConstants}
   13120      */
   13121     public boolean performHapticFeedback(int feedbackConstant) {
   13122         return performHapticFeedback(feedbackConstant, 0);
   13123     }
   13124 
   13125     /**
   13126      * BZZZTT!!1!
   13127      *
   13128      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
   13129      *
   13130      * @param feedbackConstant One of the constants defined in
   13131      * {@link HapticFeedbackConstants}
   13132      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
   13133      */
   13134     public boolean performHapticFeedback(int feedbackConstant, int flags) {
   13135         if (mAttachInfo == null) {
   13136             return false;
   13137         }
   13138         //noinspection SimplifiableIfStatement
   13139         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
   13140                 && !isHapticFeedbackEnabled()) {
   13141             return false;
   13142         }
   13143         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
   13144                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
   13145     }
   13146 
   13147     /**
   13148      * Request that the visibility of the status bar be changed.
   13149      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
   13150      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
   13151      */
   13152     public void setSystemUiVisibility(int visibility) {
   13153         if (visibility != mSystemUiVisibility) {
   13154             mSystemUiVisibility = visibility;
   13155             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   13156                 mParent.recomputeViewAttributes(this);
   13157             }
   13158         }
   13159     }
   13160 
   13161     /**
   13162      * Returns the status bar visibility that this view has requested.
   13163      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
   13164      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
   13165      */
   13166     public int getSystemUiVisibility() {
   13167         return mSystemUiVisibility;
   13168     }
   13169 
   13170     /**
   13171      * Set a listener to receive callbacks when the visibility of the system bar changes.
   13172      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
   13173      */
   13174     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
   13175         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
   13176         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   13177             mParent.recomputeViewAttributes(this);
   13178         }
   13179     }
   13180 
   13181     /**
   13182      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
   13183      * the view hierarchy.
   13184      */
   13185     public void dispatchSystemUiVisibilityChanged(int visibility) {
   13186         ListenerInfo li = mListenerInfo;
   13187         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   13188             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
   13189                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
   13190         }
   13191     }
   13192 
   13193     void updateLocalSystemUiVisibility(int localValue, int localChanges) {
   13194         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
   13195         if (val != mSystemUiVisibility) {
   13196             setSystemUiVisibility(val);
   13197         }
   13198     }
   13199 
   13200     /**
   13201      * Creates an image that the system displays during the drag and drop
   13202      * operation. This is called a &quot;drag shadow&quot;. The default implementation
   13203      * for a DragShadowBuilder based on a View returns an image that has exactly the same
   13204      * appearance as the given View. The default also positions the center of the drag shadow
   13205      * directly under the touch point. If no View is provided (the constructor with no parameters
   13206      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
   13207      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
   13208      * default is an invisible drag shadow.
   13209      * <p>
   13210      * You are not required to use the View you provide to the constructor as the basis of the
   13211      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
   13212      * anything you want as the drag shadow.
   13213      * </p>
   13214      * <p>
   13215      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
   13216      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
   13217      *  size and position of the drag shadow. It uses this data to construct a
   13218      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
   13219      *  so that your application can draw the shadow image in the Canvas.
   13220      * </p>
   13221      *
   13222      * <div class="special reference">
   13223      * <h3>Developer Guides</h3>
   13224      * <p>For a guide to implementing drag and drop features, read the
   13225      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   13226      * </div>
   13227      */
   13228     public static class DragShadowBuilder {
   13229         private final WeakReference<View> mView;
   13230 
   13231         /**
   13232          * Constructs a shadow image builder based on a View. By default, the resulting drag
   13233          * shadow will have the same appearance and dimensions as the View, with the touch point
   13234          * over the center of the View.
   13235          * @param view A View. Any View in scope can be used.
   13236          */
   13237         public DragShadowBuilder(View view) {
   13238             mView = new WeakReference<View>(view);
   13239         }
   13240 
   13241         /**
   13242          * Construct a shadow builder object with no associated View.  This
   13243          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
   13244          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
   13245          * to supply the drag shadow's dimensions and appearance without
   13246          * reference to any View object. If they are not overridden, then the result is an
   13247          * invisible drag shadow.
   13248          */
   13249         public DragShadowBuilder() {
   13250             mView = new WeakReference<View>(null);
   13251         }
   13252 
   13253         /**
   13254          * Returns the View object that had been passed to the
   13255          * {@link #View.DragShadowBuilder(View)}
   13256          * constructor.  If that View parameter was {@code null} or if the
   13257          * {@link #View.DragShadowBuilder()}
   13258          * constructor was used to instantiate the builder object, this method will return
   13259          * null.
   13260          *
   13261          * @return The View object associate with this builder object.
   13262          */
   13263         @SuppressWarnings({"JavadocReference"})
   13264         final public View getView() {
   13265             return mView.get();
   13266         }
   13267 
   13268         /**
   13269          * Provides the metrics for the shadow image. These include the dimensions of
   13270          * the shadow image, and the point within that shadow that should
   13271          * be centered under the touch location while dragging.
   13272          * <p>
   13273          * The default implementation sets the dimensions of the shadow to be the
   13274          * same as the dimensions of the View itself and centers the shadow under
   13275          * the touch point.
   13276          * </p>
   13277          *
   13278          * @param shadowSize A {@link android.graphics.Point} containing the width and height
   13279          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
   13280          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
   13281          * image.
   13282          *
   13283          * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
   13284          * shadow image that should be underneath the touch point during the drag and drop
   13285          * operation. Your application must set {@link android.graphics.Point#x} to the
   13286          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
   13287          */
   13288         public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
   13289             final View view = mView.get();
   13290             if (view != null) {
   13291                 shadowSize.set(view.getWidth(), view.getHeight());
   13292                 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
   13293             } else {
   13294                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
   13295             }
   13296         }
   13297 
   13298         /**
   13299          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
   13300          * based on the dimensions it received from the
   13301          * {@link #onProvideShadowMetrics(Point, Point)} callback.
   13302          *
   13303          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
   13304          */
   13305         public void onDrawShadow(Canvas canvas) {
   13306             final View view = mView.get();
   13307             if (view != null) {
   13308                 view.draw(canvas);
   13309             } else {
   13310                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
   13311             }
   13312         }
   13313     }
   13314 
   13315     /**
   13316      * Starts a drag and drop operation. When your application calls this method, it passes a
   13317      * {@link android.view.View.DragShadowBuilder} object to the system. The
   13318      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
   13319      * to get metrics for the drag shadow, and then calls the object's
   13320      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
   13321      * <p>
   13322      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
   13323      *  drag events to all the View objects in your application that are currently visible. It does
   13324      *  this either by calling the View object's drag listener (an implementation of
   13325      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
   13326      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
   13327      *  Both are passed a {@link android.view.DragEvent} object that has a
   13328      *  {@link android.view.DragEvent#getAction()} value of
   13329      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
   13330      * </p>
   13331      * <p>
   13332      * Your application can invoke startDrag() on any attached View object. The View object does not
   13333      * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
   13334      * be related to the View the user selected for dragging.
   13335      * </p>
   13336      * @param data A {@link android.content.ClipData} object pointing to the data to be
   13337      * transferred by the drag and drop operation.
   13338      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   13339      * drag shadow.
   13340      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
   13341      * drop operation. This Object is put into every DragEvent object sent by the system during the
   13342      * current drag.
   13343      * <p>
   13344      * myLocalState is a lightweight mechanism for the sending information from the dragged View
   13345      * to the target Views. For example, it can contain flags that differentiate between a
   13346      * a copy operation and a move operation.
   13347      * </p>
   13348      * @param flags Flags that control the drag and drop operation. No flags are currently defined,
   13349      * so the parameter should be set to 0.
   13350      * @return {@code true} if the method completes successfully, or
   13351      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
   13352      * do a drag, and so no drag operation is in progress.
   13353      */
   13354     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
   13355             Object myLocalState, int flags) {
   13356         if (ViewDebug.DEBUG_DRAG) {
   13357             Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
   13358         }
   13359         boolean okay = false;
   13360 
   13361         Point shadowSize = new Point();
   13362         Point shadowTouchPoint = new Point();
   13363         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
   13364 
   13365         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
   13366                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
   13367             throw new IllegalStateException("Drag shadow dimensions must not be negative");
   13368         }
   13369 
   13370         if (ViewDebug.DEBUG_DRAG) {
   13371             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
   13372                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
   13373         }
   13374         Surface surface = new Surface();
   13375         try {
   13376             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
   13377                     flags, shadowSize.x, shadowSize.y, surface);
   13378             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
   13379                     + " surface=" + surface);
   13380             if (token != null) {
   13381                 Canvas canvas = surface.lockCanvas(null);
   13382                 try {
   13383                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   13384                     shadowBuilder.onDrawShadow(canvas);
   13385                 } finally {
   13386                     surface.unlockCanvasAndPost(canvas);
   13387                 }
   13388 
   13389                 final ViewRootImpl root = getViewRootImpl();
   13390 
   13391                 // Cache the local state object for delivery with DragEvents
   13392                 root.setLocalDragState(myLocalState);
   13393 
   13394                 // repurpose 'shadowSize' for the last touch point
   13395                 root.getLastTouchPoint(shadowSize);
   13396 
   13397                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
   13398                         shadowSize.x, shadowSize.y,
   13399                         shadowTouchPoint.x, shadowTouchPoint.y, data);
   13400                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
   13401 
   13402                 // Off and running!  Release our local surface instance; the drag
   13403                 // shadow surface is now managed by the system process.
   13404                 surface.release();
   13405             }
   13406         } catch (Exception e) {
   13407             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
   13408             surface.destroy();
   13409         }
   13410 
   13411         return okay;
   13412     }
   13413 
   13414     /**
   13415      * Handles drag events sent by the system following a call to
   13416      * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
   13417      *<p>
   13418      * When the system calls this method, it passes a
   13419      * {@link android.view.DragEvent} object. A call to
   13420      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
   13421      * in DragEvent. The method uses these to determine what is happening in the drag and drop
   13422      * operation.
   13423      * @param event The {@link android.view.DragEvent} sent by the system.
   13424      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
   13425      * in DragEvent, indicating the type of drag event represented by this object.
   13426      * @return {@code true} if the method was successful, otherwise {@code false}.
   13427      * <p>
   13428      *  The method should return {@code true} in response to an action type of
   13429      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
   13430      *  operation.
   13431      * </p>
   13432      * <p>
   13433      *  The method should also return {@code true} in response to an action type of
   13434      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
   13435      *  {@code false} if it didn't.
   13436      * </p>
   13437      */
   13438     public boolean onDragEvent(DragEvent event) {
   13439         return false;
   13440     }
   13441 
   13442     /**
   13443      * Detects if this View is enabled and has a drag event listener.
   13444      * If both are true, then it calls the drag event listener with the
   13445      * {@link android.view.DragEvent} it received. If the drag event listener returns
   13446      * {@code true}, then dispatchDragEvent() returns {@code true}.
   13447      * <p>
   13448      * For all other cases, the method calls the
   13449      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
   13450      * method and returns its result.
   13451      * </p>
   13452      * <p>
   13453      * This ensures that a drag event is always consumed, even if the View does not have a drag
   13454      * event listener. However, if the View has a listener and the listener returns true, then
   13455      * onDragEvent() is not called.
   13456      * </p>
   13457      */
   13458     public boolean dispatchDragEvent(DragEvent event) {
   13459         //noinspection SimplifiableIfStatement
   13460         ListenerInfo li = mListenerInfo;
   13461         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   13462                 && li.mOnDragListener.onDrag(this, event)) {
   13463             return true;
   13464         }
   13465         return onDragEvent(event);
   13466     }
   13467 
   13468     boolean canAcceptDrag() {
   13469         return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
   13470     }
   13471 
   13472     /**
   13473      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
   13474      * it is ever exposed at all.
   13475      * @hide
   13476      */
   13477     public void onCloseSystemDialogs(String reason) {
   13478     }
   13479 
   13480     /**
   13481      * Given a Drawable whose bounds have been set to draw into this view,
   13482      * update a Region being computed for
   13483      * {@link #gatherTransparentRegion(android.graphics.Region)} so
   13484      * that any non-transparent parts of the Drawable are removed from the
   13485      * given transparent region.
   13486      *
   13487      * @param dr The Drawable whose transparency is to be applied to the region.
   13488      * @param region A Region holding the current transparency information,
   13489      * where any parts of the region that are set are considered to be
   13490      * transparent.  On return, this region will be modified to have the
   13491      * transparency information reduced by the corresponding parts of the
   13492      * Drawable that are not transparent.
   13493      * {@hide}
   13494      */
   13495     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
   13496         if (DBG) {
   13497             Log.i("View", "Getting transparent region for: " + this);
   13498         }
   13499         final Region r = dr.getTransparentRegion();
   13500         final Rect db = dr.getBounds();
   13501         final AttachInfo attachInfo = mAttachInfo;
   13502         if (r != null && attachInfo != null) {
   13503             final int w = getRight()-getLeft();
   13504             final int h = getBottom()-getTop();
   13505             if (db.left > 0) {
   13506                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
   13507                 r.op(0, 0, db.left, h, Region.Op.UNION);
   13508             }
   13509             if (db.right < w) {
   13510                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
   13511                 r.op(db.right, 0, w, h, Region.Op.UNION);
   13512             }
   13513             if (db.top > 0) {
   13514                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
   13515                 r.op(0, 0, w, db.top, Region.Op.UNION);
   13516             }
   13517             if (db.bottom < h) {
   13518                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
   13519                 r.op(0, db.bottom, w, h, Region.Op.UNION);
   13520             }
   13521             final int[] location = attachInfo.mTransparentLocation;
   13522             getLocationInWindow(location);
   13523             r.translate(location[0], location[1]);
   13524             region.op(r, Region.Op.INTERSECT);
   13525         } else {
   13526             region.op(db, Region.Op.DIFFERENCE);
   13527         }
   13528     }
   13529 
   13530     private void checkForLongClick(int delayOffset) {
   13531         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
   13532             mHasPerformedLongPress = false;
   13533 
   13534             if (mPendingCheckForLongPress == null) {
   13535                 mPendingCheckForLongPress = new CheckForLongPress();
   13536             }
   13537             mPendingCheckForLongPress.rememberWindowAttachCount();
   13538             postDelayed(mPendingCheckForLongPress,
   13539                     ViewConfiguration.getLongPressTimeout() - delayOffset);
   13540         }
   13541     }
   13542 
   13543     /**
   13544      * Inflate a view from an XML resource.  This convenience method wraps the {@link
   13545      * LayoutInflater} class, which provides a full range of options for view inflation.
   13546      *
   13547      * @param context The Context object for your activity or application.
   13548      * @param resource The resource ID to inflate
   13549      * @param root A view group that will be the parent.  Used to properly inflate the
   13550      * layout_* parameters.
   13551      * @see LayoutInflater
   13552      */
   13553     public static View inflate(Context context, int resource, ViewGroup root) {
   13554         LayoutInflater factory = LayoutInflater.from(context);
   13555         return factory.inflate(resource, root);
   13556     }
   13557 
   13558     /**
   13559      * Scroll the view with standard behavior for scrolling beyond the normal
   13560      * content boundaries. Views that call this method should override
   13561      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
   13562      * results of an over-scroll operation.
   13563      *
   13564      * Views can use this method to handle any touch or fling-based scrolling.
   13565      *
   13566      * @param deltaX Change in X in pixels
   13567      * @param deltaY Change in Y in pixels
   13568      * @param scrollX Current X scroll value in pixels before applying deltaX
   13569      * @param scrollY Current Y scroll value in pixels before applying deltaY
   13570      * @param scrollRangeX Maximum content scroll range along the X axis
   13571      * @param scrollRangeY Maximum content scroll range along the Y axis
   13572      * @param maxOverScrollX Number of pixels to overscroll by in either direction
   13573      *          along the X axis.
   13574      * @param maxOverScrollY Number of pixels to overscroll by in either direction
   13575      *          along the Y axis.
   13576      * @param isTouchEvent true if this scroll operation is the result of a touch event.
   13577      * @return true if scrolling was clamped to an over-scroll boundary along either
   13578      *          axis, false otherwise.
   13579      */
   13580     @SuppressWarnings({"UnusedParameters"})
   13581     protected boolean overScrollBy(int deltaX, int deltaY,
   13582             int scrollX, int scrollY,
   13583             int scrollRangeX, int scrollRangeY,
   13584             int maxOverScrollX, int maxOverScrollY,
   13585             boolean isTouchEvent) {
   13586         final int overScrollMode = mOverScrollMode;
   13587         final boolean canScrollHorizontal =
   13588                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
   13589         final boolean canScrollVertical =
   13590                 computeVerticalScrollRange() > computeVerticalScrollExtent();
   13591         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
   13592                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
   13593         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
   13594                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
   13595 
   13596         int newScrollX = scrollX + deltaX;
   13597         if (!overScrollHorizontal) {
   13598             maxOverScrollX = 0;
   13599         }
   13600 
   13601         int newScrollY = scrollY + deltaY;
   13602         if (!overScrollVertical) {
   13603             maxOverScrollY = 0;
   13604         }
   13605 
   13606         // Clamp values if at the limits and record
   13607         final int left = -maxOverScrollX;
   13608         final int right = maxOverScrollX + scrollRangeX;
   13609         final int top = -maxOverScrollY;
   13610         final int bottom = maxOverScrollY + scrollRangeY;
   13611 
   13612         boolean clampedX = false;
   13613         if (newScrollX > right) {
   13614             newScrollX = right;
   13615             clampedX = true;
   13616         } else if (newScrollX < left) {
   13617             newScrollX = left;
   13618             clampedX = true;
   13619         }
   13620 
   13621         boolean clampedY = false;
   13622         if (newScrollY > bottom) {
   13623             newScrollY = bottom;
   13624             clampedY = true;
   13625         } else if (newScrollY < top) {
   13626             newScrollY = top;
   13627             clampedY = true;
   13628         }
   13629 
   13630         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
   13631 
   13632         return clampedX || clampedY;
   13633     }
   13634 
   13635     /**
   13636      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
   13637      * respond to the results of an over-scroll operation.
   13638      *
   13639      * @param scrollX New X scroll value in pixels
   13640      * @param scrollY New Y scroll value in pixels
   13641      * @param clampedX True if scrollX was clamped to an over-scroll boundary
   13642      * @param clampedY True if scrollY was clamped to an over-scroll boundary
   13643      */
   13644     protected void onOverScrolled(int scrollX, int scrollY,
   13645             boolean clampedX, boolean clampedY) {
   13646         // Intentionally empty.
   13647     }
   13648 
   13649     /**
   13650      * Returns the over-scroll mode for this view. The result will be
   13651      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   13652      * (allow over-scrolling only if the view content is larger than the container),
   13653      * or {@link #OVER_SCROLL_NEVER}.
   13654      *
   13655      * @return This view's over-scroll mode.
   13656      */
   13657     public int getOverScrollMode() {
   13658         return mOverScrollMode;
   13659     }
   13660 
   13661     /**
   13662      * Set the over-scroll mode for this view. Valid over-scroll modes are
   13663      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   13664      * (allow over-scrolling only if the view content is larger than the container),
   13665      * or {@link #OVER_SCROLL_NEVER}.
   13666      *
   13667      * Setting the over-scroll mode of a view will have an effect only if the
   13668      * view is capable of scrolling.
   13669      *
   13670      * @param overScrollMode The new over-scroll mode for this view.
   13671      */
   13672     public void setOverScrollMode(int overScrollMode) {
   13673         if (overScrollMode != OVER_SCROLL_ALWAYS &&
   13674                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
   13675                 overScrollMode != OVER_SCROLL_NEVER) {
   13676             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
   13677         }
   13678         mOverScrollMode = overScrollMode;
   13679     }
   13680 
   13681     /**
   13682      * Gets a scale factor that determines the distance the view should scroll
   13683      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
   13684      * @return The vertical scroll scale factor.
   13685      * @hide
   13686      */
   13687     protected float getVerticalScrollFactor() {
   13688         if (mVerticalScrollFactor == 0) {
   13689             TypedValue outValue = new TypedValue();
   13690             if (!mContext.getTheme().resolveAttribute(
   13691                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
   13692                 throw new IllegalStateException(
   13693                         "Expected theme to define listPreferredItemHeight.");
   13694             }
   13695             mVerticalScrollFactor = outValue.getDimension(
   13696                     mContext.getResources().getDisplayMetrics());
   13697         }
   13698         return mVerticalScrollFactor;
   13699     }
   13700 
   13701     /**
   13702      * Gets a scale factor that determines the distance the view should scroll
   13703      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
   13704      * @return The horizontal scroll scale factor.
   13705      * @hide
   13706      */
   13707     protected float getHorizontalScrollFactor() {
   13708         // TODO: Should use something else.
   13709         return getVerticalScrollFactor();
   13710     }
   13711 
   13712     /**
   13713      * Return the value specifying the text direction or policy that was set with
   13714      * {@link #setTextDirection(int)}.
   13715      *
   13716      * @return the defined text direction. It can be one of:
   13717      *
   13718      * {@link #TEXT_DIRECTION_INHERIT},
   13719      * {@link #TEXT_DIRECTION_FIRST_STRONG}
   13720      * {@link #TEXT_DIRECTION_ANY_RTL},
   13721      * {@link #TEXT_DIRECTION_LTR},
   13722      * {@link #TEXT_DIRECTION_RTL},
   13723      *
   13724      * @hide
   13725      */
   13726     public int getTextDirection() {
   13727         return mTextDirection;
   13728     }
   13729 
   13730     /**
   13731      * Set the text direction.
   13732      *
   13733      * @param textDirection the direction to set. Should be one of:
   13734      *
   13735      * {@link #TEXT_DIRECTION_INHERIT},
   13736      * {@link #TEXT_DIRECTION_FIRST_STRONG}
   13737      * {@link #TEXT_DIRECTION_ANY_RTL},
   13738      * {@link #TEXT_DIRECTION_LTR},
   13739      * {@link #TEXT_DIRECTION_RTL},
   13740      *
   13741      * @hide
   13742      */
   13743     public void setTextDirection(int textDirection) {
   13744         if (textDirection != mTextDirection) {
   13745             mTextDirection = textDirection;
   13746             resetResolvedTextDirection();
   13747             requestLayout();
   13748         }
   13749     }
   13750 
   13751     /**
   13752      * Return the resolved text direction.
   13753      *
   13754      * @return the resolved text direction. Return one of:
   13755      *
   13756      * {@link #TEXT_DIRECTION_FIRST_STRONG}
   13757      * {@link #TEXT_DIRECTION_ANY_RTL},
   13758      * {@link #TEXT_DIRECTION_LTR},
   13759      * {@link #TEXT_DIRECTION_RTL},
   13760      *
   13761      * @hide
   13762      */
   13763     public int getResolvedTextDirection() {
   13764         if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) {
   13765             resolveTextDirection();
   13766         }
   13767         return mResolvedTextDirection;
   13768     }
   13769 
   13770     /**
   13771      * Resolve the text direction.
   13772      *
   13773      * @hide
   13774      */
   13775     protected void resolveTextDirection() {
   13776         if (mTextDirection != TEXT_DIRECTION_INHERIT) {
   13777             mResolvedTextDirection = mTextDirection;
   13778             return;
   13779         }
   13780         if (mParent != null && mParent instanceof ViewGroup) {
   13781             mResolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
   13782             return;
   13783         }
   13784         mResolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG;
   13785     }
   13786 
   13787     /**
   13788      * Reset resolved text direction. Will be resolved during a call to getResolvedTextDirection().
   13789      *
   13790      * @hide
   13791      */
   13792     protected void resetResolvedTextDirection() {
   13793         mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
   13794     }
   13795 
   13796     //
   13797     // Properties
   13798     //
   13799     /**
   13800      * A Property wrapper around the <code>alpha</code> functionality handled by the
   13801      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
   13802      */
   13803     public static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
   13804         @Override
   13805         public void setValue(View object, float value) {
   13806             object.setAlpha(value);
   13807         }
   13808 
   13809         @Override
   13810         public Float get(View object) {
   13811             return object.getAlpha();
   13812         }
   13813     };
   13814 
   13815     /**
   13816      * A Property wrapper around the <code>translationX</code> functionality handled by the
   13817      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
   13818      */
   13819     public static Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
   13820         @Override
   13821         public void setValue(View object, float value) {
   13822             object.setTranslationX(value);
   13823         }
   13824 
   13825                 @Override
   13826         public Float get(View object) {
   13827             return object.getTranslationX();
   13828         }
   13829     };
   13830 
   13831     /**
   13832      * A Property wrapper around the <code>translationY</code> functionality handled by the
   13833      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
   13834      */
   13835     public static Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
   13836         @Override
   13837         public void setValue(View object, float value) {
   13838             object.setTranslationY(value);
   13839         }
   13840 
   13841         @Override
   13842         public Float get(View object) {
   13843             return object.getTranslationY();
   13844         }
   13845     };
   13846 
   13847     /**
   13848      * A Property wrapper around the <code>x</code> functionality handled by the
   13849      * {@link View#setX(float)} and {@link View#getX()} methods.
   13850      */
   13851     public static Property<View, Float> X = new FloatProperty<View>("x") {
   13852         @Override
   13853         public void setValue(View object, float value) {
   13854             object.setX(value);
   13855         }
   13856 
   13857         @Override
   13858         public Float get(View object) {
   13859             return object.getX();
   13860         }
   13861     };
   13862 
   13863     /**
   13864      * A Property wrapper around the <code>y</code> functionality handled by the
   13865      * {@link View#setY(float)} and {@link View#getY()} methods.
   13866      */
   13867     public static Property<View, Float> Y = new FloatProperty<View>("y") {
   13868         @Override
   13869         public void setValue(View object, float value) {
   13870             object.setY(value);
   13871         }
   13872 
   13873         @Override
   13874         public Float get(View object) {
   13875             return object.getY();
   13876         }
   13877     };
   13878 
   13879     /**
   13880      * A Property wrapper around the <code>rotation</code> functionality handled by the
   13881      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
   13882      */
   13883     public static Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
   13884         @Override
   13885         public void setValue(View object, float value) {
   13886             object.setRotation(value);
   13887         }
   13888 
   13889         @Override
   13890         public Float get(View object) {
   13891             return object.getRotation();
   13892         }
   13893     };
   13894 
   13895     /**
   13896      * A Property wrapper around the <code>rotationX</code> functionality handled by the
   13897      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
   13898      */
   13899     public static Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
   13900         @Override
   13901         public void setValue(View object, float value) {
   13902             object.setRotationX(value);
   13903         }
   13904 
   13905         @Override
   13906         public Float get(View object) {
   13907             return object.getRotationX();
   13908         }
   13909     };
   13910 
   13911     /**
   13912      * A Property wrapper around the <code>rotationY</code> functionality handled by the
   13913      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
   13914      */
   13915     public static Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
   13916         @Override
   13917         public void setValue(View object, float value) {
   13918             object.setRotationY(value);
   13919         }
   13920 
   13921         @Override
   13922         public Float get(View object) {
   13923             return object.getRotationY();
   13924         }
   13925     };
   13926 
   13927     /**
   13928      * A Property wrapper around the <code>scaleX</code> functionality handled by the
   13929      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
   13930      */
   13931     public static Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
   13932         @Override
   13933         public void setValue(View object, float value) {
   13934             object.setScaleX(value);
   13935         }
   13936 
   13937         @Override
   13938         public Float get(View object) {
   13939             return object.getScaleX();
   13940         }
   13941     };
   13942 
   13943     /**
   13944      * A Property wrapper around the <code>scaleY</code> functionality handled by the
   13945      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
   13946      */
   13947     public static Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
   13948         @Override
   13949         public void setValue(View object, float value) {
   13950             object.setScaleY(value);
   13951         }
   13952 
   13953         @Override
   13954         public Float get(View object) {
   13955             return object.getScaleY();
   13956         }
   13957     };
   13958 
   13959     /**
   13960      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
   13961      * Each MeasureSpec represents a requirement for either the width or the height.
   13962      * A MeasureSpec is comprised of a size and a mode. There are three possible
   13963      * modes:
   13964      * <dl>
   13965      * <dt>UNSPECIFIED</dt>
   13966      * <dd>
   13967      * The parent has not imposed any constraint on the child. It can be whatever size
   13968      * it wants.
   13969      * </dd>
   13970      *
   13971      * <dt>EXACTLY</dt>
   13972      * <dd>
   13973      * The parent has determined an exact size for the child. The child is going to be
   13974      * given those bounds regardless of how big it wants to be.
   13975      * </dd>
   13976      *
   13977      * <dt>AT_MOST</dt>
   13978      * <dd>
   13979      * The child can be as large as it wants up to the specified size.
   13980      * </dd>
   13981      * </dl>
   13982      *
   13983      * MeasureSpecs are implemented as ints to reduce object allocation. This class
   13984      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
   13985      */
   13986     public static class MeasureSpec {
   13987         private static final int MODE_SHIFT = 30;
   13988         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
   13989 
   13990         /**
   13991          * Measure specification mode: The parent has not imposed any constraint
   13992          * on the child. It can be whatever size it wants.
   13993          */
   13994         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
   13995 
   13996         /**
   13997          * Measure specification mode: The parent has determined an exact size
   13998          * for the child. The child is going to be given those bounds regardless
   13999          * of how big it wants to be.
   14000          */
   14001         public static final int EXACTLY     = 1 << MODE_SHIFT;
   14002 
   14003         /**
   14004          * Measure specification mode: The child can be as large as it wants up
   14005          * to the specified size.
   14006          */
   14007         public static final int AT_MOST     = 2 << MODE_SHIFT;
   14008 
   14009         /**
   14010          * Creates a measure specification based on the supplied size and mode.
   14011          *
   14012          * The mode must always be one of the following:
   14013          * <ul>
   14014          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
   14015          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
   14016          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
   14017          * </ul>
   14018          *
   14019          * @param size the size of the measure specification
   14020          * @param mode the mode of the measure specification
   14021          * @return the measure specification based on size and mode
   14022          */
   14023         public static int makeMeasureSpec(int size, int mode) {
   14024             return size + mode;
   14025         }
   14026 
   14027         /**
   14028          * Extracts the mode from the supplied measure specification.
   14029          *
   14030          * @param measureSpec the measure specification to extract the mode from
   14031          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
   14032          *         {@link android.view.View.MeasureSpec#AT_MOST} or
   14033          *         {@link android.view.View.MeasureSpec#EXACTLY}
   14034          */
   14035         public static int getMode(int measureSpec) {
   14036             return (measureSpec & MODE_MASK);
   14037         }
   14038 
   14039         /**
   14040          * Extracts the size from the supplied measure specification.
   14041          *
   14042          * @param measureSpec the measure specification to extract the size from
   14043          * @return the size in pixels defined in the supplied measure specification
   14044          */
   14045         public static int getSize(int measureSpec) {
   14046             return (measureSpec & ~MODE_MASK);
   14047         }
   14048 
   14049         /**
   14050          * Returns a String representation of the specified measure
   14051          * specification.
   14052          *
   14053          * @param measureSpec the measure specification to convert to a String
   14054          * @return a String with the following format: "MeasureSpec: MODE SIZE"
   14055          */
   14056         public static String toString(int measureSpec) {
   14057             int mode = getMode(measureSpec);
   14058             int size = getSize(measureSpec);
   14059 
   14060             StringBuilder sb = new StringBuilder("MeasureSpec: ");
   14061 
   14062             if (mode == UNSPECIFIED)
   14063                 sb.append("UNSPECIFIED ");
   14064             else if (mode == EXACTLY)
   14065                 sb.append("EXACTLY ");
   14066             else if (mode == AT_MOST)
   14067                 sb.append("AT_MOST ");
   14068             else
   14069                 sb.append(mode).append(" ");
   14070 
   14071             sb.append(size);
   14072             return sb.toString();
   14073         }
   14074     }
   14075 
   14076     class CheckForLongPress implements Runnable {
   14077 
   14078         private int mOriginalWindowAttachCount;
   14079 
   14080         public void run() {
   14081             if (isPressed() && (mParent != null)
   14082                     && mOriginalWindowAttachCount == mWindowAttachCount) {
   14083                 if (performLongClick()) {
   14084                     mHasPerformedLongPress = true;
   14085                 }
   14086             }
   14087         }
   14088 
   14089         public void rememberWindowAttachCount() {
   14090             mOriginalWindowAttachCount = mWindowAttachCount;
   14091         }
   14092     }
   14093 
   14094     private final class CheckForTap implements Runnable {
   14095         public void run() {
   14096             mPrivateFlags &= ~PREPRESSED;
   14097             mPrivateFlags |= PRESSED;
   14098             refreshDrawableState();
   14099             checkForLongClick(ViewConfiguration.getTapTimeout());
   14100         }
   14101     }
   14102 
   14103     private final class PerformClick implements Runnable {
   14104         public void run() {
   14105             performClick();
   14106         }
   14107     }
   14108 
   14109     /** @hide */
   14110     public void hackTurnOffWindowResizeAnim(boolean off) {
   14111         mAttachInfo.mTurnOffWindowResizeAnim = off;
   14112     }
   14113 
   14114     /**
   14115      * This method returns a ViewPropertyAnimator object, which can be used to animate
   14116      * specific properties on this View.
   14117      *
   14118      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
   14119      */
   14120     public ViewPropertyAnimator animate() {
   14121         if (mAnimator == null) {
   14122             mAnimator = new ViewPropertyAnimator(this);
   14123         }
   14124         return mAnimator;
   14125     }
   14126 
   14127     /**
   14128      * Interface definition for a callback to be invoked when a key event is
   14129      * dispatched to this view. The callback will be invoked before the key
   14130      * event is given to the view.
   14131      */
   14132     public interface OnKeyListener {
   14133         /**
   14134          * Called when a key is dispatched to a view. This allows listeners to
   14135          * get a chance to respond before the target view.
   14136          *
   14137          * @param v The view the key has been dispatched to.
   14138          * @param keyCode The code for the physical key that was pressed
   14139          * @param event The KeyEvent object containing full information about
   14140          *        the event.
   14141          * @return True if the listener has consumed the event, false otherwise.
   14142          */
   14143         boolean onKey(View v, int keyCode, KeyEvent event);
   14144     }
   14145 
   14146     /**
   14147      * Interface definition for a callback to be invoked when a touch event is
   14148      * dispatched to this view. The callback will be invoked before the touch
   14149      * event is given to the view.
   14150      */
   14151     public interface OnTouchListener {
   14152         /**
   14153          * Called when a touch event is dispatched to a view. This allows listeners to
   14154          * get a chance to respond before the target view.
   14155          *
   14156          * @param v The view the touch event has been dispatched to.
   14157          * @param event The MotionEvent object containing full information about
   14158          *        the event.
   14159          * @return True if the listener has consumed the event, false otherwise.
   14160          */
   14161         boolean onTouch(View v, MotionEvent event);
   14162     }
   14163 
   14164     /**
   14165      * Interface definition for a callback to be invoked when a hover event is
   14166      * dispatched to this view. The callback will be invoked before the hover
   14167      * event is given to the view.
   14168      */
   14169     public interface OnHoverListener {
   14170         /**
   14171          * Called when a hover event is dispatched to a view. This allows listeners to
   14172          * get a chance to respond before the target view.
   14173          *
   14174          * @param v The view the hover event has been dispatched to.
   14175          * @param event The MotionEvent object containing full information about
   14176          *        the event.
   14177          * @return True if the listener has consumed the event, false otherwise.
   14178          */
   14179         boolean onHover(View v, MotionEvent event);
   14180     }
   14181 
   14182     /**
   14183      * Interface definition for a callback to be invoked when a generic motion event is
   14184      * dispatched to this view. The callback will be invoked before the generic motion
   14185      * event is given to the view.
   14186      */
   14187     public interface OnGenericMotionListener {
   14188         /**
   14189          * Called when a generic motion event is dispatched to a view. This allows listeners to
   14190          * get a chance to respond before the target view.
   14191          *
   14192          * @param v The view the generic motion event has been dispatched to.
   14193          * @param event The MotionEvent object containing full information about
   14194          *        the event.
   14195          * @return True if the listener has consumed the event, false otherwise.
   14196          */
   14197         boolean onGenericMotion(View v, MotionEvent event);
   14198     }
   14199 
   14200     /**
   14201      * Interface definition for a callback to be invoked when a view has been clicked and held.
   14202      */
   14203     public interface OnLongClickListener {
   14204         /**
   14205          * Called when a view has been clicked and held.
   14206          *
   14207          * @param v The view that was clicked and held.
   14208          *
   14209          * @return true if the callback consumed the long click, false otherwise.
   14210          */
   14211         boolean onLongClick(View v);
   14212     }
   14213 
   14214     /**
   14215      * Interface definition for a callback to be invoked when a drag is being dispatched
   14216      * to this view.  The callback will be invoked before the hosting view's own
   14217      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
   14218      * onDrag(event) behavior, it should return 'false' from this callback.
   14219      *
   14220      * <div class="special reference">
   14221      * <h3>Developer Guides</h3>
   14222      * <p>For a guide to implementing drag and drop features, read the
   14223      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   14224      * </div>
   14225      */
   14226     public interface OnDragListener {
   14227         /**
   14228          * Called when a drag event is dispatched to a view. This allows listeners
   14229          * to get a chance to override base View behavior.
   14230          *
   14231          * @param v The View that received the drag event.
   14232          * @param event The {@link android.view.DragEvent} object for the drag event.
   14233          * @return {@code true} if the drag event was handled successfully, or {@code false}
   14234          * if the drag event was not handled. Note that {@code false} will trigger the View
   14235          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
   14236          */
   14237         boolean onDrag(View v, DragEvent event);
   14238     }
   14239 
   14240     /**
   14241      * Interface definition for a callback to be invoked when the focus state of
   14242      * a view changed.
   14243      */
   14244     public interface OnFocusChangeListener {
   14245         /**
   14246          * Called when the focus state of a view has changed.
   14247          *
   14248          * @param v The view whose state has changed.
   14249          * @param hasFocus The new focus state of v.
   14250          */
   14251         void onFocusChange(View v, boolean hasFocus);
   14252     }
   14253 
   14254     /**
   14255      * Interface definition for a callback to be invoked when a view is clicked.
   14256      */
   14257     public interface OnClickListener {
   14258         /**
   14259          * Called when a view has been clicked.
   14260          *
   14261          * @param v The view that was clicked.
   14262          */
   14263         void onClick(View v);
   14264     }
   14265 
   14266     /**
   14267      * Interface definition for a callback to be invoked when the context menu
   14268      * for this view is being built.
   14269      */
   14270     public interface OnCreateContextMenuListener {
   14271         /**
   14272          * Called when the context menu for this view is being built. It is not
   14273          * safe to hold onto the menu after this method returns.
   14274          *
   14275          * @param menu The context menu that is being built
   14276          * @param v The view for which the context menu is being built
   14277          * @param menuInfo Extra information about the item for which the
   14278          *            context menu should be shown. This information will vary
   14279          *            depending on the class of v.
   14280          */
   14281         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
   14282     }
   14283 
   14284     /**
   14285      * Interface definition for a callback to be invoked when the status bar changes
   14286      * visibility.  This reports <strong>global</strong> changes to the system UI
   14287      * state, not just what the application is requesting.
   14288      *
   14289      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
   14290      */
   14291     public interface OnSystemUiVisibilityChangeListener {
   14292         /**
   14293          * Called when the status bar changes visibility because of a call to
   14294          * {@link View#setSystemUiVisibility(int)}.
   14295          *
   14296          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
   14297          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  This tells you the
   14298          * <strong>global</strong> state of the UI visibility flags, not what your
   14299          * app is currently applying.
   14300          */
   14301         public void onSystemUiVisibilityChange(int visibility);
   14302     }
   14303 
   14304     /**
   14305      * Interface definition for a callback to be invoked when this view is attached
   14306      * or detached from its window.
   14307      */
   14308     public interface OnAttachStateChangeListener {
   14309         /**
   14310          * Called when the view is attached to a window.
   14311          * @param v The view that was attached
   14312          */
   14313         public void onViewAttachedToWindow(View v);
   14314         /**
   14315          * Called when the view is detached from a window.
   14316          * @param v The view that was detached
   14317          */
   14318         public void onViewDetachedFromWindow(View v);
   14319     }
   14320 
   14321     private final class UnsetPressedState implements Runnable {
   14322         public void run() {
   14323             setPressed(false);
   14324         }
   14325     }
   14326 
   14327     /**
   14328      * Base class for derived classes that want to save and restore their own
   14329      * state in {@link android.view.View#onSaveInstanceState()}.
   14330      */
   14331     public static class BaseSavedState extends AbsSavedState {
   14332         /**
   14333          * Constructor used when reading from a parcel. Reads the state of the superclass.
   14334          *
   14335          * @param source
   14336          */
   14337         public BaseSavedState(Parcel source) {
   14338             super(source);
   14339         }
   14340 
   14341         /**
   14342          * Constructor called by derived classes when creating their SavedState objects
   14343          *
   14344          * @param superState The state of the superclass of this view
   14345          */
   14346         public BaseSavedState(Parcelable superState) {
   14347             super(superState);
   14348         }
   14349 
   14350         public static final Parcelable.Creator<BaseSavedState> CREATOR =
   14351                 new Parcelable.Creator<BaseSavedState>() {
   14352             public BaseSavedState createFromParcel(Parcel in) {
   14353                 return new BaseSavedState(in);
   14354             }
   14355 
   14356             public BaseSavedState[] newArray(int size) {
   14357                 return new BaseSavedState[size];
   14358             }
   14359         };
   14360     }
   14361 
   14362     /**
   14363      * A set of information given to a view when it is attached to its parent
   14364      * window.
   14365      */
   14366     static class AttachInfo {
   14367         interface Callbacks {
   14368             void playSoundEffect(int effectId);
   14369             boolean performHapticFeedback(int effectId, boolean always);
   14370         }
   14371 
   14372         /**
   14373          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
   14374          * to a Handler. This class contains the target (View) to invalidate and
   14375          * the coordinates of the dirty rectangle.
   14376          *
   14377          * For performance purposes, this class also implements a pool of up to
   14378          * POOL_LIMIT objects that get reused. This reduces memory allocations
   14379          * whenever possible.
   14380          */
   14381         static class InvalidateInfo implements Poolable<InvalidateInfo> {
   14382             private static final int POOL_LIMIT = 10;
   14383             private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
   14384                     Pools.finitePool(new PoolableManager<InvalidateInfo>() {
   14385                         public InvalidateInfo newInstance() {
   14386                             return new InvalidateInfo();
   14387                         }
   14388 
   14389                         public void onAcquired(InvalidateInfo element) {
   14390                         }
   14391 
   14392                         public void onReleased(InvalidateInfo element) {
   14393                             element.target = null;
   14394                         }
   14395                     }, POOL_LIMIT)
   14396             );
   14397 
   14398             private InvalidateInfo mNext;
   14399             private boolean mIsPooled;
   14400 
   14401             View target;
   14402 
   14403             int left;
   14404             int top;
   14405             int right;
   14406             int bottom;
   14407 
   14408             public void setNextPoolable(InvalidateInfo element) {
   14409                 mNext = element;
   14410             }
   14411 
   14412             public InvalidateInfo getNextPoolable() {
   14413                 return mNext;
   14414             }
   14415 
   14416             static InvalidateInfo acquire() {
   14417                 return sPool.acquire();
   14418             }
   14419 
   14420             void release() {
   14421                 sPool.release(this);
   14422             }
   14423 
   14424             public boolean isPooled() {
   14425                 return mIsPooled;
   14426             }
   14427 
   14428             public void setPooled(boolean isPooled) {
   14429                 mIsPooled = isPooled;
   14430             }
   14431         }
   14432 
   14433         final IWindowSession mSession;
   14434 
   14435         final IWindow mWindow;
   14436 
   14437         final IBinder mWindowToken;
   14438 
   14439         final Callbacks mRootCallbacks;
   14440 
   14441         HardwareCanvas mHardwareCanvas;
   14442 
   14443         /**
   14444          * The top view of the hierarchy.
   14445          */
   14446         View mRootView;
   14447 
   14448         IBinder mPanelParentWindowToken;
   14449         Surface mSurface;
   14450 
   14451         boolean mHardwareAccelerated;
   14452         boolean mHardwareAccelerationRequested;
   14453         HardwareRenderer mHardwareRenderer;
   14454 
   14455         /**
   14456          * Scale factor used by the compatibility mode
   14457          */
   14458         float mApplicationScale;
   14459 
   14460         /**
   14461          * Indicates whether the application is in compatibility mode
   14462          */
   14463         boolean mScalingRequired;
   14464 
   14465         /**
   14466          * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
   14467          */
   14468         boolean mTurnOffWindowResizeAnim;
   14469 
   14470         /**
   14471          * Left position of this view's window
   14472          */
   14473         int mWindowLeft;
   14474 
   14475         /**
   14476          * Top position of this view's window
   14477          */
   14478         int mWindowTop;
   14479 
   14480         /**
   14481          * Indicates whether views need to use 32-bit drawing caches
   14482          */
   14483         boolean mUse32BitDrawingCache;
   14484 
   14485         /**
   14486          * For windows that are full-screen but using insets to layout inside
   14487          * of the screen decorations, these are the current insets for the
   14488          * content of the window.
   14489          */
   14490         final Rect mContentInsets = new Rect();
   14491 
   14492         /**
   14493          * For windows that are full-screen but using insets to layout inside
   14494          * of the screen decorations, these are the current insets for the
   14495          * actual visible parts of the window.
   14496          */
   14497         final Rect mVisibleInsets = new Rect();
   14498 
   14499         /**
   14500          * The internal insets given by this window.  This value is
   14501          * supplied by the client (through
   14502          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
   14503          * be given to the window manager when changed to be used in laying
   14504          * out windows behind it.
   14505          */
   14506         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
   14507                 = new ViewTreeObserver.InternalInsetsInfo();
   14508 
   14509         /**
   14510          * All views in the window's hierarchy that serve as scroll containers,
   14511          * used to determine if the window can be resized or must be panned
   14512          * to adjust for a soft input area.
   14513          */
   14514         final ArrayList<View> mScrollContainers = new ArrayList<View>();
   14515 
   14516         final KeyEvent.DispatcherState mKeyDispatchState
   14517                 = new KeyEvent.DispatcherState();
   14518 
   14519         /**
   14520          * Indicates whether the view's window currently has the focus.
   14521          */
   14522         boolean mHasWindowFocus;
   14523 
   14524         /**
   14525          * The current visibility of the window.
   14526          */
   14527         int mWindowVisibility;
   14528 
   14529         /**
   14530          * Indicates the time at which drawing started to occur.
   14531          */
   14532         long mDrawingTime;
   14533 
   14534         /**
   14535          * Indicates whether or not ignoring the DIRTY_MASK flags.
   14536          */
   14537         boolean mIgnoreDirtyState;
   14538 
   14539         /**
   14540          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
   14541          * to avoid clearing that flag prematurely.
   14542          */
   14543         boolean mSetIgnoreDirtyState = false;
   14544 
   14545         /**
   14546          * Indicates whether the view's window is currently in touch mode.
   14547          */
   14548         boolean mInTouchMode;
   14549 
   14550         /**
   14551          * Indicates that ViewAncestor should trigger a global layout change
   14552          * the next time it performs a traversal
   14553          */
   14554         boolean mRecomputeGlobalAttributes;
   14555 
   14556         /**
   14557          * Always report new attributes at next traversal.
   14558          */
   14559         boolean mForceReportNewAttributes;
   14560 
   14561         /**
   14562          * Set during a traveral if any views want to keep the screen on.
   14563          */
   14564         boolean mKeepScreenOn;
   14565 
   14566         /**
   14567          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
   14568          */
   14569         int mSystemUiVisibility;
   14570 
   14571         /**
   14572          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
   14573          * attached.
   14574          */
   14575         boolean mHasSystemUiListeners;
   14576 
   14577         /**
   14578          * Set if the visibility of any views has changed.
   14579          */
   14580         boolean mViewVisibilityChanged;
   14581 
   14582         /**
   14583          * Set to true if a view has been scrolled.
   14584          */
   14585         boolean mViewScrollChanged;
   14586 
   14587         /**
   14588          * Global to the view hierarchy used as a temporary for dealing with
   14589          * x/y points in the transparent region computations.
   14590          */
   14591         final int[] mTransparentLocation = new int[2];
   14592 
   14593         /**
   14594          * Global to the view hierarchy used as a temporary for dealing with
   14595          * x/y points in the ViewGroup.invalidateChild implementation.
   14596          */
   14597         final int[] mInvalidateChildLocation = new int[2];
   14598 
   14599 
   14600         /**
   14601          * Global to the view hierarchy used as a temporary for dealing with
   14602          * x/y location when view is transformed.
   14603          */
   14604         final float[] mTmpTransformLocation = new float[2];
   14605 
   14606         /**
   14607          * The view tree observer used to dispatch global events like
   14608          * layout, pre-draw, touch mode change, etc.
   14609          */
   14610         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
   14611 
   14612         /**
   14613          * A Canvas used by the view hierarchy to perform bitmap caching.
   14614          */
   14615         Canvas mCanvas;
   14616 
   14617         /**
   14618          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
   14619          * handler can be used to pump events in the UI events queue.
   14620          */
   14621         final Handler mHandler;
   14622 
   14623         /**
   14624          * Identifier for messages requesting the view to be invalidated.
   14625          * Such messages should be sent to {@link #mHandler}.
   14626          */
   14627         static final int INVALIDATE_MSG = 0x1;
   14628 
   14629         /**
   14630          * Identifier for messages requesting the view to invalidate a region.
   14631          * Such messages should be sent to {@link #mHandler}.
   14632          */
   14633         static final int INVALIDATE_RECT_MSG = 0x2;
   14634 
   14635         /**
   14636          * Temporary for use in computing invalidate rectangles while
   14637          * calling up the hierarchy.
   14638          */
   14639         final Rect mTmpInvalRect = new Rect();
   14640 
   14641         /**
   14642          * Temporary for use in computing hit areas with transformed views
   14643          */
   14644         final RectF mTmpTransformRect = new RectF();
   14645 
   14646         /**
   14647          * Temporary list for use in collecting focusable descendents of a view.
   14648          */
   14649         final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
   14650 
   14651         /**
   14652          * The id of the window for accessibility purposes.
   14653          */
   14654         int mAccessibilityWindowId = View.NO_ID;
   14655 
   14656         /**
   14657          * Creates a new set of attachment information with the specified
   14658          * events handler and thread.
   14659          *
   14660          * @param handler the events handler the view must use
   14661          */
   14662         AttachInfo(IWindowSession session, IWindow window,
   14663                 Handler handler, Callbacks effectPlayer) {
   14664             mSession = session;
   14665             mWindow = window;
   14666             mWindowToken = window.asBinder();
   14667             mHandler = handler;
   14668             mRootCallbacks = effectPlayer;
   14669         }
   14670     }
   14671 
   14672     /**
   14673      * <p>ScrollabilityCache holds various fields used by a View when scrolling
   14674      * is supported. This avoids keeping too many unused fields in most
   14675      * instances of View.</p>
   14676      */
   14677     private static class ScrollabilityCache implements Runnable {
   14678 
   14679         /**
   14680          * Scrollbars are not visible
   14681          */
   14682         public static final int OFF = 0;
   14683 
   14684         /**
   14685          * Scrollbars are visible
   14686          */
   14687         public static final int ON = 1;
   14688 
   14689         /**
   14690          * Scrollbars are fading away
   14691          */
   14692         public static final int FADING = 2;
   14693 
   14694         public boolean fadeScrollBars;
   14695 
   14696         public int fadingEdgeLength;
   14697         public int scrollBarDefaultDelayBeforeFade;
   14698         public int scrollBarFadeDuration;
   14699 
   14700         public int scrollBarSize;
   14701         public ScrollBarDrawable scrollBar;
   14702         public float[] interpolatorValues;
   14703         public View host;
   14704 
   14705         public final Paint paint;
   14706         public final Matrix matrix;
   14707         public Shader shader;
   14708 
   14709         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
   14710 
   14711         private static final float[] OPAQUE = { 255 };
   14712         private static final float[] TRANSPARENT = { 0.0f };
   14713 
   14714         /**
   14715          * When fading should start. This time moves into the future every time
   14716          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
   14717          */
   14718         public long fadeStartTime;
   14719 
   14720 
   14721         /**
   14722          * The current state of the scrollbars: ON, OFF, or FADING
   14723          */
   14724         public int state = OFF;
   14725 
   14726         private int mLastColor;
   14727 
   14728         public ScrollabilityCache(ViewConfiguration configuration, View host) {
   14729             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
   14730             scrollBarSize = configuration.getScaledScrollBarSize();
   14731             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
   14732             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
   14733 
   14734             paint = new Paint();
   14735             matrix = new Matrix();
   14736             // use use a height of 1, and then wack the matrix each time we
   14737             // actually use it.
   14738             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   14739 
   14740             paint.setShader(shader);
   14741             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   14742             this.host = host;
   14743         }
   14744 
   14745         public void setFadeColor(int color) {
   14746             if (color != 0 && color != mLastColor) {
   14747                 mLastColor = color;
   14748                 color |= 0xFF000000;
   14749 
   14750                 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
   14751                         color & 0x00FFFFFF, Shader.TileMode.CLAMP);
   14752 
   14753                 paint.setShader(shader);
   14754                 // Restore the default transfer mode (src_over)
   14755                 paint.setXfermode(null);
   14756             }
   14757         }
   14758 
   14759         public void run() {
   14760             long now = AnimationUtils.currentAnimationTimeMillis();
   14761             if (now >= fadeStartTime) {
   14762 
   14763                 // the animation fades the scrollbars out by changing
   14764                 // the opacity (alpha) from fully opaque to fully
   14765                 // transparent
   14766                 int nextFrame = (int) now;
   14767                 int framesCount = 0;
   14768 
   14769                 Interpolator interpolator = scrollBarInterpolator;
   14770 
   14771                 // Start opaque
   14772                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
   14773 
   14774                 // End transparent
   14775                 nextFrame += scrollBarFadeDuration;
   14776                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
   14777 
   14778                 state = FADING;
   14779 
   14780                 // Kick off the fade animation
   14781                 host.invalidate(true);
   14782             }
   14783         }
   14784     }
   14785 
   14786     /**
   14787      * Resuable callback for sending
   14788      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   14789      */
   14790     private class SendViewScrolledAccessibilityEvent implements Runnable {
   14791         public volatile boolean mIsPending;
   14792 
   14793         public void run() {
   14794             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
   14795             mIsPending = false;
   14796         }
   14797     }
   14798 
   14799     /**
   14800      * <p>
   14801      * This class represents a delegate that can be registered in a {@link View}
   14802      * to enhance accessibility support via composition rather via inheritance.
   14803      * It is specifically targeted to widget developers that extend basic View
   14804      * classes i.e. classes in package android.view, that would like their
   14805      * applications to be backwards compatible.
   14806      * </p>
   14807      * <p>
   14808      * A scenario in which a developer would like to use an accessibility delegate
   14809      * is overriding a method introduced in a later API version then the minimal API
   14810      * version supported by the application. For example, the method
   14811      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
   14812      * in API version 4 when the accessibility APIs were first introduced. If a
   14813      * developer would like his application to run on API version 4 devices (assuming
   14814      * all other APIs used by the application are version 4 or lower) and take advantage
   14815      * of this method, instead of overriding the method which would break the application's
   14816      * backwards compatibility, he can override the corresponding method in this
   14817      * delegate and register the delegate in the target View if the API version of
   14818      * the system is high enough i.e. the API version is same or higher to the API
   14819      * version that introduced
   14820      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
   14821      * </p>
   14822      * <p>
   14823      * Here is an example implementation:
   14824      * </p>
   14825      * <code><pre><p>
   14826      * if (Build.VERSION.SDK_INT >= 14) {
   14827      *     // If the API version is equal of higher than the version in
   14828      *     // which onInitializeAccessibilityNodeInfo was introduced we
   14829      *     // register a delegate with a customized implementation.
   14830      *     View view = findViewById(R.id.view_id);
   14831      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
   14832      *         public void onInitializeAccessibilityNodeInfo(View host,
   14833      *                 AccessibilityNodeInfo info) {
   14834      *             // Let the default implementation populate the info.
   14835      *             super.onInitializeAccessibilityNodeInfo(host, info);
   14836      *             // Set some other information.
   14837      *             info.setEnabled(host.isEnabled());
   14838      *         }
   14839      *     });
   14840      * }
   14841      * </code></pre></p>
   14842      * <p>
   14843      * This delegate contains methods that correspond to the accessibility methods
   14844      * in View. If a delegate has been specified the implementation in View hands
   14845      * off handling to the corresponding method in this delegate. The default
   14846      * implementation the delegate methods behaves exactly as the corresponding
   14847      * method in View for the case of no accessibility delegate been set. Hence,
   14848      * to customize the behavior of a View method, clients can override only the
   14849      * corresponding delegate method without altering the behavior of the rest
   14850      * accessibility related methods of the host view.
   14851      * </p>
   14852      */
   14853     public static class AccessibilityDelegate {
   14854 
   14855         /**
   14856          * Sends an accessibility event of the given type. If accessibility is not
   14857          * enabled this method has no effect.
   14858          * <p>
   14859          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
   14860          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
   14861          * been set.
   14862          * </p>
   14863          *
   14864          * @param host The View hosting the delegate.
   14865          * @param eventType The type of the event to send.
   14866          *
   14867          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
   14868          */
   14869         public void sendAccessibilityEvent(View host, int eventType) {
   14870             host.sendAccessibilityEventInternal(eventType);
   14871         }
   14872 
   14873         /**
   14874          * Sends an accessibility event. This method behaves exactly as
   14875          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
   14876          * empty {@link AccessibilityEvent} and does not perform a check whether
   14877          * accessibility is enabled.
   14878          * <p>
   14879          * The default implementation behaves as
   14880          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   14881          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
   14882          * the case of no accessibility delegate been set.
   14883          * </p>
   14884          *
   14885          * @param host The View hosting the delegate.
   14886          * @param event The event to send.
   14887          *
   14888          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   14889          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   14890          */
   14891         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
   14892             host.sendAccessibilityEventUncheckedInternal(event);
   14893         }
   14894 
   14895         /**
   14896          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
   14897          * to its children for adding their text content to the event.
   14898          * <p>
   14899          * The default implementation behaves as
   14900          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   14901          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
   14902          * the case of no accessibility delegate been set.
   14903          * </p>
   14904          *
   14905          * @param host The View hosting the delegate.
   14906          * @param event The event.
   14907          * @return True if the event population was completed.
   14908          *
   14909          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   14910          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   14911          */
   14912         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   14913             return host.dispatchPopulateAccessibilityEventInternal(event);
   14914         }
   14915 
   14916         /**
   14917          * Gives a chance to the host View to populate the accessibility event with its
   14918          * text content.
   14919          * <p>
   14920          * The default implementation behaves as
   14921          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
   14922          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
   14923          * the case of no accessibility delegate been set.
   14924          * </p>
   14925          *
   14926          * @param host The View hosting the delegate.
   14927          * @param event The accessibility event which to populate.
   14928          *
   14929          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
   14930          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
   14931          */
   14932         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   14933             host.onPopulateAccessibilityEventInternal(event);
   14934         }
   14935 
   14936         /**
   14937          * Initializes an {@link AccessibilityEvent} with information about the
   14938          * the host View which is the event source.
   14939          * <p>
   14940          * The default implementation behaves as
   14941          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
   14942          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
   14943          * the case of no accessibility delegate been set.
   14944          * </p>
   14945          *
   14946          * @param host The View hosting the delegate.
   14947          * @param event The event to initialize.
   14948          *
   14949          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
   14950          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
   14951          */
   14952         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
   14953             host.onInitializeAccessibilityEventInternal(event);
   14954         }
   14955 
   14956         /**
   14957          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
   14958          * <p>
   14959          * The default implementation behaves as
   14960          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   14961          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
   14962          * the case of no accessibility delegate been set.
   14963          * </p>
   14964          *
   14965          * @param host The View hosting the delegate.
   14966          * @param info The instance to initialize.
   14967          *
   14968          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   14969          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   14970          */
   14971         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
   14972             host.onInitializeAccessibilityNodeInfoInternal(info);
   14973         }
   14974 
   14975         /**
   14976          * Called when a child of the host View has requested sending an
   14977          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
   14978          * to augment the event.
   14979          * <p>
   14980          * The default implementation behaves as
   14981          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   14982          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
   14983          * the case of no accessibility delegate been set.
   14984          * </p>
   14985          *
   14986          * @param host The View hosting the delegate.
   14987          * @param child The child which requests sending the event.
   14988          * @param event The event to be sent.
   14989          * @return True if the event should be sent
   14990          *
   14991          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   14992          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   14993          */
   14994         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
   14995                 AccessibilityEvent event) {
   14996             return host.onRequestSendAccessibilityEventInternal(child, event);
   14997         }
   14998     }
   14999 }
   15000