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.animation.AnimatorInflater;
     20 import android.animation.StateListAnimator;
     21 import android.annotation.CallSuper;
     22 import android.annotation.ColorInt;
     23 import android.annotation.DrawableRes;
     24 import android.annotation.FloatRange;
     25 import android.annotation.IdRes;
     26 import android.annotation.IntDef;
     27 import android.annotation.IntRange;
     28 import android.annotation.LayoutRes;
     29 import android.annotation.NonNull;
     30 import android.annotation.Nullable;
     31 import android.annotation.Size;
     32 import android.annotation.UiThread;
     33 import android.content.ClipData;
     34 import android.content.Context;
     35 import android.content.ContextWrapper;
     36 import android.content.Intent;
     37 import android.content.res.ColorStateList;
     38 import android.content.res.Configuration;
     39 import android.content.res.Resources;
     40 import android.content.res.TypedArray;
     41 import android.graphics.Bitmap;
     42 import android.graphics.Canvas;
     43 import android.graphics.Insets;
     44 import android.graphics.Interpolator;
     45 import android.graphics.LinearGradient;
     46 import android.graphics.Matrix;
     47 import android.graphics.Outline;
     48 import android.graphics.Paint;
     49 import android.graphics.PixelFormat;
     50 import android.graphics.Point;
     51 import android.graphics.PorterDuff;
     52 import android.graphics.PorterDuffXfermode;
     53 import android.graphics.Rect;
     54 import android.graphics.RectF;
     55 import android.graphics.Region;
     56 import android.graphics.Shader;
     57 import android.graphics.drawable.ColorDrawable;
     58 import android.graphics.drawable.Drawable;
     59 import android.hardware.display.DisplayManagerGlobal;
     60 import android.os.Build.VERSION_CODES;
     61 import android.os.Bundle;
     62 import android.os.Handler;
     63 import android.os.IBinder;
     64 import android.os.Parcel;
     65 import android.os.Parcelable;
     66 import android.os.RemoteException;
     67 import android.os.SystemClock;
     68 import android.os.SystemProperties;
     69 import android.os.Trace;
     70 import android.text.TextUtils;
     71 import android.util.AttributeSet;
     72 import android.util.FloatProperty;
     73 import android.util.LayoutDirection;
     74 import android.util.Log;
     75 import android.util.LongSparseLongArray;
     76 import android.util.Pools.SynchronizedPool;
     77 import android.util.Property;
     78 import android.util.SparseArray;
     79 import android.util.StateSet;
     80 import android.util.SuperNotCalledException;
     81 import android.util.TypedValue;
     82 import android.view.ContextMenu.ContextMenuInfo;
     83 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
     84 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
     85 import android.view.AccessibilityIterators.TextSegmentIterator;
     86 import android.view.AccessibilityIterators.WordTextSegmentIterator;
     87 import android.view.accessibility.AccessibilityEvent;
     88 import android.view.accessibility.AccessibilityEventSource;
     89 import android.view.accessibility.AccessibilityManager;
     90 import android.view.accessibility.AccessibilityNodeInfo;
     91 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
     92 import android.view.accessibility.AccessibilityNodeProvider;
     93 import android.view.animation.Animation;
     94 import android.view.animation.AnimationUtils;
     95 import android.view.animation.Transformation;
     96 import android.view.inputmethod.EditorInfo;
     97 import android.view.inputmethod.InputConnection;
     98 import android.view.inputmethod.InputMethodManager;
     99 import android.widget.Checkable;
    100 import android.widget.FrameLayout;
    101 import android.widget.ScrollBarDrawable;
    102 import static android.os.Build.VERSION_CODES.*;
    103 import static java.lang.Math.max;
    104 
    105 import com.android.internal.R;
    106 import com.android.internal.util.Predicate;
    107 import com.android.internal.view.menu.MenuBuilder;
    108 import com.android.internal.widget.ScrollBarUtils;
    109 import com.google.android.collect.Lists;
    110 import com.google.android.collect.Maps;
    111 
    112 import java.lang.NullPointerException;
    113 import java.lang.annotation.Retention;
    114 import java.lang.annotation.RetentionPolicy;
    115 import java.lang.ref.WeakReference;
    116 import java.lang.reflect.Field;
    117 import java.lang.reflect.InvocationTargetException;
    118 import java.lang.reflect.Method;
    119 import java.lang.reflect.Modifier;
    120 import java.util.ArrayList;
    121 import java.util.Arrays;
    122 import java.util.Collections;
    123 import java.util.HashMap;
    124 import java.util.List;
    125 import java.util.Locale;
    126 import java.util.Map;
    127 import java.util.concurrent.CopyOnWriteArrayList;
    128 import java.util.concurrent.atomic.AtomicInteger;
    129 
    130 /**
    131  * <p>
    132  * This class represents the basic building block for user interface components. A View
    133  * occupies a rectangular area on the screen and is responsible for drawing and
    134  * event handling. View is the base class for <em>widgets</em>, which are
    135  * used to create interactive UI components (buttons, text fields, etc.). The
    136  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
    137  * are invisible containers that hold other Views (or other ViewGroups) and define
    138  * their layout properties.
    139  * </p>
    140  *
    141  * <div class="special reference">
    142  * <h3>Developer Guides</h3>
    143  * <p>For information about using this class to develop your application's user interface,
    144  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
    145  * </div>
    146  *
    147  * <a name="Using"></a>
    148  * <h3>Using Views</h3>
    149  * <p>
    150  * All of the views in a window are arranged in a single tree. You can add views
    151  * either from code or by specifying a tree of views in one or more XML layout
    152  * files. There are many specialized subclasses of views that act as controls or
    153  * are capable of displaying text, images, or other content.
    154  * </p>
    155  * <p>
    156  * Once you have created a tree of views, there are typically a few types of
    157  * common operations you may wish to perform:
    158  * <ul>
    159  * <li><strong>Set properties:</strong> for example setting the text of a
    160  * {@link android.widget.TextView}. The available properties and the methods
    161  * that set them will vary among the different subclasses of views. Note that
    162  * properties that are known at build time can be set in the XML layout
    163  * files.</li>
    164  * <li><strong>Set focus:</strong> The framework will handle moving focus in
    165  * response to user input. To force focus to a specific view, call
    166  * {@link #requestFocus}.</li>
    167  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
    168  * that will be notified when something interesting happens to the view. For
    169  * example, all views will let you set a listener to be notified when the view
    170  * gains or loses focus. You can register such a listener using
    171  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
    172  * Other view subclasses offer more specialized listeners. For example, a Button
    173  * exposes a listener to notify clients when the button is clicked.</li>
    174  * <li><strong>Set visibility:</strong> You can hide or show views using
    175  * {@link #setVisibility(int)}.</li>
    176  * </ul>
    177  * </p>
    178  * <p><em>
    179  * Note: The Android framework is responsible for measuring, laying out and
    180  * drawing views. You should not call methods that perform these actions on
    181  * views yourself unless you are actually implementing a
    182  * {@link android.view.ViewGroup}.
    183  * </em></p>
    184  *
    185  * <a name="Lifecycle"></a>
    186  * <h3>Implementing a Custom View</h3>
    187  *
    188  * <p>
    189  * To implement a custom view, you will usually begin by providing overrides for
    190  * some of the standard methods that the framework calls on all views. You do
    191  * not need to override all of these methods. In fact, you can start by just
    192  * overriding {@link #onDraw(android.graphics.Canvas)}.
    193  * <table border="2" width="85%" align="center" cellpadding="5">
    194  *     <thead>
    195  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
    196  *     </thead>
    197  *
    198  *     <tbody>
    199  *     <tr>
    200  *         <td rowspan="2">Creation</td>
    201  *         <td>Constructors</td>
    202  *         <td>There is a form of the constructor that are called when the view
    203  *         is created from code and a form that is called when the view is
    204  *         inflated from a layout file. The second form should parse and apply
    205  *         any attributes defined in the layout file.
    206  *         </td>
    207  *     </tr>
    208  *     <tr>
    209  *         <td><code>{@link #onFinishInflate()}</code></td>
    210  *         <td>Called after a view and all of its children has been inflated
    211  *         from XML.</td>
    212  *     </tr>
    213  *
    214  *     <tr>
    215  *         <td rowspan="3">Layout</td>
    216  *         <td><code>{@link #onMeasure(int, int)}</code></td>
    217  *         <td>Called to determine the size requirements for this view and all
    218  *         of its children.
    219  *         </td>
    220  *     </tr>
    221  *     <tr>
    222  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
    223  *         <td>Called when this view should assign a size and position to all
    224  *         of its children.
    225  *         </td>
    226  *     </tr>
    227  *     <tr>
    228  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
    229  *         <td>Called when the size of this view has changed.
    230  *         </td>
    231  *     </tr>
    232  *
    233  *     <tr>
    234  *         <td>Drawing</td>
    235  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
    236  *         <td>Called when the view should render its content.
    237  *         </td>
    238  *     </tr>
    239  *
    240  *     <tr>
    241  *         <td rowspan="4">Event processing</td>
    242  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
    243  *         <td>Called when a new hardware key event occurs.
    244  *         </td>
    245  *     </tr>
    246  *     <tr>
    247  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
    248  *         <td>Called when a hardware key up event occurs.
    249  *         </td>
    250  *     </tr>
    251  *     <tr>
    252  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
    253  *         <td>Called when a trackball motion event occurs.
    254  *         </td>
    255  *     </tr>
    256  *     <tr>
    257  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
    258  *         <td>Called when a touch screen motion event occurs.
    259  *         </td>
    260  *     </tr>
    261  *
    262  *     <tr>
    263  *         <td rowspan="2">Focus</td>
    264  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
    265  *         <td>Called when the view gains or loses focus.
    266  *         </td>
    267  *     </tr>
    268  *
    269  *     <tr>
    270  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
    271  *         <td>Called when the window containing the view gains or loses focus.
    272  *         </td>
    273  *     </tr>
    274  *
    275  *     <tr>
    276  *         <td rowspan="3">Attaching</td>
    277  *         <td><code>{@link #onAttachedToWindow()}</code></td>
    278  *         <td>Called when the view is attached to a window.
    279  *         </td>
    280  *     </tr>
    281  *
    282  *     <tr>
    283  *         <td><code>{@link #onDetachedFromWindow}</code></td>
    284  *         <td>Called when the view is detached from its window.
    285  *         </td>
    286  *     </tr>
    287  *
    288  *     <tr>
    289  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
    290  *         <td>Called when the visibility of the window containing the view
    291  *         has changed.
    292  *         </td>
    293  *     </tr>
    294  *     </tbody>
    295  *
    296  * </table>
    297  * </p>
    298  *
    299  * <a name="IDs"></a>
    300  * <h3>IDs</h3>
    301  * Views may have an integer id associated with them. These ids are typically
    302  * assigned in the layout XML files, and are used to find specific views within
    303  * the view tree. A common pattern is to:
    304  * <ul>
    305  * <li>Define a Button in the layout file and assign it a unique ID.
    306  * <pre>
    307  * &lt;Button
    308  *     android:id="@+id/my_button"
    309  *     android:layout_width="wrap_content"
    310  *     android:layout_height="wrap_content"
    311  *     android:text="@string/my_button_text"/&gt;
    312  * </pre></li>
    313  * <li>From the onCreate method of an Activity, find the Button
    314  * <pre class="prettyprint">
    315  *      Button myButton = (Button) findViewById(R.id.my_button);
    316  * </pre></li>
    317  * </ul>
    318  * <p>
    319  * View IDs need not be unique throughout the tree, but it is good practice to
    320  * ensure that they are at least unique within the part of the tree you are
    321  * searching.
    322  * </p>
    323  *
    324  * <a name="Position"></a>
    325  * <h3>Position</h3>
    326  * <p>
    327  * The geometry of a view is that of a rectangle. A view has a location,
    328  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
    329  * two dimensions, expressed as a width and a height. The unit for location
    330  * and dimensions is the pixel.
    331  * </p>
    332  *
    333  * <p>
    334  * It is possible to retrieve the location of a view by invoking the methods
    335  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
    336  * coordinate of the rectangle representing the view. The latter returns the
    337  * top, or Y, coordinate of the rectangle representing the view. These methods
    338  * both return the location of the view relative to its parent. For instance,
    339  * when getLeft() returns 20, that means the view is located 20 pixels to the
    340  * right of the left edge of its direct parent.
    341  * </p>
    342  *
    343  * <p>
    344  * In addition, several convenience methods are offered to avoid unnecessary
    345  * computations, namely {@link #getRight()} and {@link #getBottom()}.
    346  * These methods return the coordinates of the right and bottom edges of the
    347  * rectangle representing the view. For instance, calling {@link #getRight()}
    348  * is similar to the following computation: <code>getLeft() + getWidth()</code>
    349  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
    350  * </p>
    351  *
    352  * <a name="SizePaddingMargins"></a>
    353  * <h3>Size, padding and margins</h3>
    354  * <p>
    355  * The size of a view is expressed with a width and a height. A view actually
    356  * possess two pairs of width and height values.
    357  * </p>
    358  *
    359  * <p>
    360  * The first pair is known as <em>measured width</em> and
    361  * <em>measured height</em>. These dimensions define how big a view wants to be
    362  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
    363  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
    364  * and {@link #getMeasuredHeight()}.
    365  * </p>
    366  *
    367  * <p>
    368  * The second pair is simply known as <em>width</em> and <em>height</em>, or
    369  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
    370  * dimensions define the actual size of the view on screen, at drawing time and
    371  * after layout. These values may, but do not have to, be different from the
    372  * measured width and height. The width and height can be obtained by calling
    373  * {@link #getWidth()} and {@link #getHeight()}.
    374  * </p>
    375  *
    376  * <p>
    377  * To measure its dimensions, a view takes into account its padding. The padding
    378  * is expressed in pixels for the left, top, right and bottom parts of the view.
    379  * Padding can be used to offset the content of the view by a specific amount of
    380  * pixels. For instance, a left padding of 2 will push the view's content by
    381  * 2 pixels to the right of the left edge. Padding can be set using the
    382  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
    383  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
    384  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
    385  * {@link #getPaddingEnd()}.
    386  * </p>
    387  *
    388  * <p>
    389  * Even though a view can define a padding, it does not provide any support for
    390  * margins. However, view groups provide such a support. Refer to
    391  * {@link android.view.ViewGroup} and
    392  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
    393  * </p>
    394  *
    395  * <a name="Layout"></a>
    396  * <h3>Layout</h3>
    397  * <p>
    398  * Layout is a two pass process: a measure pass and a layout pass. The measuring
    399  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
    400  * of the view tree. Each view pushes dimension specifications down the tree
    401  * during the recursion. At the end of the measure pass, every view has stored
    402  * its measurements. The second pass happens in
    403  * {@link #layout(int,int,int,int)} and is also top-down. During
    404  * this pass each parent is responsible for positioning all of its children
    405  * using the sizes computed in the measure pass.
    406  * </p>
    407  *
    408  * <p>
    409  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
    410  * {@link #getMeasuredHeight()} values must be set, along with those for all of
    411  * that view's descendants. A view's measured width and measured height values
    412  * must respect the constraints imposed by the view's parents. This guarantees
    413  * that at the end of the measure pass, all parents accept all of their
    414  * children's measurements. A parent view may call measure() more than once on
    415  * its children. For example, the parent may measure each child once with
    416  * unspecified dimensions to find out how big they want to be, then call
    417  * measure() on them again with actual numbers if the sum of all the children's
    418  * unconstrained sizes is too big or too small.
    419  * </p>
    420  *
    421  * <p>
    422  * The measure pass uses two classes to communicate dimensions. The
    423  * {@link MeasureSpec} class is used by views to tell their parents how they
    424  * want to be measured and positioned. The base LayoutParams class just
    425  * describes how big the view wants to be for both width and height. For each
    426  * dimension, it can specify one of:
    427  * <ul>
    428  * <li> an exact number
    429  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
    430  * (minus padding)
    431  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
    432  * enclose its content (plus padding).
    433  * </ul>
    434  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
    435  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
    436  * an X and Y value.
    437  * </p>
    438  *
    439  * <p>
    440  * MeasureSpecs are used to push requirements down the tree from parent to
    441  * child. A MeasureSpec can be in one of three modes:
    442  * <ul>
    443  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
    444  * of a child view. For example, a LinearLayout may call measure() on its child
    445  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
    446  * tall the child view wants to be given a width of 240 pixels.
    447  * <li>EXACTLY: This is used by the parent to impose an exact size on the
    448  * child. The child must use this size, and guarantee that all of its
    449  * descendants will fit within this size.
    450  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
    451  * child. The child must guarantee that it and all of its descendants will fit
    452  * within this size.
    453  * </ul>
    454  * </p>
    455  *
    456  * <p>
    457  * To initiate a layout, call {@link #requestLayout}. This method is typically
    458  * called by a view on itself when it believes that is can no longer fit within
    459  * its current bounds.
    460  * </p>
    461  *
    462  * <a name="Drawing"></a>
    463  * <h3>Drawing</h3>
    464  * <p>
    465  * Drawing is handled by walking the tree and recording the drawing commands of
    466  * any View that needs to update. After this, the drawing commands of the
    467  * entire tree are issued to screen, clipped to the newly damaged area.
    468  * </p>
    469  *
    470  * <p>
    471  * The tree is largely recorded and drawn in order, with parents drawn before
    472  * (i.e., behind) their children, with siblings drawn in the order they appear
    473  * in the tree. If you set a background drawable for a View, then the View will
    474  * draw it before calling back to its <code>onDraw()</code> method. The child
    475  * drawing order can be overridden with
    476  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
    477  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
    478  * </p>
    479  *
    480  * <p>
    481  * To force a view to draw, call {@link #invalidate()}.
    482  * </p>
    483  *
    484  * <a name="EventHandlingThreading"></a>
    485  * <h3>Event Handling and Threading</h3>
    486  * <p>
    487  * The basic cycle of a view is as follows:
    488  * <ol>
    489  * <li>An event comes in and is dispatched to the appropriate view. The view
    490  * handles the event and notifies any listeners.</li>
    491  * <li>If in the course of processing the event, the view's bounds may need
    492  * to be changed, the view will call {@link #requestLayout()}.</li>
    493  * <li>Similarly, if in the course of processing the event the view's appearance
    494  * may need to be changed, the view will call {@link #invalidate()}.</li>
    495  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
    496  * the framework will take care of measuring, laying out, and drawing the tree
    497  * as appropriate.</li>
    498  * </ol>
    499  * </p>
    500  *
    501  * <p><em>Note: The entire view tree is single threaded. You must always be on
    502  * the UI thread when calling any method on any view.</em>
    503  * If you are doing work on other threads and want to update the state of a view
    504  * from that thread, you should use a {@link Handler}.
    505  * </p>
    506  *
    507  * <a name="FocusHandling"></a>
    508  * <h3>Focus Handling</h3>
    509  * <p>
    510  * The framework will handle routine focus movement in response to user input.
    511  * This includes changing the focus as views are removed or hidden, or as new
    512  * views become available. Views indicate their willingness to take focus
    513  * through the {@link #isFocusable} method. To change whether a view can take
    514  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
    515  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
    516  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
    517  * </p>
    518  * <p>
    519  * Focus movement is based on an algorithm which finds the nearest neighbor in a
    520  * given direction. In rare cases, the default algorithm may not match the
    521  * intended behavior of the developer. In these situations, you can provide
    522  * explicit overrides by using these XML attributes in the layout file:
    523  * <pre>
    524  * nextFocusDown
    525  * nextFocusLeft
    526  * nextFocusRight
    527  * nextFocusUp
    528  * </pre>
    529  * </p>
    530  *
    531  *
    532  * <p>
    533  * To get a particular view to take focus, call {@link #requestFocus()}.
    534  * </p>
    535  *
    536  * <a name="TouchMode"></a>
    537  * <h3>Touch Mode</h3>
    538  * <p>
    539  * When a user is navigating a user interface via directional keys such as a D-pad, it is
    540  * necessary to give focus to actionable items such as buttons so the user can see
    541  * what will take input.  If the device has touch capabilities, however, and the user
    542  * begins interacting with the interface by touching it, it is no longer necessary to
    543  * always highlight, or give focus to, a particular view.  This motivates a mode
    544  * for interaction named 'touch mode'.
    545  * </p>
    546  * <p>
    547  * For a touch capable device, once the user touches the screen, the device
    548  * will enter touch mode.  From this point onward, only views for which
    549  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
    550  * Other views that are touchable, like buttons, will not take focus when touched; they will
    551  * only fire the on click listeners.
    552  * </p>
    553  * <p>
    554  * Any time a user hits a directional key, such as a D-pad direction, the view device will
    555  * exit touch mode, and find a view to take focus, so that the user may resume interacting
    556  * with the user interface without touching the screen again.
    557  * </p>
    558  * <p>
    559  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
    560  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
    561  * </p>
    562  *
    563  * <a name="Scrolling"></a>
    564  * <h3>Scrolling</h3>
    565  * <p>
    566  * The framework provides basic support for views that wish to internally
    567  * scroll their content. This includes keeping track of the X and Y scroll
    568  * offset as well as mechanisms for drawing scrollbars. See
    569  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
    570  * {@link #awakenScrollBars()} for more details.
    571  * </p>
    572  *
    573  * <a name="Tags"></a>
    574  * <h3>Tags</h3>
    575  * <p>
    576  * Unlike IDs, tags are not used to identify views. Tags are essentially an
    577  * extra piece of information that can be associated with a view. They are most
    578  * often used as a convenience to store data related to views in the views
    579  * themselves rather than by putting them in a separate structure.
    580  * </p>
    581  * <p>
    582  * Tags may be specified with character sequence values in layout XML as either
    583  * a single tag using the {@link android.R.styleable#View_tag android:tag}
    584  * attribute or multiple tags using the {@code <tag>} child element:
    585  * <pre>
    586  *     &ltView ...
    587  *           android:tag="@string/mytag_value" /&gt;
    588  *     &ltView ...&gt;
    589  *         &lttag android:id="@+id/mytag"
    590  *              android:value="@string/mytag_value" /&gt;
    591  *     &lt/View>
    592  * </pre>
    593  * </p>
    594  * <p>
    595  * Tags may also be specified with arbitrary objects from code using
    596  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
    597  * </p>
    598  *
    599  * <a name="Themes"></a>
    600  * <h3>Themes</h3>
    601  * <p>
    602  * By default, Views are created using the theme of the Context object supplied
    603  * to their constructor; however, a different theme may be specified by using
    604  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
    605  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
    606  * code.
    607  * </p>
    608  * <p>
    609  * When the {@link android.R.styleable#View_theme android:theme} attribute is
    610  * used in XML, the specified theme is applied on top of the inflation
    611  * context's theme (see {@link LayoutInflater}) and used for the view itself as
    612  * well as any child elements.
    613  * </p>
    614  * <p>
    615  * In the following example, both views will be created using the Material dark
    616  * color scheme; however, because an overlay theme is used which only defines a
    617  * subset of attributes, the value of
    618  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
    619  * the inflation context's theme (e.g. the Activity theme) will be preserved.
    620  * <pre>
    621  *     &ltLinearLayout
    622  *             ...
    623  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
    624  *         &ltView ...&gt;
    625  *     &lt/LinearLayout&gt;
    626  * </pre>
    627  * </p>
    628  *
    629  * <a name="Properties"></a>
    630  * <h3>Properties</h3>
    631  * <p>
    632  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
    633  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
    634  * available both in the {@link Property} form as well as in similarly-named setter/getter
    635  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
    636  * be used to set persistent state associated with these rendering-related properties on the view.
    637  * The properties and methods can also be used in conjunction with
    638  * {@link android.animation.Animator Animator}-based animations, described more in the
    639  * <a href="#Animation">Animation</a> section.
    640  * </p>
    641  *
    642  * <a name="Animation"></a>
    643  * <h3>Animation</h3>
    644  * <p>
    645  * Starting with Android 3.0, the preferred way of animating views is to use the
    646  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
    647  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
    648  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
    649  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
    650  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
    651  * makes animating these View properties particularly easy and efficient.
    652  * </p>
    653  * <p>
    654  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
    655  * You can attach an {@link Animation} object to a view using
    656  * {@link #setAnimation(Animation)} or
    657  * {@link #startAnimation(Animation)}. The animation can alter the scale,
    658  * rotation, translation and alpha of a view over time. If the animation is
    659  * attached to a view that has children, the animation will affect the entire
    660  * subtree rooted by that node. When an animation is started, the framework will
    661  * take care of redrawing the appropriate views until the animation completes.
    662  * </p>
    663  *
    664  * <a name="Security"></a>
    665  * <h3>Security</h3>
    666  * <p>
    667  * Sometimes it is essential that an application be able to verify that an action
    668  * is being performed with the full knowledge and consent of the user, such as
    669  * granting a permission request, making a purchase or clicking on an advertisement.
    670  * Unfortunately, a malicious application could try to spoof the user into
    671  * performing these actions, unaware, by concealing the intended purpose of the view.
    672  * As a remedy, the framework offers a touch filtering mechanism that can be used to
    673  * improve the security of views that provide access to sensitive functionality.
    674  * </p><p>
    675  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
    676  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
    677  * will discard touches that are received whenever the view's window is obscured by
    678  * another visible window.  As a result, the view will not receive touches whenever a
    679  * toast, dialog or other window appears above the view's window.
    680  * </p><p>
    681  * For more fine-grained control over security, consider overriding the
    682  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
    683  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
    684  * </p>
    685  *
    686  * @attr ref android.R.styleable#View_alpha
    687  * @attr ref android.R.styleable#View_background
    688  * @attr ref android.R.styleable#View_clickable
    689  * @attr ref android.R.styleable#View_contentDescription
    690  * @attr ref android.R.styleable#View_drawingCacheQuality
    691  * @attr ref android.R.styleable#View_duplicateParentState
    692  * @attr ref android.R.styleable#View_id
    693  * @attr ref android.R.styleable#View_requiresFadingEdge
    694  * @attr ref android.R.styleable#View_fadeScrollbars
    695  * @attr ref android.R.styleable#View_fadingEdgeLength
    696  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
    697  * @attr ref android.R.styleable#View_fitsSystemWindows
    698  * @attr ref android.R.styleable#View_isScrollContainer
    699  * @attr ref android.R.styleable#View_focusable
    700  * @attr ref android.R.styleable#View_focusableInTouchMode
    701  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
    702  * @attr ref android.R.styleable#View_keepScreenOn
    703  * @attr ref android.R.styleable#View_layerType
    704  * @attr ref android.R.styleable#View_layoutDirection
    705  * @attr ref android.R.styleable#View_longClickable
    706  * @attr ref android.R.styleable#View_minHeight
    707  * @attr ref android.R.styleable#View_minWidth
    708  * @attr ref android.R.styleable#View_nextFocusDown
    709  * @attr ref android.R.styleable#View_nextFocusLeft
    710  * @attr ref android.R.styleable#View_nextFocusRight
    711  * @attr ref android.R.styleable#View_nextFocusUp
    712  * @attr ref android.R.styleable#View_onClick
    713  * @attr ref android.R.styleable#View_padding
    714  * @attr ref android.R.styleable#View_paddingBottom
    715  * @attr ref android.R.styleable#View_paddingLeft
    716  * @attr ref android.R.styleable#View_paddingRight
    717  * @attr ref android.R.styleable#View_paddingTop
    718  * @attr ref android.R.styleable#View_paddingStart
    719  * @attr ref android.R.styleable#View_paddingEnd
    720  * @attr ref android.R.styleable#View_saveEnabled
    721  * @attr ref android.R.styleable#View_rotation
    722  * @attr ref android.R.styleable#View_rotationX
    723  * @attr ref android.R.styleable#View_rotationY
    724  * @attr ref android.R.styleable#View_scaleX
    725  * @attr ref android.R.styleable#View_scaleY
    726  * @attr ref android.R.styleable#View_scrollX
    727  * @attr ref android.R.styleable#View_scrollY
    728  * @attr ref android.R.styleable#View_scrollbarSize
    729  * @attr ref android.R.styleable#View_scrollbarStyle
    730  * @attr ref android.R.styleable#View_scrollbars
    731  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
    732  * @attr ref android.R.styleable#View_scrollbarFadeDuration
    733  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
    734  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
    735  * @attr ref android.R.styleable#View_scrollbarThumbVertical
    736  * @attr ref android.R.styleable#View_scrollbarTrackVertical
    737  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
    738  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
    739  * @attr ref android.R.styleable#View_stateListAnimator
    740  * @attr ref android.R.styleable#View_transitionName
    741  * @attr ref android.R.styleable#View_soundEffectsEnabled
    742  * @attr ref android.R.styleable#View_tag
    743  * @attr ref android.R.styleable#View_textAlignment
    744  * @attr ref android.R.styleable#View_textDirection
    745  * @attr ref android.R.styleable#View_transformPivotX
    746  * @attr ref android.R.styleable#View_transformPivotY
    747  * @attr ref android.R.styleable#View_translationX
    748  * @attr ref android.R.styleable#View_translationY
    749  * @attr ref android.R.styleable#View_translationZ
    750  * @attr ref android.R.styleable#View_visibility
    751  * @attr ref android.R.styleable#View_theme
    752  *
    753  * @see android.view.ViewGroup
    754  */
    755 @UiThread
    756 public class View implements Drawable.Callback, KeyEvent.Callback,
    757         AccessibilityEventSource {
    758     private static final boolean DBG = false;
    759 
    760     /**
    761      * The logging tag used by this class with android.util.Log.
    762      */
    763     protected static final String VIEW_LOG_TAG = "View";
    764 
    765     /**
    766      * When set to true, apps will draw debugging information about their layouts.
    767      *
    768      * @hide
    769      */
    770     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
    771 
    772     /**
    773      * When set to true, this view will save its attribute data.
    774      *
    775      * @hide
    776      */
    777     public static boolean mDebugViewAttributes = false;
    778 
    779     /**
    780      * Used to mark a View that has no ID.
    781      */
    782     public static final int NO_ID = -1;
    783 
    784     /**
    785      * Signals that compatibility booleans have been initialized according to
    786      * target SDK versions.
    787      */
    788     private static boolean sCompatibilityDone = false;
    789 
    790     /**
    791      * Use the old (broken) way of building MeasureSpecs.
    792      */
    793     private static boolean sUseBrokenMakeMeasureSpec = false;
    794 
    795     /**
    796      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
    797      */
    798     static boolean sUseZeroUnspecifiedMeasureSpec = false;
    799 
    800     /**
    801      * Ignore any optimizations using the measure cache.
    802      */
    803     private static boolean sIgnoreMeasureCache = false;
    804 
    805     /**
    806      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
    807      */
    808     private static boolean sAlwaysRemeasureExactly = false;
    809 
    810     /**
    811      * Relax constraints around whether setLayoutParams() must be called after
    812      * modifying the layout params.
    813      */
    814     private static boolean sLayoutParamsAlwaysChanged = false;
    815 
    816     /**
    817      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
    818      * without throwing
    819      */
    820     static boolean sTextureViewIgnoresDrawableSetters = false;
    821 
    822     /**
    823      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
    824      * calling setFlags.
    825      */
    826     private static final int NOT_FOCUSABLE = 0x00000000;
    827 
    828     /**
    829      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
    830      * setFlags.
    831      */
    832     private static final int FOCUSABLE = 0x00000001;
    833 
    834     /**
    835      * Mask for use with setFlags indicating bits used for focus.
    836      */
    837     private static final int FOCUSABLE_MASK = 0x00000001;
    838 
    839     /**
    840      * This view will adjust its padding to fit sytem windows (e.g. status bar)
    841      */
    842     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
    843 
    844     /** @hide */
    845     @IntDef({VISIBLE, INVISIBLE, GONE})
    846     @Retention(RetentionPolicy.SOURCE)
    847     public @interface Visibility {}
    848 
    849     /**
    850      * This view is visible.
    851      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    852      * android:visibility}.
    853      */
    854     public static final int VISIBLE = 0x00000000;
    855 
    856     /**
    857      * This view is invisible, but it still takes up space for layout purposes.
    858      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    859      * android:visibility}.
    860      */
    861     public static final int INVISIBLE = 0x00000004;
    862 
    863     /**
    864      * This view is invisible, and it doesn't take any space for layout
    865      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    866      * android:visibility}.
    867      */
    868     public static final int GONE = 0x00000008;
    869 
    870     /**
    871      * Mask for use with setFlags indicating bits used for visibility.
    872      * {@hide}
    873      */
    874     static final int VISIBILITY_MASK = 0x0000000C;
    875 
    876     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
    877 
    878     /**
    879      * This view is enabled. Interpretation varies by subclass.
    880      * Use with ENABLED_MASK when calling setFlags.
    881      * {@hide}
    882      */
    883     static final int ENABLED = 0x00000000;
    884 
    885     /**
    886      * This view is disabled. Interpretation varies by subclass.
    887      * Use with ENABLED_MASK when calling setFlags.
    888      * {@hide}
    889      */
    890     static final int DISABLED = 0x00000020;
    891 
    892    /**
    893     * Mask for use with setFlags indicating bits used for indicating whether
    894     * this view is enabled
    895     * {@hide}
    896     */
    897     static final int ENABLED_MASK = 0x00000020;
    898 
    899     /**
    900      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
    901      * called and further optimizations will be performed. It is okay to have
    902      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
    903      * {@hide}
    904      */
    905     static final int WILL_NOT_DRAW = 0x00000080;
    906 
    907     /**
    908      * Mask for use with setFlags indicating bits used for indicating whether
    909      * this view is will draw
    910      * {@hide}
    911      */
    912     static final int DRAW_MASK = 0x00000080;
    913 
    914     /**
    915      * <p>This view doesn't show scrollbars.</p>
    916      * {@hide}
    917      */
    918     static final int SCROLLBARS_NONE = 0x00000000;
    919 
    920     /**
    921      * <p>This view shows horizontal scrollbars.</p>
    922      * {@hide}
    923      */
    924     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
    925 
    926     /**
    927      * <p>This view shows vertical scrollbars.</p>
    928      * {@hide}
    929      */
    930     static final int SCROLLBARS_VERTICAL = 0x00000200;
    931 
    932     /**
    933      * <p>Mask for use with setFlags indicating bits used for indicating which
    934      * scrollbars are enabled.</p>
    935      * {@hide}
    936      */
    937     static final int SCROLLBARS_MASK = 0x00000300;
    938 
    939     /**
    940      * Indicates that the view should filter touches when its window is obscured.
    941      * Refer to the class comments for more information about this security feature.
    942      * {@hide}
    943      */
    944     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
    945 
    946     /**
    947      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
    948      * that they are optional and should be skipped if the window has
    949      * requested system UI flags that ignore those insets for layout.
    950      */
    951     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
    952 
    953     /**
    954      * <p>This view doesn't show fading edges.</p>
    955      * {@hide}
    956      */
    957     static final int FADING_EDGE_NONE = 0x00000000;
    958 
    959     /**
    960      * <p>This view shows horizontal fading edges.</p>
    961      * {@hide}
    962      */
    963     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
    964 
    965     /**
    966      * <p>This view shows vertical fading edges.</p>
    967      * {@hide}
    968      */
    969     static final int FADING_EDGE_VERTICAL = 0x00002000;
    970 
    971     /**
    972      * <p>Mask for use with setFlags indicating bits used for indicating which
    973      * fading edges are enabled.</p>
    974      * {@hide}
    975      */
    976     static final int FADING_EDGE_MASK = 0x00003000;
    977 
    978     /**
    979      * <p>Indicates this view can be clicked. When clickable, a View reacts
    980      * to clicks by notifying the OnClickListener.<p>
    981      * {@hide}
    982      */
    983     static final int CLICKABLE = 0x00004000;
    984 
    985     /**
    986      * <p>Indicates this view is caching its drawing into a bitmap.</p>
    987      * {@hide}
    988      */
    989     static final int DRAWING_CACHE_ENABLED = 0x00008000;
    990 
    991     /**
    992      * <p>Indicates that no icicle should be saved for this view.<p>
    993      * {@hide}
    994      */
    995     static final int SAVE_DISABLED = 0x000010000;
    996 
    997     /**
    998      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
    999      * property.</p>
   1000      * {@hide}
   1001      */
   1002     static final int SAVE_DISABLED_MASK = 0x000010000;
   1003 
   1004     /**
   1005      * <p>Indicates that no drawing cache should ever be created for this view.<p>
   1006      * {@hide}
   1007      */
   1008     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
   1009 
   1010     /**
   1011      * <p>Indicates this view can take / keep focus when int touch mode.</p>
   1012      * {@hide}
   1013      */
   1014     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
   1015 
   1016     /** @hide */
   1017     @Retention(RetentionPolicy.SOURCE)
   1018     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
   1019     public @interface DrawingCacheQuality {}
   1020 
   1021     /**
   1022      * <p>Enables low quality mode for the drawing cache.</p>
   1023      */
   1024     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
   1025 
   1026     /**
   1027      * <p>Enables high quality mode for the drawing cache.</p>
   1028      */
   1029     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
   1030 
   1031     /**
   1032      * <p>Enables automatic quality mode for the drawing cache.</p>
   1033      */
   1034     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
   1035 
   1036     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
   1037             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
   1038     };
   1039 
   1040     /**
   1041      * <p>Mask for use with setFlags indicating bits used for the cache
   1042      * quality property.</p>
   1043      * {@hide}
   1044      */
   1045     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
   1046 
   1047     /**
   1048      * <p>
   1049      * Indicates this view can be long clicked. When long clickable, a View
   1050      * reacts to long clicks by notifying the OnLongClickListener or showing a
   1051      * context menu.
   1052      * </p>
   1053      * {@hide}
   1054      */
   1055     static final int LONG_CLICKABLE = 0x00200000;
   1056 
   1057     /**
   1058      * <p>Indicates that this view gets its drawable states from its direct parent
   1059      * and ignores its original internal states.</p>
   1060      *
   1061      * @hide
   1062      */
   1063     static final int DUPLICATE_PARENT_STATE = 0x00400000;
   1064 
   1065     /**
   1066      * <p>
   1067      * Indicates this view can be context clicked. When context clickable, a View reacts to a
   1068      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
   1069      * OnContextClickListener.
   1070      * </p>
   1071      * {@hide}
   1072      */
   1073     static final int CONTEXT_CLICKABLE = 0x00800000;
   1074 
   1075 
   1076     /** @hide */
   1077     @IntDef({
   1078         SCROLLBARS_INSIDE_OVERLAY,
   1079         SCROLLBARS_INSIDE_INSET,
   1080         SCROLLBARS_OUTSIDE_OVERLAY,
   1081         SCROLLBARS_OUTSIDE_INSET
   1082     })
   1083     @Retention(RetentionPolicy.SOURCE)
   1084     public @interface ScrollBarStyle {}
   1085 
   1086     /**
   1087      * The scrollbar style to display the scrollbars inside the content area,
   1088      * without increasing the padding. The scrollbars will be overlaid with
   1089      * translucency on the view's content.
   1090      */
   1091     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
   1092 
   1093     /**
   1094      * The scrollbar style to display the scrollbars inside the padded area,
   1095      * increasing the padding of the view. The scrollbars will not overlap the
   1096      * content area of the view.
   1097      */
   1098     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
   1099 
   1100     /**
   1101      * The scrollbar style to display the scrollbars at the edge of the view,
   1102      * without increasing the padding. The scrollbars will be overlaid with
   1103      * translucency.
   1104      */
   1105     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
   1106 
   1107     /**
   1108      * The scrollbar style to display the scrollbars at the edge of the view,
   1109      * increasing the padding of the view. The scrollbars will only overlap the
   1110      * background, if any.
   1111      */
   1112     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
   1113 
   1114     /**
   1115      * Mask to check if the scrollbar style is overlay or inset.
   1116      * {@hide}
   1117      */
   1118     static final int SCROLLBARS_INSET_MASK = 0x01000000;
   1119 
   1120     /**
   1121      * Mask to check if the scrollbar style is inside or outside.
   1122      * {@hide}
   1123      */
   1124     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
   1125 
   1126     /**
   1127      * Mask for scrollbar style.
   1128      * {@hide}
   1129      */
   1130     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
   1131 
   1132     /**
   1133      * View flag indicating that the screen should remain on while the
   1134      * window containing this view is visible to the user.  This effectively
   1135      * takes care of automatically setting the WindowManager's
   1136      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
   1137      */
   1138     public static final int KEEP_SCREEN_ON = 0x04000000;
   1139 
   1140     /**
   1141      * View flag indicating whether this view should have sound effects enabled
   1142      * for events such as clicking and touching.
   1143      */
   1144     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
   1145 
   1146     /**
   1147      * View flag indicating whether this view should have haptic feedback
   1148      * enabled for events such as long presses.
   1149      */
   1150     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
   1151 
   1152     /**
   1153      * <p>Indicates that the view hierarchy should stop saving state when
   1154      * it reaches this view.  If state saving is initiated immediately at
   1155      * the view, it will be allowed.
   1156      * {@hide}
   1157      */
   1158     static final int PARENT_SAVE_DISABLED = 0x20000000;
   1159 
   1160     /**
   1161      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
   1162      * {@hide}
   1163      */
   1164     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
   1165 
   1166     /** @hide */
   1167     @IntDef(flag = true,
   1168             value = {
   1169                 FOCUSABLES_ALL,
   1170                 FOCUSABLES_TOUCH_MODE
   1171             })
   1172     @Retention(RetentionPolicy.SOURCE)
   1173     public @interface FocusableMode {}
   1174 
   1175     /**
   1176      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1177      * should add all focusable Views regardless if they are focusable in touch mode.
   1178      */
   1179     public static final int FOCUSABLES_ALL = 0x00000000;
   1180 
   1181     /**
   1182      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1183      * should add only Views focusable in touch mode.
   1184      */
   1185     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
   1186 
   1187     /** @hide */
   1188     @IntDef({
   1189             FOCUS_BACKWARD,
   1190             FOCUS_FORWARD,
   1191             FOCUS_LEFT,
   1192             FOCUS_UP,
   1193             FOCUS_RIGHT,
   1194             FOCUS_DOWN
   1195     })
   1196     @Retention(RetentionPolicy.SOURCE)
   1197     public @interface FocusDirection {}
   1198 
   1199     /** @hide */
   1200     @IntDef({
   1201             FOCUS_LEFT,
   1202             FOCUS_UP,
   1203             FOCUS_RIGHT,
   1204             FOCUS_DOWN
   1205     })
   1206     @Retention(RetentionPolicy.SOURCE)
   1207     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
   1208 
   1209     /**
   1210      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
   1211      * item.
   1212      */
   1213     public static final int FOCUS_BACKWARD = 0x00000001;
   1214 
   1215     /**
   1216      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
   1217      * item.
   1218      */
   1219     public static final int FOCUS_FORWARD = 0x00000002;
   1220 
   1221     /**
   1222      * Use with {@link #focusSearch(int)}. Move focus to the left.
   1223      */
   1224     public static final int FOCUS_LEFT = 0x00000011;
   1225 
   1226     /**
   1227      * Use with {@link #focusSearch(int)}. Move focus up.
   1228      */
   1229     public static final int FOCUS_UP = 0x00000021;
   1230 
   1231     /**
   1232      * Use with {@link #focusSearch(int)}. Move focus to the right.
   1233      */
   1234     public static final int FOCUS_RIGHT = 0x00000042;
   1235 
   1236     /**
   1237      * Use with {@link #focusSearch(int)}. Move focus down.
   1238      */
   1239     public static final int FOCUS_DOWN = 0x00000082;
   1240 
   1241     /**
   1242      * Bits of {@link #getMeasuredWidthAndState()} and
   1243      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
   1244      */
   1245     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
   1246 
   1247     /**
   1248      * Bits of {@link #getMeasuredWidthAndState()} and
   1249      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
   1250      */
   1251     public static final int MEASURED_STATE_MASK = 0xff000000;
   1252 
   1253     /**
   1254      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
   1255      * for functions that combine both width and height into a single int,
   1256      * such as {@link #getMeasuredState()} and the childState argument of
   1257      * {@link #resolveSizeAndState(int, int, int)}.
   1258      */
   1259     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
   1260 
   1261     /**
   1262      * Bit of {@link #getMeasuredWidthAndState()} and
   1263      * {@link #getMeasuredWidthAndState()} that indicates the measured size
   1264      * is smaller that the space the view would like to have.
   1265      */
   1266     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
   1267 
   1268     /**
   1269      * Base View state sets
   1270      */
   1271     // Singles
   1272     /**
   1273      * Indicates the view has no states set. States are used with
   1274      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1275      * view depending on its state.
   1276      *
   1277      * @see android.graphics.drawable.Drawable
   1278      * @see #getDrawableState()
   1279      */
   1280     protected static final int[] EMPTY_STATE_SET;
   1281     /**
   1282      * Indicates the view is enabled. States are used with
   1283      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1284      * view depending on its state.
   1285      *
   1286      * @see android.graphics.drawable.Drawable
   1287      * @see #getDrawableState()
   1288      */
   1289     protected static final int[] ENABLED_STATE_SET;
   1290     /**
   1291      * Indicates the view is focused. States are used with
   1292      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1293      * view depending on its state.
   1294      *
   1295      * @see android.graphics.drawable.Drawable
   1296      * @see #getDrawableState()
   1297      */
   1298     protected static final int[] FOCUSED_STATE_SET;
   1299     /**
   1300      * Indicates the view is selected. States are used with
   1301      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1302      * view depending on its state.
   1303      *
   1304      * @see android.graphics.drawable.Drawable
   1305      * @see #getDrawableState()
   1306      */
   1307     protected static final int[] SELECTED_STATE_SET;
   1308     /**
   1309      * Indicates the view is pressed. States are used with
   1310      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1311      * view depending on its state.
   1312      *
   1313      * @see android.graphics.drawable.Drawable
   1314      * @see #getDrawableState()
   1315      */
   1316     protected static final int[] PRESSED_STATE_SET;
   1317     /**
   1318      * Indicates the view's window has focus. States are used with
   1319      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1320      * view depending on its state.
   1321      *
   1322      * @see android.graphics.drawable.Drawable
   1323      * @see #getDrawableState()
   1324      */
   1325     protected static final int[] WINDOW_FOCUSED_STATE_SET;
   1326     // Doubles
   1327     /**
   1328      * Indicates the view is enabled and has the focus.
   1329      *
   1330      * @see #ENABLED_STATE_SET
   1331      * @see #FOCUSED_STATE_SET
   1332      */
   1333     protected static final int[] ENABLED_FOCUSED_STATE_SET;
   1334     /**
   1335      * Indicates the view is enabled and selected.
   1336      *
   1337      * @see #ENABLED_STATE_SET
   1338      * @see #SELECTED_STATE_SET
   1339      */
   1340     protected static final int[] ENABLED_SELECTED_STATE_SET;
   1341     /**
   1342      * Indicates the view is enabled and that its window has focus.
   1343      *
   1344      * @see #ENABLED_STATE_SET
   1345      * @see #WINDOW_FOCUSED_STATE_SET
   1346      */
   1347     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
   1348     /**
   1349      * Indicates the view is focused and selected.
   1350      *
   1351      * @see #FOCUSED_STATE_SET
   1352      * @see #SELECTED_STATE_SET
   1353      */
   1354     protected static final int[] FOCUSED_SELECTED_STATE_SET;
   1355     /**
   1356      * Indicates the view has the focus and that its window has the focus.
   1357      *
   1358      * @see #FOCUSED_STATE_SET
   1359      * @see #WINDOW_FOCUSED_STATE_SET
   1360      */
   1361     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1362     /**
   1363      * Indicates the view is selected and that its window has the focus.
   1364      *
   1365      * @see #SELECTED_STATE_SET
   1366      * @see #WINDOW_FOCUSED_STATE_SET
   1367      */
   1368     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
   1369     // Triples
   1370     /**
   1371      * Indicates the view is enabled, focused and selected.
   1372      *
   1373      * @see #ENABLED_STATE_SET
   1374      * @see #FOCUSED_STATE_SET
   1375      * @see #SELECTED_STATE_SET
   1376      */
   1377     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
   1378     /**
   1379      * Indicates the view is enabled, focused and its window has the focus.
   1380      *
   1381      * @see #ENABLED_STATE_SET
   1382      * @see #FOCUSED_STATE_SET
   1383      * @see #WINDOW_FOCUSED_STATE_SET
   1384      */
   1385     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1386     /**
   1387      * Indicates the view is enabled, selected and its window has the focus.
   1388      *
   1389      * @see #ENABLED_STATE_SET
   1390      * @see #SELECTED_STATE_SET
   1391      * @see #WINDOW_FOCUSED_STATE_SET
   1392      */
   1393     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1394     /**
   1395      * Indicates the view is focused, selected and its window has the focus.
   1396      *
   1397      * @see #FOCUSED_STATE_SET
   1398      * @see #SELECTED_STATE_SET
   1399      * @see #WINDOW_FOCUSED_STATE_SET
   1400      */
   1401     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1402     /**
   1403      * Indicates the view is enabled, focused, selected and its window
   1404      * has the focus.
   1405      *
   1406      * @see #ENABLED_STATE_SET
   1407      * @see #FOCUSED_STATE_SET
   1408      * @see #SELECTED_STATE_SET
   1409      * @see #WINDOW_FOCUSED_STATE_SET
   1410      */
   1411     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1412     /**
   1413      * Indicates the view is pressed and its window has the focus.
   1414      *
   1415      * @see #PRESSED_STATE_SET
   1416      * @see #WINDOW_FOCUSED_STATE_SET
   1417      */
   1418     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
   1419     /**
   1420      * Indicates the view is pressed and selected.
   1421      *
   1422      * @see #PRESSED_STATE_SET
   1423      * @see #SELECTED_STATE_SET
   1424      */
   1425     protected static final int[] PRESSED_SELECTED_STATE_SET;
   1426     /**
   1427      * Indicates the view is pressed, selected and its window has the focus.
   1428      *
   1429      * @see #PRESSED_STATE_SET
   1430      * @see #SELECTED_STATE_SET
   1431      * @see #WINDOW_FOCUSED_STATE_SET
   1432      */
   1433     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1434     /**
   1435      * Indicates the view is pressed and focused.
   1436      *
   1437      * @see #PRESSED_STATE_SET
   1438      * @see #FOCUSED_STATE_SET
   1439      */
   1440     protected static final int[] PRESSED_FOCUSED_STATE_SET;
   1441     /**
   1442      * Indicates the view is pressed, focused and its window has the focus.
   1443      *
   1444      * @see #PRESSED_STATE_SET
   1445      * @see #FOCUSED_STATE_SET
   1446      * @see #WINDOW_FOCUSED_STATE_SET
   1447      */
   1448     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1449     /**
   1450      * Indicates the view is pressed, focused and selected.
   1451      *
   1452      * @see #PRESSED_STATE_SET
   1453      * @see #SELECTED_STATE_SET
   1454      * @see #FOCUSED_STATE_SET
   1455      */
   1456     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
   1457     /**
   1458      * Indicates the view is pressed, focused, selected and its window has the focus.
   1459      *
   1460      * @see #PRESSED_STATE_SET
   1461      * @see #FOCUSED_STATE_SET
   1462      * @see #SELECTED_STATE_SET
   1463      * @see #WINDOW_FOCUSED_STATE_SET
   1464      */
   1465     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1466     /**
   1467      * Indicates the view is pressed and enabled.
   1468      *
   1469      * @see #PRESSED_STATE_SET
   1470      * @see #ENABLED_STATE_SET
   1471      */
   1472     protected static final int[] PRESSED_ENABLED_STATE_SET;
   1473     /**
   1474      * Indicates the view is pressed, enabled and its window has the focus.
   1475      *
   1476      * @see #PRESSED_STATE_SET
   1477      * @see #ENABLED_STATE_SET
   1478      * @see #WINDOW_FOCUSED_STATE_SET
   1479      */
   1480     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
   1481     /**
   1482      * Indicates the view is pressed, enabled and selected.
   1483      *
   1484      * @see #PRESSED_STATE_SET
   1485      * @see #ENABLED_STATE_SET
   1486      * @see #SELECTED_STATE_SET
   1487      */
   1488     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
   1489     /**
   1490      * Indicates the view is pressed, enabled, selected and its window has the
   1491      * focus.
   1492      *
   1493      * @see #PRESSED_STATE_SET
   1494      * @see #ENABLED_STATE_SET
   1495      * @see #SELECTED_STATE_SET
   1496      * @see #WINDOW_FOCUSED_STATE_SET
   1497      */
   1498     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1499     /**
   1500      * Indicates the view is pressed, enabled and focused.
   1501      *
   1502      * @see #PRESSED_STATE_SET
   1503      * @see #ENABLED_STATE_SET
   1504      * @see #FOCUSED_STATE_SET
   1505      */
   1506     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
   1507     /**
   1508      * Indicates the view is pressed, enabled, focused and its window has the
   1509      * focus.
   1510      *
   1511      * @see #PRESSED_STATE_SET
   1512      * @see #ENABLED_STATE_SET
   1513      * @see #FOCUSED_STATE_SET
   1514      * @see #WINDOW_FOCUSED_STATE_SET
   1515      */
   1516     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1517     /**
   1518      * Indicates the view is pressed, enabled, focused and selected.
   1519      *
   1520      * @see #PRESSED_STATE_SET
   1521      * @see #ENABLED_STATE_SET
   1522      * @see #SELECTED_STATE_SET
   1523      * @see #FOCUSED_STATE_SET
   1524      */
   1525     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
   1526     /**
   1527      * Indicates the view is pressed, enabled, focused, selected and its window
   1528      * has the focus.
   1529      *
   1530      * @see #PRESSED_STATE_SET
   1531      * @see #ENABLED_STATE_SET
   1532      * @see #SELECTED_STATE_SET
   1533      * @see #FOCUSED_STATE_SET
   1534      * @see #WINDOW_FOCUSED_STATE_SET
   1535      */
   1536     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1537 
   1538     static {
   1539         EMPTY_STATE_SET = StateSet.get(0);
   1540 
   1541         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
   1542 
   1543         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
   1544         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1545                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
   1546 
   1547         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
   1548         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1549                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
   1550         FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1551                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
   1552         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1553                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1554                         | StateSet.VIEW_STATE_FOCUSED);
   1555 
   1556         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
   1557         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1558                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   1559         ENABLED_SELECTED_STATE_SET = StateSet.get(
   1560                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
   1561         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1562                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1563                         | StateSet.VIEW_STATE_ENABLED);
   1564         ENABLED_FOCUSED_STATE_SET = StateSet.get(
   1565                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   1566         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1567                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1568                         | StateSet.VIEW_STATE_ENABLED);
   1569         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1570                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1571                         | StateSet.VIEW_STATE_ENABLED);
   1572         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1573                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1574                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
   1575 
   1576         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
   1577         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1578                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1579         PRESSED_SELECTED_STATE_SET = StateSet.get(
   1580                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
   1581         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1582                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1583                         | StateSet.VIEW_STATE_PRESSED);
   1584         PRESSED_FOCUSED_STATE_SET = StateSet.get(
   1585                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1586         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1587                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1588                         | StateSet.VIEW_STATE_PRESSED);
   1589         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1590                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1591                         | StateSet.VIEW_STATE_PRESSED);
   1592         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1593                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1594                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1595         PRESSED_ENABLED_STATE_SET = StateSet.get(
   1596                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1597         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1598                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
   1599                         | StateSet.VIEW_STATE_PRESSED);
   1600         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
   1601                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
   1602                         | StateSet.VIEW_STATE_PRESSED);
   1603         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1604                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1605                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1606         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
   1607                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
   1608                         | StateSet.VIEW_STATE_PRESSED);
   1609         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1610                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1611                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1612         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1613                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1614                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1615         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1616                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1617                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
   1618                         | StateSet.VIEW_STATE_PRESSED);
   1619     }
   1620 
   1621     /**
   1622      * Accessibility event types that are dispatched for text population.
   1623      */
   1624     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
   1625             AccessibilityEvent.TYPE_VIEW_CLICKED
   1626             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   1627             | AccessibilityEvent.TYPE_VIEW_SELECTED
   1628             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   1629             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   1630             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   1631             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   1632             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   1633             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
   1634             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
   1635             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
   1636 
   1637     /**
   1638      * Temporary Rect currently for use in setBackground().  This will probably
   1639      * be extended in the future to hold our own class with more than just
   1640      * a Rect. :)
   1641      */
   1642     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
   1643 
   1644     /**
   1645      * Map used to store views' tags.
   1646      */
   1647     private SparseArray<Object> mKeyedTags;
   1648 
   1649     /**
   1650      * The next available accessibility id.
   1651      */
   1652     private static int sNextAccessibilityViewId;
   1653 
   1654     /**
   1655      * The animation currently associated with this view.
   1656      * @hide
   1657      */
   1658     protected Animation mCurrentAnimation = null;
   1659 
   1660     /**
   1661      * Width as measured during measure pass.
   1662      * {@hide}
   1663      */
   1664     @ViewDebug.ExportedProperty(category = "measurement")
   1665     int mMeasuredWidth;
   1666 
   1667     /**
   1668      * Height as measured during measure pass.
   1669      * {@hide}
   1670      */
   1671     @ViewDebug.ExportedProperty(category = "measurement")
   1672     int mMeasuredHeight;
   1673 
   1674     /**
   1675      * Flag to indicate that this view was marked INVALIDATED, or had its display list
   1676      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
   1677      * its display list. This flag, used only when hw accelerated, allows us to clear the
   1678      * flag while retaining this information until it's needed (at getDisplayList() time and
   1679      * in drawChild(), when we decide to draw a view's children's display lists into our own).
   1680      *
   1681      * {@hide}
   1682      */
   1683     boolean mRecreateDisplayList = false;
   1684 
   1685     /**
   1686      * The view's identifier.
   1687      * {@hide}
   1688      *
   1689      * @see #setId(int)
   1690      * @see #getId()
   1691      */
   1692     @IdRes
   1693     @ViewDebug.ExportedProperty(resolveId = true)
   1694     int mID = NO_ID;
   1695 
   1696     /**
   1697      * The stable ID of this view for accessibility purposes.
   1698      */
   1699     int mAccessibilityViewId = NO_ID;
   1700 
   1701     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   1702 
   1703     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
   1704 
   1705     /**
   1706      * The view's tag.
   1707      * {@hide}
   1708      *
   1709      * @see #setTag(Object)
   1710      * @see #getTag()
   1711      */
   1712     protected Object mTag = null;
   1713 
   1714     // for mPrivateFlags:
   1715     /** {@hide} */
   1716     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
   1717     /** {@hide} */
   1718     static final int PFLAG_FOCUSED                     = 0x00000002;
   1719     /** {@hide} */
   1720     static final int PFLAG_SELECTED                    = 0x00000004;
   1721     /** {@hide} */
   1722     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
   1723     /** {@hide} */
   1724     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
   1725     /** {@hide} */
   1726     static final int PFLAG_DRAWN                       = 0x00000020;
   1727     /**
   1728      * When this flag is set, this view is running an animation on behalf of its
   1729      * children and should therefore not cancel invalidate requests, even if they
   1730      * lie outside of this view's bounds.
   1731      *
   1732      * {@hide}
   1733      */
   1734     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
   1735     /** {@hide} */
   1736     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
   1737     /** {@hide} */
   1738     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
   1739     /** {@hide} */
   1740     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
   1741     /** {@hide} */
   1742     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
   1743     /** {@hide} */
   1744     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
   1745     /** {@hide} */
   1746     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
   1747 
   1748     private static final int PFLAG_PRESSED             = 0x00004000;
   1749 
   1750     /** {@hide} */
   1751     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
   1752     /**
   1753      * Flag used to indicate that this view should be drawn once more (and only once
   1754      * more) after its animation has completed.
   1755      * {@hide}
   1756      */
   1757     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
   1758 
   1759     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
   1760 
   1761     /**
   1762      * Indicates that the View returned true when onSetAlpha() was called and that
   1763      * the alpha must be restored.
   1764      * {@hide}
   1765      */
   1766     static final int PFLAG_ALPHA_SET                   = 0x00040000;
   1767 
   1768     /**
   1769      * Set by {@link #setScrollContainer(boolean)}.
   1770      */
   1771     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
   1772 
   1773     /**
   1774      * Set by {@link #setScrollContainer(boolean)}.
   1775      */
   1776     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
   1777 
   1778     /**
   1779      * View flag indicating whether this view was invalidated (fully or partially.)
   1780      *
   1781      * @hide
   1782      */
   1783     static final int PFLAG_DIRTY                       = 0x00200000;
   1784 
   1785     /**
   1786      * View flag indicating whether this view was invalidated by an opaque
   1787      * invalidate request.
   1788      *
   1789      * @hide
   1790      */
   1791     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
   1792 
   1793     /**
   1794      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
   1795      *
   1796      * @hide
   1797      */
   1798     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
   1799 
   1800     /**
   1801      * Indicates whether the background is opaque.
   1802      *
   1803      * @hide
   1804      */
   1805     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
   1806 
   1807     /**
   1808      * Indicates whether the scrollbars are opaque.
   1809      *
   1810      * @hide
   1811      */
   1812     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
   1813 
   1814     /**
   1815      * Indicates whether the view is opaque.
   1816      *
   1817      * @hide
   1818      */
   1819     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
   1820 
   1821     /**
   1822      * Indicates a prepressed state;
   1823      * the short time between ACTION_DOWN and recognizing
   1824      * a 'real' press. Prepressed is used to recognize quick taps
   1825      * even when they are shorter than ViewConfiguration.getTapTimeout().
   1826      *
   1827      * @hide
   1828      */
   1829     private static final int PFLAG_PREPRESSED          = 0x02000000;
   1830 
   1831     /**
   1832      * Indicates whether the view is temporarily detached.
   1833      *
   1834      * @hide
   1835      */
   1836     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
   1837 
   1838     /**
   1839      * Indicates that we should awaken scroll bars once attached
   1840      *
   1841      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
   1842      * during window attachment and it is no longer needed. Feel free to repurpose it.
   1843      *
   1844      * @hide
   1845      */
   1846     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
   1847 
   1848     /**
   1849      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
   1850      * @hide
   1851      */
   1852     private static final int PFLAG_HOVERED             = 0x10000000;
   1853 
   1854     /**
   1855      * no longer needed, should be reused
   1856      */
   1857     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
   1858 
   1859     /** {@hide} */
   1860     static final int PFLAG_ACTIVATED                   = 0x40000000;
   1861 
   1862     /**
   1863      * Indicates that this view was specifically invalidated, not just dirtied because some
   1864      * child view was invalidated. The flag is used to determine when we need to recreate
   1865      * a view's display list (as opposed to just returning a reference to its existing
   1866      * display list).
   1867      *
   1868      * @hide
   1869      */
   1870     static final int PFLAG_INVALIDATED                 = 0x80000000;
   1871 
   1872     /**
   1873      * Masks for mPrivateFlags2, as generated by dumpFlags():
   1874      *
   1875      * |-------|-------|-------|-------|
   1876      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
   1877      *                                1  PFLAG2_DRAG_HOVERED
   1878      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
   1879      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
   1880      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
   1881      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
   1882      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
   1883      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
   1884      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
   1885      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
   1886      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
   1887      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
   1888      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
   1889      *                         111       PFLAG2_TEXT_DIRECTION_MASK
   1890      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
   1891      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
   1892      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
   1893      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
   1894      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
   1895      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
   1896      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
   1897      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
   1898      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
   1899      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
   1900      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
   1901      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
   1902      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
   1903      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
   1904      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
   1905      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
   1906      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
   1907      *     1                             PFLAG2_VIEW_QUICK_REJECTED
   1908      *    1                              PFLAG2_PADDING_RESOLVED
   1909      *   1                               PFLAG2_DRAWABLE_RESOLVED
   1910      *  1                                PFLAG2_HAS_TRANSIENT_STATE
   1911      * |-------|-------|-------|-------|
   1912      */
   1913 
   1914     /**
   1915      * Indicates that this view has reported that it can accept the current drag's content.
   1916      * Cleared when the drag operation concludes.
   1917      * @hide
   1918      */
   1919     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
   1920 
   1921     /**
   1922      * Indicates that this view is currently directly under the drag location in a
   1923      * drag-and-drop operation involving content that it can accept.  Cleared when
   1924      * the drag exits the view, or when the drag operation concludes.
   1925      * @hide
   1926      */
   1927     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
   1928 
   1929     /** @hide */
   1930     @IntDef({
   1931         LAYOUT_DIRECTION_LTR,
   1932         LAYOUT_DIRECTION_RTL,
   1933         LAYOUT_DIRECTION_INHERIT,
   1934         LAYOUT_DIRECTION_LOCALE
   1935     })
   1936     @Retention(RetentionPolicy.SOURCE)
   1937     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
   1938     public @interface LayoutDir {}
   1939 
   1940     /** @hide */
   1941     @IntDef({
   1942         LAYOUT_DIRECTION_LTR,
   1943         LAYOUT_DIRECTION_RTL
   1944     })
   1945     @Retention(RetentionPolicy.SOURCE)
   1946     public @interface ResolvedLayoutDir {}
   1947 
   1948     /**
   1949      * A flag to indicate that the layout direction of this view has not been defined yet.
   1950      * @hide
   1951      */
   1952     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
   1953 
   1954     /**
   1955      * Horizontal layout direction of this view is from Left to Right.
   1956      * Use with {@link #setLayoutDirection}.
   1957      */
   1958     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
   1959 
   1960     /**
   1961      * Horizontal layout direction of this view is from Right to Left.
   1962      * Use with {@link #setLayoutDirection}.
   1963      */
   1964     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
   1965 
   1966     /**
   1967      * Horizontal layout direction of this view is inherited from its parent.
   1968      * Use with {@link #setLayoutDirection}.
   1969      */
   1970     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
   1971 
   1972     /**
   1973      * Horizontal layout direction of this view is from deduced from the default language
   1974      * script for the locale. Use with {@link #setLayoutDirection}.
   1975      */
   1976     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
   1977 
   1978     /**
   1979      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   1980      * @hide
   1981      */
   1982     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
   1983 
   1984     /**
   1985      * Mask for use with private flags indicating bits used for horizontal layout direction.
   1986      * @hide
   1987      */
   1988     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   1989 
   1990     /**
   1991      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
   1992      * right-to-left direction.
   1993      * @hide
   1994      */
   1995     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   1996 
   1997     /**
   1998      * Indicates whether the view horizontal layout direction has been resolved.
   1999      * @hide
   2000      */
   2001     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2002 
   2003     /**
   2004      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
   2005      * @hide
   2006      */
   2007     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
   2008             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2009 
   2010     /*
   2011      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
   2012      * flag value.
   2013      * @hide
   2014      */
   2015     private static final int[] LAYOUT_DIRECTION_FLAGS = {
   2016             LAYOUT_DIRECTION_LTR,
   2017             LAYOUT_DIRECTION_RTL,
   2018             LAYOUT_DIRECTION_INHERIT,
   2019             LAYOUT_DIRECTION_LOCALE
   2020     };
   2021 
   2022     /**
   2023      * Default horizontal layout direction.
   2024      */
   2025     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
   2026 
   2027     /**
   2028      * Default horizontal layout direction.
   2029      * @hide
   2030      */
   2031     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
   2032 
   2033     /**
   2034      * Text direction is inherited through {@link ViewGroup}
   2035      */
   2036     public static final int TEXT_DIRECTION_INHERIT = 0;
   2037 
   2038     /**
   2039      * Text direction is using "first strong algorithm". The first strong directional character
   2040      * determines the paragraph direction. If there is no strong directional character, the
   2041      * paragraph direction is the view's resolved layout direction.
   2042      */
   2043     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
   2044 
   2045     /**
   2046      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
   2047      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
   2048      * If there are neither, the paragraph direction is the view's resolved layout direction.
   2049      */
   2050     public static final int TEXT_DIRECTION_ANY_RTL = 2;
   2051 
   2052     /**
   2053      * Text direction is forced to LTR.
   2054      */
   2055     public static final int TEXT_DIRECTION_LTR = 3;
   2056 
   2057     /**
   2058      * Text direction is forced to RTL.
   2059      */
   2060     public static final int TEXT_DIRECTION_RTL = 4;
   2061 
   2062     /**
   2063      * Text direction is coming from the system Locale.
   2064      */
   2065     public static final int TEXT_DIRECTION_LOCALE = 5;
   2066 
   2067     /**
   2068      * Text direction is using "first strong algorithm". The first strong directional character
   2069      * determines the paragraph direction. If there is no strong directional character, the
   2070      * paragraph direction is LTR.
   2071      */
   2072     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
   2073 
   2074     /**
   2075      * Text direction is using "first strong algorithm". The first strong directional character
   2076      * determines the paragraph direction. If there is no strong directional character, the
   2077      * paragraph direction is RTL.
   2078      */
   2079     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
   2080 
   2081     /**
   2082      * Default text direction is inherited
   2083      */
   2084     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
   2085 
   2086     /**
   2087      * Default resolved text direction
   2088      * @hide
   2089      */
   2090     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
   2091 
   2092     /**
   2093      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
   2094      * @hide
   2095      */
   2096     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
   2097 
   2098     /**
   2099      * Mask for use with private flags indicating bits used for text direction.
   2100      * @hide
   2101      */
   2102     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
   2103             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2104 
   2105     /**
   2106      * Array of text direction flags for mapping attribute "textDirection" to correct
   2107      * flag value.
   2108      * @hide
   2109      */
   2110     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
   2111             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2112             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2113             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2114             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2115             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2116             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2117             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2118             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
   2119     };
   2120 
   2121     /**
   2122      * Indicates whether the view text direction has been resolved.
   2123      * @hide
   2124      */
   2125     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
   2126             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2127 
   2128     /**
   2129      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2130      * @hide
   2131      */
   2132     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
   2133 
   2134     /**
   2135      * Mask for use with private flags indicating bits used for resolved text direction.
   2136      * @hide
   2137      */
   2138     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
   2139             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2140 
   2141     /**
   2142      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
   2143      * @hide
   2144      */
   2145     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
   2146             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2147 
   2148     /** @hide */
   2149     @IntDef({
   2150         TEXT_ALIGNMENT_INHERIT,
   2151         TEXT_ALIGNMENT_GRAVITY,
   2152         TEXT_ALIGNMENT_CENTER,
   2153         TEXT_ALIGNMENT_TEXT_START,
   2154         TEXT_ALIGNMENT_TEXT_END,
   2155         TEXT_ALIGNMENT_VIEW_START,
   2156         TEXT_ALIGNMENT_VIEW_END
   2157     })
   2158     @Retention(RetentionPolicy.SOURCE)
   2159     public @interface TextAlignment {}
   2160 
   2161     /**
   2162      * Default text alignment. The text alignment of this View is inherited from its parent.
   2163      * Use with {@link #setTextAlignment(int)}
   2164      */
   2165     public static final int TEXT_ALIGNMENT_INHERIT = 0;
   2166 
   2167     /**
   2168      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
   2169      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraphs text direction.
   2170      *
   2171      * Use with {@link #setTextAlignment(int)}
   2172      */
   2173     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
   2174 
   2175     /**
   2176      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
   2177      *
   2178      * Use with {@link #setTextAlignment(int)}
   2179      */
   2180     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
   2181 
   2182     /**
   2183      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
   2184      *
   2185      * Use with {@link #setTextAlignment(int)}
   2186      */
   2187     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
   2188 
   2189     /**
   2190      * Center the paragraph, e.g. ALIGN_CENTER.
   2191      *
   2192      * Use with {@link #setTextAlignment(int)}
   2193      */
   2194     public static final int TEXT_ALIGNMENT_CENTER = 4;
   2195 
   2196     /**
   2197      * Align to the start of the view, which is ALIGN_LEFT if the views resolved
   2198      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
   2199      *
   2200      * Use with {@link #setTextAlignment(int)}
   2201      */
   2202     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
   2203 
   2204     /**
   2205      * Align to the end of the view, which is ALIGN_RIGHT if the views resolved
   2206      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
   2207      *
   2208      * Use with {@link #setTextAlignment(int)}
   2209      */
   2210     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
   2211 
   2212     /**
   2213      * Default text alignment is inherited
   2214      */
   2215     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2216 
   2217     /**
   2218      * Default resolved text alignment
   2219      * @hide
   2220      */
   2221     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2222 
   2223     /**
   2224       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2225       * @hide
   2226       */
   2227     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
   2228 
   2229     /**
   2230       * Mask for use with private flags indicating bits used for text alignment.
   2231       * @hide
   2232       */
   2233     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2234 
   2235     /**
   2236      * Array of text direction flags for mapping attribute "textAlignment" to correct
   2237      * flag value.
   2238      * @hide
   2239      */
   2240     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
   2241             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2242             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2243             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2244             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2245             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2246             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2247             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
   2248     };
   2249 
   2250     /**
   2251      * Indicates whether the view text alignment has been resolved.
   2252      * @hide
   2253      */
   2254     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2255 
   2256     /**
   2257      * Bit shift to get the resolved text alignment.
   2258      * @hide
   2259      */
   2260     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
   2261 
   2262     /**
   2263      * Mask for use with private flags indicating bits used for text alignment.
   2264      * @hide
   2265      */
   2266     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
   2267             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2268 
   2269     /**
   2270      * Indicates whether if the view text alignment has been resolved to gravity
   2271      */
   2272     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
   2273             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2274 
   2275     // Accessiblity constants for mPrivateFlags2
   2276 
   2277     /**
   2278      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2279      * "importantForAccessibility" attribute.
   2280      */
   2281     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
   2282 
   2283     /**
   2284      * Automatically determine whether a view is important for accessibility.
   2285      */
   2286     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
   2287 
   2288     /**
   2289      * The view is important for accessibility.
   2290      */
   2291     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
   2292 
   2293     /**
   2294      * The view is not important for accessibility.
   2295      */
   2296     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
   2297 
   2298     /**
   2299      * The view is not important for accessibility, nor are any of its
   2300      * descendant views.
   2301      */
   2302     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
   2303 
   2304     /**
   2305      * The default whether the view is important for accessibility.
   2306      */
   2307     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   2308 
   2309     /**
   2310      * Mask for obtainig the bits which specify how to determine
   2311      * whether a view is important for accessibility.
   2312      */
   2313     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
   2314         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
   2315         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
   2316         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   2317 
   2318     /**
   2319      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2320      * "accessibilityLiveRegion" attribute.
   2321      */
   2322     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
   2323 
   2324     /**
   2325      * Live region mode specifying that accessibility services should not
   2326      * automatically announce changes to this view. This is the default live
   2327      * region mode for most views.
   2328      * <p>
   2329      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2330      */
   2331     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
   2332 
   2333     /**
   2334      * Live region mode specifying that accessibility services should announce
   2335      * changes to this view.
   2336      * <p>
   2337      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2338      */
   2339     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
   2340 
   2341     /**
   2342      * Live region mode specifying that accessibility services should interrupt
   2343      * ongoing speech to immediately announce changes to this view.
   2344      * <p>
   2345      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2346      */
   2347     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
   2348 
   2349     /**
   2350      * The default whether the view is important for accessibility.
   2351      */
   2352     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
   2353 
   2354     /**
   2355      * Mask for obtaining the bits which specify a view's accessibility live
   2356      * region mode.
   2357      */
   2358     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
   2359             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
   2360             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   2361 
   2362     /**
   2363      * Flag indicating whether a view has accessibility focus.
   2364      */
   2365     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
   2366 
   2367     /**
   2368      * Flag whether the accessibility state of the subtree rooted at this view changed.
   2369      */
   2370     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
   2371 
   2372     /**
   2373      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
   2374      * is used to check whether later changes to the view's transform should invalidate the
   2375      * view to force the quickReject test to run again.
   2376      */
   2377     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
   2378 
   2379     /**
   2380      * Flag indicating that start/end padding has been resolved into left/right padding
   2381      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
   2382      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
   2383      * during measurement. In some special cases this is required such as when an adapter-based
   2384      * view measures prospective children without attaching them to a window.
   2385      */
   2386     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
   2387 
   2388     /**
   2389      * Flag indicating that the start/end drawables has been resolved into left/right ones.
   2390      */
   2391     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
   2392 
   2393     /**
   2394      * Indicates that the view is tracking some sort of transient state
   2395      * that the app should not need to be aware of, but that the framework
   2396      * should take special care to preserve.
   2397      */
   2398     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
   2399 
   2400     /**
   2401      * Group of bits indicating that RTL properties resolution is done.
   2402      */
   2403     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
   2404             PFLAG2_TEXT_DIRECTION_RESOLVED |
   2405             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   2406             PFLAG2_PADDING_RESOLVED |
   2407             PFLAG2_DRAWABLE_RESOLVED;
   2408 
   2409     // There are a couple of flags left in mPrivateFlags2
   2410 
   2411     /* End of masks for mPrivateFlags2 */
   2412 
   2413     /**
   2414      * Masks for mPrivateFlags3, as generated by dumpFlags():
   2415      *
   2416      * |-------|-------|-------|-------|
   2417      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
   2418      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
   2419      *                               1   PFLAG3_IS_LAID_OUT
   2420      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
   2421      *                             1     PFLAG3_CALLED_SUPER
   2422      *                            1      PFLAG3_APPLYING_INSETS
   2423      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
   2424      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
   2425      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
   2426      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
   2427      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
   2428      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
   2429      *                     1             PFLAG3_SCROLL_INDICATOR_START
   2430      *                    1              PFLAG3_SCROLL_INDICATOR_END
   2431      *                   1               PFLAG3_ASSIST_BLOCKED
   2432      *                  1                PFLAG3_POINTER_ICON_NULL
   2433      *                 1                 PFLAG3_POINTER_ICON_VALUE_START
   2434      *           11111111                PFLAG3_POINTER_ICON_MASK
   2435      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
   2436      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
   2437      *        1                          PFLAG3_TEMPORARY_DETACH
   2438      * |-------|-------|-------|-------|
   2439      */
   2440 
   2441     /**
   2442      * Flag indicating that view has a transform animation set on it. This is used to track whether
   2443      * an animation is cleared between successive frames, in order to tell the associated
   2444      * DisplayList to clear its animation matrix.
   2445      */
   2446     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
   2447 
   2448     /**
   2449      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
   2450      * animation is cleared between successive frames, in order to tell the associated
   2451      * DisplayList to restore its alpha value.
   2452      */
   2453     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
   2454 
   2455     /**
   2456      * Flag indicating that the view has been through at least one layout since it
   2457      * was last attached to a window.
   2458      */
   2459     static final int PFLAG3_IS_LAID_OUT = 0x4;
   2460 
   2461     /**
   2462      * Flag indicating that a call to measure() was skipped and should be done
   2463      * instead when layout() is invoked.
   2464      */
   2465     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
   2466 
   2467     /**
   2468      * Flag indicating that an overridden method correctly called down to
   2469      * the superclass implementation as required by the API spec.
   2470      */
   2471     static final int PFLAG3_CALLED_SUPER = 0x10;
   2472 
   2473     /**
   2474      * Flag indicating that we're in the process of applying window insets.
   2475      */
   2476     static final int PFLAG3_APPLYING_INSETS = 0x20;
   2477 
   2478     /**
   2479      * Flag indicating that we're in the process of fitting system windows using the old method.
   2480      */
   2481     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
   2482 
   2483     /**
   2484      * Flag indicating that nested scrolling is enabled for this view.
   2485      * The view will optionally cooperate with views up its parent chain to allow for
   2486      * integrated nested scrolling along the same axis.
   2487      */
   2488     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
   2489 
   2490     /**
   2491      * Flag indicating that the bottom scroll indicator should be displayed
   2492      * when this view can scroll up.
   2493      */
   2494     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
   2495 
   2496     /**
   2497      * Flag indicating that the bottom scroll indicator should be displayed
   2498      * when this view can scroll down.
   2499      */
   2500     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
   2501 
   2502     /**
   2503      * Flag indicating that the left scroll indicator should be displayed
   2504      * when this view can scroll left.
   2505      */
   2506     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
   2507 
   2508     /**
   2509      * Flag indicating that the right scroll indicator should be displayed
   2510      * when this view can scroll right.
   2511      */
   2512     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
   2513 
   2514     /**
   2515      * Flag indicating that the start scroll indicator should be displayed
   2516      * when this view can scroll in the start direction.
   2517      */
   2518     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
   2519 
   2520     /**
   2521      * Flag indicating that the end scroll indicator should be displayed
   2522      * when this view can scroll in the end direction.
   2523      */
   2524     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
   2525 
   2526     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
   2527 
   2528     static final int SCROLL_INDICATORS_NONE = 0x0000;
   2529 
   2530     /**
   2531      * Mask for use with setFlags indicating bits used for indicating which
   2532      * scroll indicators are enabled.
   2533      */
   2534     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
   2535             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
   2536             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
   2537             | PFLAG3_SCROLL_INDICATOR_END;
   2538 
   2539     /**
   2540      * Left-shift required to translate between public scroll indicator flags
   2541      * and internal PFLAGS3 flags. When used as a right-shift, translates
   2542      * PFLAGS3 flags to public flags.
   2543      */
   2544     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
   2545 
   2546     /** @hide */
   2547     @Retention(RetentionPolicy.SOURCE)
   2548     @IntDef(flag = true,
   2549             value = {
   2550                     SCROLL_INDICATOR_TOP,
   2551                     SCROLL_INDICATOR_BOTTOM,
   2552                     SCROLL_INDICATOR_LEFT,
   2553                     SCROLL_INDICATOR_RIGHT,
   2554                     SCROLL_INDICATOR_START,
   2555                     SCROLL_INDICATOR_END,
   2556             })
   2557     public @interface ScrollIndicators {}
   2558 
   2559     /**
   2560      * Scroll indicator direction for the top edge of the view.
   2561      *
   2562      * @see #setScrollIndicators(int)
   2563      * @see #setScrollIndicators(int, int)
   2564      * @see #getScrollIndicators()
   2565      */
   2566     public static final int SCROLL_INDICATOR_TOP =
   2567             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2568 
   2569     /**
   2570      * Scroll indicator direction for the bottom edge of the view.
   2571      *
   2572      * @see #setScrollIndicators(int)
   2573      * @see #setScrollIndicators(int, int)
   2574      * @see #getScrollIndicators()
   2575      */
   2576     public static final int SCROLL_INDICATOR_BOTTOM =
   2577             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2578 
   2579     /**
   2580      * Scroll indicator direction for the left edge of the view.
   2581      *
   2582      * @see #setScrollIndicators(int)
   2583      * @see #setScrollIndicators(int, int)
   2584      * @see #getScrollIndicators()
   2585      */
   2586     public static final int SCROLL_INDICATOR_LEFT =
   2587             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2588 
   2589     /**
   2590      * Scroll indicator direction for the right edge of the view.
   2591      *
   2592      * @see #setScrollIndicators(int)
   2593      * @see #setScrollIndicators(int, int)
   2594      * @see #getScrollIndicators()
   2595      */
   2596     public static final int SCROLL_INDICATOR_RIGHT =
   2597             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2598 
   2599     /**
   2600      * Scroll indicator direction for the starting edge of the view.
   2601      * <p>
   2602      * Resolved according to the view's layout direction, see
   2603      * {@link #getLayoutDirection()} for more information.
   2604      *
   2605      * @see #setScrollIndicators(int)
   2606      * @see #setScrollIndicators(int, int)
   2607      * @see #getScrollIndicators()
   2608      */
   2609     public static final int SCROLL_INDICATOR_START =
   2610             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2611 
   2612     /**
   2613      * Scroll indicator direction for the ending edge of the view.
   2614      * <p>
   2615      * Resolved according to the view's layout direction, see
   2616      * {@link #getLayoutDirection()} for more information.
   2617      *
   2618      * @see #setScrollIndicators(int)
   2619      * @see #setScrollIndicators(int, int)
   2620      * @see #getScrollIndicators()
   2621      */
   2622     public static final int SCROLL_INDICATOR_END =
   2623             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2624 
   2625     /**
   2626      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
   2627      * into this view.<p>
   2628      */
   2629     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
   2630 
   2631     /**
   2632      * The mask for use with private flags indicating bits used for pointer icon shapes.
   2633      */
   2634     static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
   2635 
   2636     /**
   2637      * Left-shift used for pointer icon shape values in private flags.
   2638      */
   2639     static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
   2640 
   2641     /**
   2642      * Value indicating no specific pointer icons.
   2643      */
   2644     private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
   2645 
   2646     /**
   2647      * Value indicating {@link PointerIcon.TYPE_NULL}.
   2648      */
   2649     private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
   2650 
   2651     /**
   2652      * The base value for other pointer icon shapes.
   2653      */
   2654     private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
   2655 
   2656     /**
   2657      * Whether this view has rendered elements that overlap (see {@link
   2658      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
   2659      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
   2660      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
   2661      * determined by whatever {@link #hasOverlappingRendering()} returns.
   2662      */
   2663     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
   2664 
   2665     /**
   2666      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
   2667      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
   2668      */
   2669     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
   2670 
   2671     /**
   2672      * Flag indicating that the view is temporarily detached from the parent view.
   2673      *
   2674      * @see #onStartTemporaryDetach()
   2675      * @see #onFinishTemporaryDetach()
   2676      */
   2677     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
   2678 
   2679     /* End of masks for mPrivateFlags3 */
   2680 
   2681     /**
   2682      * Always allow a user to over-scroll this view, provided it is a
   2683      * view that can scroll.
   2684      *
   2685      * @see #getOverScrollMode()
   2686      * @see #setOverScrollMode(int)
   2687      */
   2688     public static final int OVER_SCROLL_ALWAYS = 0;
   2689 
   2690     /**
   2691      * Allow a user to over-scroll this view only if the content is large
   2692      * enough to meaningfully scroll, provided it is a view that can scroll.
   2693      *
   2694      * @see #getOverScrollMode()
   2695      * @see #setOverScrollMode(int)
   2696      */
   2697     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
   2698 
   2699     /**
   2700      * Never allow a user to over-scroll this view.
   2701      *
   2702      * @see #getOverScrollMode()
   2703      * @see #setOverScrollMode(int)
   2704      */
   2705     public static final int OVER_SCROLL_NEVER = 2;
   2706 
   2707     /**
   2708      * Special constant for {@link #setSystemUiVisibility(int)}: View has
   2709      * requested the system UI (status bar) to be visible (the default).
   2710      *
   2711      * @see #setSystemUiVisibility(int)
   2712      */
   2713     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
   2714 
   2715     /**
   2716      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
   2717      * system UI to enter an unobtrusive "low profile" mode.
   2718      *
   2719      * <p>This is for use in games, book readers, video players, or any other
   2720      * "immersive" application where the usual system chrome is deemed too distracting.
   2721      *
   2722      * <p>In low profile mode, the status bar and/or navigation icons may dim.
   2723      *
   2724      * @see #setSystemUiVisibility(int)
   2725      */
   2726     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
   2727 
   2728     /**
   2729      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
   2730      * system navigation be temporarily hidden.
   2731      *
   2732      * <p>This is an even less obtrusive state than that called for by
   2733      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
   2734      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
   2735      * those to disappear. This is useful (in conjunction with the
   2736      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
   2737      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
   2738      * window flags) for displaying content using every last pixel on the display.
   2739      *
   2740      * <p>There is a limitation: because navigation controls are so important, the least user
   2741      * interaction will cause them to reappear immediately.  When this happens, both
   2742      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
   2743      * so that both elements reappear at the same time.
   2744      *
   2745      * @see #setSystemUiVisibility(int)
   2746      */
   2747     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
   2748 
   2749     /**
   2750      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
   2751      * into the normal fullscreen mode so that its content can take over the screen
   2752      * while still allowing the user to interact with the application.
   2753      *
   2754      * <p>This has the same visual effect as
   2755      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
   2756      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
   2757      * meaning that non-critical screen decorations (such as the status bar) will be
   2758      * hidden while the user is in the View's window, focusing the experience on
   2759      * that content.  Unlike the window flag, if you are using ActionBar in
   2760      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   2761      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
   2762      * hide the action bar.
   2763      *
   2764      * <p>This approach to going fullscreen is best used over the window flag when
   2765      * it is a transient state -- that is, the application does this at certain
   2766      * points in its user interaction where it wants to allow the user to focus
   2767      * on content, but not as a continuous state.  For situations where the application
   2768      * would like to simply stay full screen the entire time (such as a game that
   2769      * wants to take over the screen), the
   2770      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
   2771      * is usually a better approach.  The state set here will be removed by the system
   2772      * in various situations (such as the user moving to another application) like
   2773      * the other system UI states.
   2774      *
   2775      * <p>When using this flag, the application should provide some easy facility
   2776      * for the user to go out of it.  A common example would be in an e-book
   2777      * reader, where tapping on the screen brings back whatever screen and UI
   2778      * decorations that had been hidden while the user was immersed in reading
   2779      * the book.
   2780      *
   2781      * @see #setSystemUiVisibility(int)
   2782      */
   2783     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
   2784 
   2785     /**
   2786      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
   2787      * flags, we would like a stable view of the content insets given to
   2788      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
   2789      * will always represent the worst case that the application can expect
   2790      * as a continuous state.  In the stock Android UI this is the space for
   2791      * the system bar, nav bar, and status bar, but not more transient elements
   2792      * such as an input method.
   2793      *
   2794      * The stable layout your UI sees is based on the system UI modes you can
   2795      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   2796      * then you will get a stable layout for changes of the
   2797      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
   2798      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
   2799      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
   2800      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
   2801      * with a stable layout.  (Note that you should avoid using
   2802      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
   2803      *
   2804      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
   2805      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
   2806      * then a hidden status bar will be considered a "stable" state for purposes
   2807      * here.  This allows your UI to continually hide the status bar, while still
   2808      * using the system UI flags to hide the action bar while still retaining
   2809      * a stable layout.  Note that changing the window fullscreen flag will never
   2810      * provide a stable layout for a clean transition.
   2811      *
   2812      * <p>If you are using ActionBar in
   2813      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   2814      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
   2815      * insets it adds to those given to the application.
   2816      */
   2817     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
   2818 
   2819     /**
   2820      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   2821      * to be laid out as if it has requested
   2822      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
   2823      * allows it to avoid artifacts when switching in and out of that mode, at
   2824      * the expense that some of its user interface may be covered by screen
   2825      * decorations when they are shown.  You can perform layout of your inner
   2826      * UI elements to account for the navigation system UI through the
   2827      * {@link #fitSystemWindows(Rect)} method.
   2828      */
   2829     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
   2830 
   2831     /**
   2832      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   2833      * to be laid out as if it has requested
   2834      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
   2835      * allows it to avoid artifacts when switching in and out of that mode, at
   2836      * the expense that some of its user interface may be covered by screen
   2837      * decorations when they are shown.  You can perform layout of your inner
   2838      * UI elements to account for non-fullscreen system UI through the
   2839      * {@link #fitSystemWindows(Rect)} method.
   2840      */
   2841     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
   2842 
   2843     /**
   2844      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   2845      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
   2846      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
   2847      * user interaction.
   2848      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
   2849      * has an effect when used in combination with that flag.</p>
   2850      */
   2851     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
   2852 
   2853     /**
   2854      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   2855      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
   2856      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
   2857      * experience while also hiding the system bars.  If this flag is not set,
   2858      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
   2859      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
   2860      * if the user swipes from the top of the screen.
   2861      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
   2862      * system gestures, such as swiping from the top of the screen.  These transient system bars
   2863      * will overlay apps content, may have some degree of transparency, and will automatically
   2864      * hide after a short timeout.
   2865      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
   2866      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
   2867      * with one or both of those flags.</p>
   2868      */
   2869     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
   2870 
   2871     /**
   2872      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
   2873      * is compatible with light status bar backgrounds.
   2874      *
   2875      * <p>For this to take effect, the window must request
   2876      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
   2877      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
   2878      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
   2879      *         FLAG_TRANSLUCENT_STATUS}.
   2880      *
   2881      * @see android.R.attr#windowLightStatusBar
   2882      */
   2883     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
   2884 
   2885     /**
   2886      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
   2887      */
   2888     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
   2889 
   2890     /**
   2891      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
   2892      */
   2893     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
   2894 
   2895     /**
   2896      * @hide
   2897      *
   2898      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2899      * out of the public fields to keep the undefined bits out of the developer's way.
   2900      *
   2901      * Flag to make the status bar not expandable.  Unless you also
   2902      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
   2903      */
   2904     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
   2905 
   2906     /**
   2907      * @hide
   2908      *
   2909      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2910      * out of the public fields to keep the undefined bits out of the developer's way.
   2911      *
   2912      * Flag to hide notification icons and scrolling ticker text.
   2913      */
   2914     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
   2915 
   2916     /**
   2917      * @hide
   2918      *
   2919      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2920      * out of the public fields to keep the undefined bits out of the developer's way.
   2921      *
   2922      * Flag to disable incoming notification alerts.  This will not block
   2923      * icons, but it will block sound, vibrating and other visual or aural notifications.
   2924      */
   2925     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
   2926 
   2927     /**
   2928      * @hide
   2929      *
   2930      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2931      * out of the public fields to keep the undefined bits out of the developer's way.
   2932      *
   2933      * Flag to hide only the scrolling ticker.  Note that
   2934      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
   2935      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
   2936      */
   2937     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
   2938 
   2939     /**
   2940      * @hide
   2941      *
   2942      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2943      * out of the public fields to keep the undefined bits out of the developer's way.
   2944      *
   2945      * Flag to hide the center system info area.
   2946      */
   2947     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
   2948 
   2949     /**
   2950      * @hide
   2951      *
   2952      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2953      * out of the public fields to keep the undefined bits out of the developer's way.
   2954      *
   2955      * Flag to hide only the home button.  Don't use this
   2956      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   2957      */
   2958     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
   2959 
   2960     /**
   2961      * @hide
   2962      *
   2963      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2964      * out of the public fields to keep the undefined bits out of the developer's way.
   2965      *
   2966      * Flag to hide only the back button. Don't use this
   2967      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   2968      */
   2969     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
   2970 
   2971     /**
   2972      * @hide
   2973      *
   2974      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2975      * out of the public fields to keep the undefined bits out of the developer's way.
   2976      *
   2977      * Flag to hide only the clock.  You might use this if your activity has
   2978      * its own clock making the status bar's clock redundant.
   2979      */
   2980     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
   2981 
   2982     /**
   2983      * @hide
   2984      *
   2985      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2986      * out of the public fields to keep the undefined bits out of the developer's way.
   2987      *
   2988      * Flag to hide only the recent apps button. Don't use this
   2989      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   2990      */
   2991     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
   2992 
   2993     /**
   2994      * @hide
   2995      *
   2996      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2997      * out of the public fields to keep the undefined bits out of the developer's way.
   2998      *
   2999      * Flag to disable the global search gesture. Don't use this
   3000      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3001      */
   3002     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
   3003 
   3004     /**
   3005      * @hide
   3006      *
   3007      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3008      * out of the public fields to keep the undefined bits out of the developer's way.
   3009      *
   3010      * Flag to specify that the status bar is displayed in transient mode.
   3011      */
   3012     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
   3013 
   3014     /**
   3015      * @hide
   3016      *
   3017      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3018      * out of the public fields to keep the undefined bits out of the developer's way.
   3019      *
   3020      * Flag to specify that the navigation bar is displayed in transient mode.
   3021      */
   3022     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
   3023 
   3024     /**
   3025      * @hide
   3026      *
   3027      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3028      * out of the public fields to keep the undefined bits out of the developer's way.
   3029      *
   3030      * Flag to specify that the hidden status bar would like to be shown.
   3031      */
   3032     public static final int STATUS_BAR_UNHIDE = 0x10000000;
   3033 
   3034     /**
   3035      * @hide
   3036      *
   3037      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3038      * out of the public fields to keep the undefined bits out of the developer's way.
   3039      *
   3040      * Flag to specify that the hidden navigation bar would like to be shown.
   3041      */
   3042     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
   3043 
   3044     /**
   3045      * @hide
   3046      *
   3047      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3048      * out of the public fields to keep the undefined bits out of the developer's way.
   3049      *
   3050      * Flag to specify that the status bar is displayed in translucent mode.
   3051      */
   3052     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
   3053 
   3054     /**
   3055      * @hide
   3056      *
   3057      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3058      * out of the public fields to keep the undefined bits out of the developer's way.
   3059      *
   3060      * Flag to specify that the navigation bar is displayed in translucent mode.
   3061      */
   3062     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
   3063 
   3064     /**
   3065      * @hide
   3066      *
   3067      * Whether Recents is visible or not.
   3068      */
   3069     public static final int RECENT_APPS_VISIBLE = 0x00004000;
   3070 
   3071     /**
   3072      * @hide
   3073      *
   3074      * Whether the TV's picture-in-picture is visible or not.
   3075      */
   3076     public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000;
   3077 
   3078     /**
   3079      * @hide
   3080      *
   3081      * Makes navigation bar transparent (but not the status bar).
   3082      */
   3083     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
   3084 
   3085     /**
   3086      * @hide
   3087      *
   3088      * Makes status bar transparent (but not the navigation bar).
   3089      */
   3090     public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
   3091 
   3092     /**
   3093      * @hide
   3094      *
   3095      * Makes both status bar and navigation bar transparent.
   3096      */
   3097     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
   3098             | STATUS_BAR_TRANSPARENT;
   3099 
   3100     /**
   3101      * @hide
   3102      */
   3103     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
   3104 
   3105     /**
   3106      * These are the system UI flags that can be cleared by events outside
   3107      * of an application.  Currently this is just the ability to tap on the
   3108      * screen while hiding the navigation bar to have it return.
   3109      * @hide
   3110      */
   3111     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
   3112             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
   3113             | SYSTEM_UI_FLAG_FULLSCREEN;
   3114 
   3115     /**
   3116      * Flags that can impact the layout in relation to system UI.
   3117      */
   3118     public static final int SYSTEM_UI_LAYOUT_FLAGS =
   3119             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
   3120             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
   3121 
   3122     /** @hide */
   3123     @IntDef(flag = true,
   3124             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
   3125     @Retention(RetentionPolicy.SOURCE)
   3126     public @interface FindViewFlags {}
   3127 
   3128     /**
   3129      * Find views that render the specified text.
   3130      *
   3131      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3132      */
   3133     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
   3134 
   3135     /**
   3136      * Find find views that contain the specified content description.
   3137      *
   3138      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3139      */
   3140     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
   3141 
   3142     /**
   3143      * Find views that contain {@link AccessibilityNodeProvider}. Such
   3144      * a View is a root of virtual view hierarchy and may contain the searched
   3145      * text. If this flag is set Views with providers are automatically
   3146      * added and it is a responsibility of the client to call the APIs of
   3147      * the provider to determine whether the virtual tree rooted at this View
   3148      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
   3149      * representing the virtual views with this text.
   3150      *
   3151      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3152      *
   3153      * @hide
   3154      */
   3155     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
   3156 
   3157     /**
   3158      * The undefined cursor position.
   3159      *
   3160      * @hide
   3161      */
   3162     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
   3163 
   3164     /**
   3165      * Indicates that the screen has changed state and is now off.
   3166      *
   3167      * @see #onScreenStateChanged(int)
   3168      */
   3169     public static final int SCREEN_STATE_OFF = 0x0;
   3170 
   3171     /**
   3172      * Indicates that the screen has changed state and is now on.
   3173      *
   3174      * @see #onScreenStateChanged(int)
   3175      */
   3176     public static final int SCREEN_STATE_ON = 0x1;
   3177 
   3178     /**
   3179      * Indicates no axis of view scrolling.
   3180      */
   3181     public static final int SCROLL_AXIS_NONE = 0;
   3182 
   3183     /**
   3184      * Indicates scrolling along the horizontal axis.
   3185      */
   3186     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
   3187 
   3188     /**
   3189      * Indicates scrolling along the vertical axis.
   3190      */
   3191     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
   3192 
   3193     /**
   3194      * Controls the over-scroll mode for this view.
   3195      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
   3196      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
   3197      * and {@link #OVER_SCROLL_NEVER}.
   3198      */
   3199     private int mOverScrollMode;
   3200 
   3201     /**
   3202      * The parent this view is attached to.
   3203      * {@hide}
   3204      *
   3205      * @see #getParent()
   3206      */
   3207     protected ViewParent mParent;
   3208 
   3209     /**
   3210      * {@hide}
   3211      */
   3212     AttachInfo mAttachInfo;
   3213 
   3214     /**
   3215      * {@hide}
   3216      */
   3217     @ViewDebug.ExportedProperty(flagMapping = {
   3218         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
   3219                 name = "FORCE_LAYOUT"),
   3220         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
   3221                 name = "LAYOUT_REQUIRED"),
   3222         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
   3223             name = "DRAWING_CACHE_INVALID", outputIf = false),
   3224         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
   3225         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
   3226         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
   3227         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
   3228     }, formatToHexString = true)
   3229     int mPrivateFlags;
   3230     int mPrivateFlags2;
   3231     int mPrivateFlags3;
   3232 
   3233     /**
   3234      * This view's request for the visibility of the status bar.
   3235      * @hide
   3236      */
   3237     @ViewDebug.ExportedProperty(flagMapping = {
   3238         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
   3239                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
   3240                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
   3241         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3242                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3243                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
   3244         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
   3245                                 equals = SYSTEM_UI_FLAG_VISIBLE,
   3246                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
   3247     }, formatToHexString = true)
   3248     int mSystemUiVisibility;
   3249 
   3250     /**
   3251      * Reference count for transient state.
   3252      * @see #setHasTransientState(boolean)
   3253      */
   3254     int mTransientStateCount = 0;
   3255 
   3256     /**
   3257      * Count of how many windows this view has been attached to.
   3258      */
   3259     int mWindowAttachCount;
   3260 
   3261     /**
   3262      * The layout parameters associated with this view and used by the parent
   3263      * {@link android.view.ViewGroup} to determine how this view should be
   3264      * laid out.
   3265      * {@hide}
   3266      */
   3267     protected ViewGroup.LayoutParams mLayoutParams;
   3268 
   3269     /**
   3270      * The view flags hold various views states.
   3271      * {@hide}
   3272      */
   3273     @ViewDebug.ExportedProperty(formatToHexString = true)
   3274     int mViewFlags;
   3275 
   3276     static class TransformationInfo {
   3277         /**
   3278          * The transform matrix for the View. This transform is calculated internally
   3279          * based on the translation, rotation, and scale properties.
   3280          *
   3281          * Do *not* use this variable directly; instead call getMatrix(), which will
   3282          * load the value from the View's RenderNode.
   3283          */
   3284         private final Matrix mMatrix = new Matrix();
   3285 
   3286         /**
   3287          * The inverse transform matrix for the View. This transform is calculated
   3288          * internally based on the translation, rotation, and scale properties.
   3289          *
   3290          * Do *not* use this variable directly; instead call getInverseMatrix(),
   3291          * which will load the value from the View's RenderNode.
   3292          */
   3293         private Matrix mInverseMatrix;
   3294 
   3295         /**
   3296          * The opacity of the View. This is a value from 0 to 1, where 0 means
   3297          * completely transparent and 1 means completely opaque.
   3298          */
   3299         @ViewDebug.ExportedProperty
   3300         float mAlpha = 1f;
   3301 
   3302         /**
   3303          * The opacity of the view as manipulated by the Fade transition. This is a hidden
   3304          * property only used by transitions, which is composited with the other alpha
   3305          * values to calculate the final visual alpha value.
   3306          */
   3307         float mTransitionAlpha = 1f;
   3308     }
   3309 
   3310     TransformationInfo mTransformationInfo;
   3311 
   3312     /**
   3313      * Current clip bounds. to which all drawing of this view are constrained.
   3314      */
   3315     Rect mClipBounds = null;
   3316 
   3317     private boolean mLastIsOpaque;
   3318 
   3319     /**
   3320      * The distance in pixels from the left edge of this view's parent
   3321      * to the left edge of this view.
   3322      * {@hide}
   3323      */
   3324     @ViewDebug.ExportedProperty(category = "layout")
   3325     protected int mLeft;
   3326     /**
   3327      * The distance in pixels from the left edge of this view's parent
   3328      * to the right edge of this view.
   3329      * {@hide}
   3330      */
   3331     @ViewDebug.ExportedProperty(category = "layout")
   3332     protected int mRight;
   3333     /**
   3334      * The distance in pixels from the top edge of this view's parent
   3335      * to the top edge of this view.
   3336      * {@hide}
   3337      */
   3338     @ViewDebug.ExportedProperty(category = "layout")
   3339     protected int mTop;
   3340     /**
   3341      * The distance in pixels from the top edge of this view's parent
   3342      * to the bottom edge of this view.
   3343      * {@hide}
   3344      */
   3345     @ViewDebug.ExportedProperty(category = "layout")
   3346     protected int mBottom;
   3347 
   3348     /**
   3349      * The offset, in pixels, by which the content of this view is scrolled
   3350      * horizontally.
   3351      * {@hide}
   3352      */
   3353     @ViewDebug.ExportedProperty(category = "scrolling")
   3354     protected int mScrollX;
   3355     /**
   3356      * The offset, in pixels, by which the content of this view is scrolled
   3357      * vertically.
   3358      * {@hide}
   3359      */
   3360     @ViewDebug.ExportedProperty(category = "scrolling")
   3361     protected int mScrollY;
   3362 
   3363     /**
   3364      * The left padding in pixels, that is the distance in pixels between the
   3365      * left edge of this view and the left edge of its content.
   3366      * {@hide}
   3367      */
   3368     @ViewDebug.ExportedProperty(category = "padding")
   3369     protected int mPaddingLeft = 0;
   3370     /**
   3371      * The right padding in pixels, that is the distance in pixels between the
   3372      * right edge of this view and the right edge of its content.
   3373      * {@hide}
   3374      */
   3375     @ViewDebug.ExportedProperty(category = "padding")
   3376     protected int mPaddingRight = 0;
   3377     /**
   3378      * The top padding in pixels, that is the distance in pixels between the
   3379      * top edge of this view and the top edge of its content.
   3380      * {@hide}
   3381      */
   3382     @ViewDebug.ExportedProperty(category = "padding")
   3383     protected int mPaddingTop;
   3384     /**
   3385      * The bottom padding in pixels, that is the distance in pixels between the
   3386      * bottom edge of this view and the bottom edge of its content.
   3387      * {@hide}
   3388      */
   3389     @ViewDebug.ExportedProperty(category = "padding")
   3390     protected int mPaddingBottom;
   3391 
   3392     /**
   3393      * The layout insets in pixels, that is the distance in pixels between the
   3394      * visible edges of this view its bounds.
   3395      */
   3396     private Insets mLayoutInsets;
   3397 
   3398     /**
   3399      * Briefly describes the view and is primarily used for accessibility support.
   3400      */
   3401     private CharSequence mContentDescription;
   3402 
   3403     /**
   3404      * Specifies the id of a view for which this view serves as a label for
   3405      * accessibility purposes.
   3406      */
   3407     private int mLabelForId = View.NO_ID;
   3408 
   3409     /**
   3410      * Predicate for matching labeled view id with its label for
   3411      * accessibility purposes.
   3412      */
   3413     private MatchLabelForPredicate mMatchLabelForPredicate;
   3414 
   3415     /**
   3416      * Specifies a view before which this one is visited in accessibility traversal.
   3417      */
   3418     private int mAccessibilityTraversalBeforeId = NO_ID;
   3419 
   3420     /**
   3421      * Specifies a view after which this one is visited in accessibility traversal.
   3422      */
   3423     private int mAccessibilityTraversalAfterId = NO_ID;
   3424 
   3425     /**
   3426      * Predicate for matching a view by its id.
   3427      */
   3428     private MatchIdPredicate mMatchIdPredicate;
   3429 
   3430     /**
   3431      * Cache the paddingRight set by the user to append to the scrollbar's size.
   3432      *
   3433      * @hide
   3434      */
   3435     @ViewDebug.ExportedProperty(category = "padding")
   3436     protected int mUserPaddingRight;
   3437 
   3438     /**
   3439      * Cache the paddingBottom set by the user to append to the scrollbar's size.
   3440      *
   3441      * @hide
   3442      */
   3443     @ViewDebug.ExportedProperty(category = "padding")
   3444     protected int mUserPaddingBottom;
   3445 
   3446     /**
   3447      * Cache the paddingLeft set by the user to append to the scrollbar's size.
   3448      *
   3449      * @hide
   3450      */
   3451     @ViewDebug.ExportedProperty(category = "padding")
   3452     protected int mUserPaddingLeft;
   3453 
   3454     /**
   3455      * Cache the paddingStart set by the user to append to the scrollbar's size.
   3456      *
   3457      */
   3458     @ViewDebug.ExportedProperty(category = "padding")
   3459     int mUserPaddingStart;
   3460 
   3461     /**
   3462      * Cache the paddingEnd set by the user to append to the scrollbar's size.
   3463      *
   3464      */
   3465     @ViewDebug.ExportedProperty(category = "padding")
   3466     int mUserPaddingEnd;
   3467 
   3468     /**
   3469      * Cache initial left padding.
   3470      *
   3471      * @hide
   3472      */
   3473     int mUserPaddingLeftInitial;
   3474 
   3475     /**
   3476      * Cache initial right padding.
   3477      *
   3478      * @hide
   3479      */
   3480     int mUserPaddingRightInitial;
   3481 
   3482     /**
   3483      * Default undefined padding
   3484      */
   3485     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
   3486 
   3487     /**
   3488      * Cache if a left padding has been defined
   3489      */
   3490     private boolean mLeftPaddingDefined = false;
   3491 
   3492     /**
   3493      * Cache if a right padding has been defined
   3494      */
   3495     private boolean mRightPaddingDefined = false;
   3496 
   3497     /**
   3498      * @hide
   3499      */
   3500     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
   3501     /**
   3502      * @hide
   3503      */
   3504     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
   3505 
   3506     private LongSparseLongArray mMeasureCache;
   3507 
   3508     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
   3509     private Drawable mBackground;
   3510     private TintInfo mBackgroundTint;
   3511 
   3512     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
   3513     private ForegroundInfo mForegroundInfo;
   3514 
   3515     private Drawable mScrollIndicatorDrawable;
   3516 
   3517     /**
   3518      * RenderNode used for backgrounds.
   3519      * <p>
   3520      * When non-null and valid, this is expected to contain an up-to-date copy
   3521      * of the background drawable. It is cleared on temporary detach, and reset
   3522      * on cleanup.
   3523      */
   3524     private RenderNode mBackgroundRenderNode;
   3525 
   3526     private int mBackgroundResource;
   3527     private boolean mBackgroundSizeChanged;
   3528 
   3529     private String mTransitionName;
   3530 
   3531     static class TintInfo {
   3532         ColorStateList mTintList;
   3533         PorterDuff.Mode mTintMode;
   3534         boolean mHasTintMode;
   3535         boolean mHasTintList;
   3536     }
   3537 
   3538     private static class ForegroundInfo {
   3539         private Drawable mDrawable;
   3540         private TintInfo mTintInfo;
   3541         private int mGravity = Gravity.FILL;
   3542         private boolean mInsidePadding = true;
   3543         private boolean mBoundsChanged = true;
   3544         private final Rect mSelfBounds = new Rect();
   3545         private final Rect mOverlayBounds = new Rect();
   3546     }
   3547 
   3548     static class ListenerInfo {
   3549         /**
   3550          * Listener used to dispatch focus change events.
   3551          * This field should be made private, so it is hidden from the SDK.
   3552          * {@hide}
   3553          */
   3554         protected OnFocusChangeListener mOnFocusChangeListener;
   3555 
   3556         /**
   3557          * Listeners for layout change events.
   3558          */
   3559         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
   3560 
   3561         protected OnScrollChangeListener mOnScrollChangeListener;
   3562 
   3563         /**
   3564          * Listeners for attach events.
   3565          */
   3566         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
   3567 
   3568         /**
   3569          * Listener used to dispatch click events.
   3570          * This field should be made private, so it is hidden from the SDK.
   3571          * {@hide}
   3572          */
   3573         public OnClickListener mOnClickListener;
   3574 
   3575         /**
   3576          * Listener used to dispatch long click events.
   3577          * This field should be made private, so it is hidden from the SDK.
   3578          * {@hide}
   3579          */
   3580         protected OnLongClickListener mOnLongClickListener;
   3581 
   3582         /**
   3583          * Listener used to dispatch context click events. This field should be made private, so it
   3584          * is hidden from the SDK.
   3585          * {@hide}
   3586          */
   3587         protected OnContextClickListener mOnContextClickListener;
   3588 
   3589         /**
   3590          * Listener used to build the context menu.
   3591          * This field should be made private, so it is hidden from the SDK.
   3592          * {@hide}
   3593          */
   3594         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
   3595 
   3596         private OnKeyListener mOnKeyListener;
   3597 
   3598         private OnTouchListener mOnTouchListener;
   3599 
   3600         private OnHoverListener mOnHoverListener;
   3601 
   3602         private OnGenericMotionListener mOnGenericMotionListener;
   3603 
   3604         private OnDragListener mOnDragListener;
   3605 
   3606         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
   3607 
   3608         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
   3609     }
   3610 
   3611     ListenerInfo mListenerInfo;
   3612 
   3613     // Temporary values used to hold (x,y) coordinates when delegating from the
   3614     // two-arg performLongClick() method to the legacy no-arg version.
   3615     private float mLongClickX = Float.NaN;
   3616     private float mLongClickY = Float.NaN;
   3617 
   3618     /**
   3619      * The application environment this view lives in.
   3620      * This field should be made private, so it is hidden from the SDK.
   3621      * {@hide}
   3622      */
   3623     @ViewDebug.ExportedProperty(deepExport = true)
   3624     protected Context mContext;
   3625 
   3626     private final Resources mResources;
   3627 
   3628     private ScrollabilityCache mScrollCache;
   3629 
   3630     private int[] mDrawableState = null;
   3631 
   3632     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
   3633 
   3634     /**
   3635      * Animator that automatically runs based on state changes.
   3636      */
   3637     private StateListAnimator mStateListAnimator;
   3638 
   3639     /**
   3640      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
   3641      * the user may specify which view to go to next.
   3642      */
   3643     private int mNextFocusLeftId = View.NO_ID;
   3644 
   3645     /**
   3646      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
   3647      * the user may specify which view to go to next.
   3648      */
   3649     private int mNextFocusRightId = View.NO_ID;
   3650 
   3651     /**
   3652      * When this view has focus and the next focus is {@link #FOCUS_UP},
   3653      * the user may specify which view to go to next.
   3654      */
   3655     private int mNextFocusUpId = View.NO_ID;
   3656 
   3657     /**
   3658      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
   3659      * the user may specify which view to go to next.
   3660      */
   3661     private int mNextFocusDownId = View.NO_ID;
   3662 
   3663     /**
   3664      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
   3665      * the user may specify which view to go to next.
   3666      */
   3667     int mNextFocusForwardId = View.NO_ID;
   3668 
   3669     private CheckForLongPress mPendingCheckForLongPress;
   3670     private CheckForTap mPendingCheckForTap = null;
   3671     private PerformClick mPerformClick;
   3672     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
   3673 
   3674     private UnsetPressedState mUnsetPressedState;
   3675 
   3676     /**
   3677      * Whether the long press's action has been invoked.  The tap's action is invoked on the
   3678      * up event while a long press is invoked as soon as the long press duration is reached, so
   3679      * a long press could be performed before the tap is checked, in which case the tap's action
   3680      * should not be invoked.
   3681      */
   3682     private boolean mHasPerformedLongPress;
   3683 
   3684     /**
   3685      * Whether a context click button is currently pressed down. This is true when the stylus is
   3686      * touching the screen and the primary button has been pressed, or if a mouse's right button is
   3687      * pressed. This is false once the button is released or if the stylus has been lifted.
   3688      */
   3689     private boolean mInContextButtonPress;
   3690 
   3691     /**
   3692      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
   3693      * true after a stylus button press has occured, when the next up event should not be recognized
   3694      * as a tap.
   3695      */
   3696     private boolean mIgnoreNextUpEvent;
   3697 
   3698     /**
   3699      * The minimum height of the view. We'll try our best to have the height
   3700      * of this view to at least this amount.
   3701      */
   3702     @ViewDebug.ExportedProperty(category = "measurement")
   3703     private int mMinHeight;
   3704 
   3705     /**
   3706      * The minimum width of the view. We'll try our best to have the width
   3707      * of this view to at least this amount.
   3708      */
   3709     @ViewDebug.ExportedProperty(category = "measurement")
   3710     private int mMinWidth;
   3711 
   3712     /**
   3713      * The delegate to handle touch events that are physically in this view
   3714      * but should be handled by another view.
   3715      */
   3716     private TouchDelegate mTouchDelegate = null;
   3717 
   3718     /**
   3719      * Solid color to use as a background when creating the drawing cache. Enables
   3720      * the cache to use 16 bit bitmaps instead of 32 bit.
   3721      */
   3722     private int mDrawingCacheBackgroundColor = 0;
   3723 
   3724     /**
   3725      * Special tree observer used when mAttachInfo is null.
   3726      */
   3727     private ViewTreeObserver mFloatingTreeObserver;
   3728 
   3729     /**
   3730      * Cache the touch slop from the context that created the view.
   3731      */
   3732     private int mTouchSlop;
   3733 
   3734     /**
   3735      * Object that handles automatic animation of view properties.
   3736      */
   3737     private ViewPropertyAnimator mAnimator = null;
   3738 
   3739     /**
   3740      * List of registered FrameMetricsObservers.
   3741      */
   3742     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
   3743 
   3744     /**
   3745      * Flag indicating that a drag can cross window boundaries.  When
   3746      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
   3747      * with this flag set, all visible applications will be able to participate
   3748      * in the drag operation and receive the dragged content.
   3749      *
   3750      * If this is the only flag set, then the drag recipient will only have access to text data
   3751      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
   3752      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
   3753      */
   3754     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
   3755 
   3756     /**
   3757      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
   3758      * request read access to the content URI(s) contained in the {@link ClipData} object.
   3759      * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
   3760      */
   3761     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
   3762 
   3763     /**
   3764      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
   3765      * request write access to the content URI(s) contained in the {@link ClipData} object.
   3766      * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
   3767      */
   3768     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
   3769 
   3770     /**
   3771      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
   3772      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
   3773      * reboots until explicitly revoked with
   3774      * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
   3775      * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
   3776      */
   3777     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
   3778             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
   3779 
   3780     /**
   3781      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
   3782      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
   3783      * match against the original granted URI.
   3784      * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
   3785      */
   3786     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
   3787             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
   3788 
   3789     /**
   3790      * Flag indicating that the drag shadow will be opaque.  When
   3791      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
   3792      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
   3793      */
   3794     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
   3795 
   3796     /**
   3797      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
   3798      */
   3799     private float mVerticalScrollFactor;
   3800 
   3801     /**
   3802      * Position of the vertical scroll bar.
   3803      */
   3804     private int mVerticalScrollbarPosition;
   3805 
   3806     /**
   3807      * Position the scroll bar at the default position as determined by the system.
   3808      */
   3809     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
   3810 
   3811     /**
   3812      * Position the scroll bar along the left edge.
   3813      */
   3814     public static final int SCROLLBAR_POSITION_LEFT = 1;
   3815 
   3816     /**
   3817      * Position the scroll bar along the right edge.
   3818      */
   3819     public static final int SCROLLBAR_POSITION_RIGHT = 2;
   3820 
   3821     /**
   3822      * Indicates that the view does not have a layer.
   3823      *
   3824      * @see #getLayerType()
   3825      * @see #setLayerType(int, android.graphics.Paint)
   3826      * @see #LAYER_TYPE_SOFTWARE
   3827      * @see #LAYER_TYPE_HARDWARE
   3828      */
   3829     public static final int LAYER_TYPE_NONE = 0;
   3830 
   3831     /**
   3832      * <p>Indicates that the view has a software layer. A software layer is backed
   3833      * by a bitmap and causes the view to be rendered using Android's software
   3834      * rendering pipeline, even if hardware acceleration is enabled.</p>
   3835      *
   3836      * <p>Software layers have various usages:</p>
   3837      * <p>When the application is not using hardware acceleration, a software layer
   3838      * is useful to apply a specific color filter and/or blending mode and/or
   3839      * translucency to a view and all its children.</p>
   3840      * <p>When the application is using hardware acceleration, a software layer
   3841      * is useful to render drawing primitives not supported by the hardware
   3842      * accelerated pipeline. It can also be used to cache a complex view tree
   3843      * into a texture and reduce the complexity of drawing operations. For instance,
   3844      * when animating a complex view tree with a translation, a software layer can
   3845      * be used to render the view tree only once.</p>
   3846      * <p>Software layers should be avoided when the affected view tree updates
   3847      * often. Every update will require to re-render the software layer, which can
   3848      * potentially be slow (particularly when hardware acceleration is turned on
   3849      * since the layer will have to be uploaded into a hardware texture after every
   3850      * update.)</p>
   3851      *
   3852      * @see #getLayerType()
   3853      * @see #setLayerType(int, android.graphics.Paint)
   3854      * @see #LAYER_TYPE_NONE
   3855      * @see #LAYER_TYPE_HARDWARE
   3856      */
   3857     public static final int LAYER_TYPE_SOFTWARE = 1;
   3858 
   3859     /**
   3860      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
   3861      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
   3862      * OpenGL hardware) and causes the view to be rendered using Android's hardware
   3863      * rendering pipeline, but only if hardware acceleration is turned on for the
   3864      * view hierarchy. When hardware acceleration is turned off, hardware layers
   3865      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
   3866      *
   3867      * <p>A hardware layer is useful to apply a specific color filter and/or
   3868      * blending mode and/or translucency to a view and all its children.</p>
   3869      * <p>A hardware layer can be used to cache a complex view tree into a
   3870      * texture and reduce the complexity of drawing operations. For instance,
   3871      * when animating a complex view tree with a translation, a hardware layer can
   3872      * be used to render the view tree only once.</p>
   3873      * <p>A hardware layer can also be used to increase the rendering quality when
   3874      * rotation transformations are applied on a view. It can also be used to
   3875      * prevent potential clipping issues when applying 3D transforms on a view.</p>
   3876      *
   3877      * @see #getLayerType()
   3878      * @see #setLayerType(int, android.graphics.Paint)
   3879      * @see #LAYER_TYPE_NONE
   3880      * @see #LAYER_TYPE_SOFTWARE
   3881      */
   3882     public static final int LAYER_TYPE_HARDWARE = 2;
   3883 
   3884     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
   3885             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
   3886             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
   3887             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
   3888     })
   3889     int mLayerType = LAYER_TYPE_NONE;
   3890     Paint mLayerPaint;
   3891 
   3892     /**
   3893      * Set to true when drawing cache is enabled and cannot be created.
   3894      *
   3895      * @hide
   3896      */
   3897     public boolean mCachingFailed;
   3898     private Bitmap mDrawingCache;
   3899     private Bitmap mUnscaledDrawingCache;
   3900 
   3901     /**
   3902      * RenderNode holding View properties, potentially holding a DisplayList of View content.
   3903      * <p>
   3904      * When non-null and valid, this is expected to contain an up-to-date copy
   3905      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
   3906      * cleanup.
   3907      */
   3908     final RenderNode mRenderNode;
   3909 
   3910     /**
   3911      * Set to true when the view is sending hover accessibility events because it
   3912      * is the innermost hovered view.
   3913      */
   3914     private boolean mSendingHoverAccessibilityEvents;
   3915 
   3916     /**
   3917      * Delegate for injecting accessibility functionality.
   3918      */
   3919     AccessibilityDelegate mAccessibilityDelegate;
   3920 
   3921     /**
   3922      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
   3923      * and add/remove objects to/from the overlay directly through the Overlay methods.
   3924      */
   3925     ViewOverlay mOverlay;
   3926 
   3927     /**
   3928      * The currently active parent view for receiving delegated nested scrolling events.
   3929      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
   3930      * by {@link #stopNestedScroll()} at the same point where we clear
   3931      * requestDisallowInterceptTouchEvent.
   3932      */
   3933     private ViewParent mNestedScrollingParent;
   3934 
   3935     /**
   3936      * Consistency verifier for debugging purposes.
   3937      * @hide
   3938      */
   3939     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
   3940             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
   3941                     new InputEventConsistencyVerifier(this, 0) : null;
   3942 
   3943     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
   3944 
   3945     private int[] mTempNestedScrollConsumed;
   3946 
   3947     /**
   3948      * An overlay is going to draw this View instead of being drawn as part of this
   3949      * View's parent. mGhostView is the View in the Overlay that must be invalidated
   3950      * when this view is invalidated.
   3951      */
   3952     GhostView mGhostView;
   3953 
   3954     /**
   3955      * Holds pairs of adjacent attribute data: attribute name followed by its value.
   3956      * @hide
   3957      */
   3958     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
   3959     public String[] mAttributes;
   3960 
   3961     /**
   3962      * Maps a Resource id to its name.
   3963      */
   3964     private static SparseArray<String> mAttributeMap;
   3965 
   3966     /**
   3967      * Queue of pending runnables. Used to postpone calls to post() until this
   3968      * view is attached and has a handler.
   3969      */
   3970     private HandlerActionQueue mRunQueue;
   3971 
   3972     /**
   3973      * The pointer icon when the mouse hovers on this view. The default is null.
   3974      */
   3975     private PointerIcon mPointerIcon;
   3976 
   3977     /**
   3978      * @hide
   3979      */
   3980     String mStartActivityRequestWho;
   3981 
   3982     /**
   3983      * Simple constructor to use when creating a view from code.
   3984      *
   3985      * @param context The Context the view is running in, through which it can
   3986      *        access the current theme, resources, etc.
   3987      */
   3988     public View(Context context) {
   3989         mContext = context;
   3990         mResources = context != null ? context.getResources() : null;
   3991         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
   3992         // Set some flags defaults
   3993         mPrivateFlags2 =
   3994                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
   3995                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
   3996                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
   3997                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
   3998                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
   3999                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
   4000         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
   4001         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
   4002         mUserPaddingStart = UNDEFINED_PADDING;
   4003         mUserPaddingEnd = UNDEFINED_PADDING;
   4004         mRenderNode = RenderNode.create(getClass().getName(), this);
   4005 
   4006         if (!sCompatibilityDone && context != null) {
   4007             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   4008 
   4009             // Older apps may need this compatibility hack for measurement.
   4010             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
   4011 
   4012             // Older apps expect onMeasure() to always be called on a layout pass, regardless
   4013             // of whether a layout was requested on that View.
   4014             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
   4015 
   4016             Canvas.sCompatibilityRestore = targetSdkVersion < M;
   4017 
   4018             // In M and newer, our widgets can pass a "hint" value in the size
   4019             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
   4020             // know what the expected parent size is going to be, so e.g. list items can size
   4021             // themselves at 1/3 the size of their container. It breaks older apps though,
   4022             // specifically apps that use some popular open source libraries.
   4023             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
   4024 
   4025             // Old versions of the platform would give different results from
   4026             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
   4027             // modes, so we always need to run an additional EXACTLY pass.
   4028             sAlwaysRemeasureExactly = targetSdkVersion <= M;
   4029 
   4030             // Prior to N, layout params could change without requiring a
   4031             // subsequent call to setLayoutParams() and they would usually
   4032             // work. Partial layout breaks this assumption.
   4033             sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
   4034 
   4035             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
   4036             // On N+, we throw, but that breaks compatibility with apps that use these methods.
   4037             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
   4038 
   4039             sCompatibilityDone = true;
   4040         }
   4041     }
   4042 
   4043     /**
   4044      * Constructor that is called when inflating a view from XML. This is called
   4045      * when a view is being constructed from an XML file, supplying attributes
   4046      * that were specified in the XML file. This version uses a default style of
   4047      * 0, so the only attribute values applied are those in the Context's Theme
   4048      * and the given AttributeSet.
   4049      *
   4050      * <p>
   4051      * The method onFinishInflate() will be called after all children have been
   4052      * added.
   4053      *
   4054      * @param context The Context the view is running in, through which it can
   4055      *        access the current theme, resources, etc.
   4056      * @param attrs The attributes of the XML tag that is inflating the view.
   4057      * @see #View(Context, AttributeSet, int)
   4058      */
   4059     public View(Context context, @Nullable AttributeSet attrs) {
   4060         this(context, attrs, 0);
   4061     }
   4062 
   4063     /**
   4064      * Perform inflation from XML and apply a class-specific base style from a
   4065      * theme attribute. This constructor of View allows subclasses to use their
   4066      * own base style when they are inflating. For example, a Button class's
   4067      * constructor would call this version of the super class constructor and
   4068      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
   4069      * allows the theme's button style to modify all of the base view attributes
   4070      * (in particular its background) as well as the Button class's attributes.
   4071      *
   4072      * @param context The Context the view is running in, through which it can
   4073      *        access the current theme, resources, etc.
   4074      * @param attrs The attributes of the XML tag that is inflating the view.
   4075      * @param defStyleAttr An attribute in the current theme that contains a
   4076      *        reference to a style resource that supplies default values for
   4077      *        the view. Can be 0 to not look for defaults.
   4078      * @see #View(Context, AttributeSet)
   4079      */
   4080     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
   4081         this(context, attrs, defStyleAttr, 0);
   4082     }
   4083 
   4084     /**
   4085      * Perform inflation from XML and apply a class-specific base style from a
   4086      * theme attribute or style resource. This constructor of View allows
   4087      * subclasses to use their own base style when they are inflating.
   4088      * <p>
   4089      * When determining the final value of a particular attribute, there are
   4090      * four inputs that come into play:
   4091      * <ol>
   4092      * <li>Any attribute values in the given AttributeSet.
   4093      * <li>The style resource specified in the AttributeSet (named "style").
   4094      * <li>The default style specified by <var>defStyleAttr</var>.
   4095      * <li>The default style specified by <var>defStyleRes</var>.
   4096      * <li>The base values in this theme.
   4097      * </ol>
   4098      * <p>
   4099      * Each of these inputs is considered in-order, with the first listed taking
   4100      * precedence over the following ones. In other words, if in the
   4101      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
   4102      * , then the button's text will <em>always</em> be black, regardless of
   4103      * what is specified in any of the styles.
   4104      *
   4105      * @param context The Context the view is running in, through which it can
   4106      *        access the current theme, resources, etc.
   4107      * @param attrs The attributes of the XML tag that is inflating the view.
   4108      * @param defStyleAttr An attribute in the current theme that contains a
   4109      *        reference to a style resource that supplies default values for
   4110      *        the view. Can be 0 to not look for defaults.
   4111      * @param defStyleRes A resource identifier of a style resource that
   4112      *        supplies default values for the view, used only if
   4113      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
   4114      *        to not look for defaults.
   4115      * @see #View(Context, AttributeSet, int)
   4116      */
   4117     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
   4118         this(context);
   4119 
   4120         final TypedArray a = context.obtainStyledAttributes(
   4121                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
   4122 
   4123         if (mDebugViewAttributes) {
   4124             saveAttributeData(attrs, a);
   4125         }
   4126 
   4127         Drawable background = null;
   4128 
   4129         int leftPadding = -1;
   4130         int topPadding = -1;
   4131         int rightPadding = -1;
   4132         int bottomPadding = -1;
   4133         int startPadding = UNDEFINED_PADDING;
   4134         int endPadding = UNDEFINED_PADDING;
   4135 
   4136         int padding = -1;
   4137 
   4138         int viewFlagValues = 0;
   4139         int viewFlagMasks = 0;
   4140 
   4141         boolean setScrollContainer = false;
   4142 
   4143         int x = 0;
   4144         int y = 0;
   4145 
   4146         float tx = 0;
   4147         float ty = 0;
   4148         float tz = 0;
   4149         float elevation = 0;
   4150         float rotation = 0;
   4151         float rotationX = 0;
   4152         float rotationY = 0;
   4153         float sx = 1f;
   4154         float sy = 1f;
   4155         boolean transformSet = false;
   4156 
   4157         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
   4158         int overScrollMode = mOverScrollMode;
   4159         boolean initializeScrollbars = false;
   4160         boolean initializeScrollIndicators = false;
   4161 
   4162         boolean startPaddingDefined = false;
   4163         boolean endPaddingDefined = false;
   4164         boolean leftPaddingDefined = false;
   4165         boolean rightPaddingDefined = false;
   4166 
   4167         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   4168 
   4169         final int N = a.getIndexCount();
   4170         for (int i = 0; i < N; i++) {
   4171             int attr = a.getIndex(i);
   4172             switch (attr) {
   4173                 case com.android.internal.R.styleable.View_background:
   4174                     background = a.getDrawable(attr);
   4175                     break;
   4176                 case com.android.internal.R.styleable.View_padding:
   4177                     padding = a.getDimensionPixelSize(attr, -1);
   4178                     mUserPaddingLeftInitial = padding;
   4179                     mUserPaddingRightInitial = padding;
   4180                     leftPaddingDefined = true;
   4181                     rightPaddingDefined = true;
   4182                     break;
   4183                  case com.android.internal.R.styleable.View_paddingLeft:
   4184                     leftPadding = a.getDimensionPixelSize(attr, -1);
   4185                     mUserPaddingLeftInitial = leftPadding;
   4186                     leftPaddingDefined = true;
   4187                     break;
   4188                 case com.android.internal.R.styleable.View_paddingTop:
   4189                     topPadding = a.getDimensionPixelSize(attr, -1);
   4190                     break;
   4191                 case com.android.internal.R.styleable.View_paddingRight:
   4192                     rightPadding = a.getDimensionPixelSize(attr, -1);
   4193                     mUserPaddingRightInitial = rightPadding;
   4194                     rightPaddingDefined = true;
   4195                     break;
   4196                 case com.android.internal.R.styleable.View_paddingBottom:
   4197                     bottomPadding = a.getDimensionPixelSize(attr, -1);
   4198                     break;
   4199                 case com.android.internal.R.styleable.View_paddingStart:
   4200                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   4201                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
   4202                     break;
   4203                 case com.android.internal.R.styleable.View_paddingEnd:
   4204                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   4205                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
   4206                     break;
   4207                 case com.android.internal.R.styleable.View_scrollX:
   4208                     x = a.getDimensionPixelOffset(attr, 0);
   4209                     break;
   4210                 case com.android.internal.R.styleable.View_scrollY:
   4211                     y = a.getDimensionPixelOffset(attr, 0);
   4212                     break;
   4213                 case com.android.internal.R.styleable.View_alpha:
   4214                     setAlpha(a.getFloat(attr, 1f));
   4215                     break;
   4216                 case com.android.internal.R.styleable.View_transformPivotX:
   4217                     setPivotX(a.getDimensionPixelOffset(attr, 0));
   4218                     break;
   4219                 case com.android.internal.R.styleable.View_transformPivotY:
   4220                     setPivotY(a.getDimensionPixelOffset(attr, 0));
   4221                     break;
   4222                 case com.android.internal.R.styleable.View_translationX:
   4223                     tx = a.getDimensionPixelOffset(attr, 0);
   4224                     transformSet = true;
   4225                     break;
   4226                 case com.android.internal.R.styleable.View_translationY:
   4227                     ty = a.getDimensionPixelOffset(attr, 0);
   4228                     transformSet = true;
   4229                     break;
   4230                 case com.android.internal.R.styleable.View_translationZ:
   4231                     tz = a.getDimensionPixelOffset(attr, 0);
   4232                     transformSet = true;
   4233                     break;
   4234                 case com.android.internal.R.styleable.View_elevation:
   4235                     elevation = a.getDimensionPixelOffset(attr, 0);
   4236                     transformSet = true;
   4237                     break;
   4238                 case com.android.internal.R.styleable.View_rotation:
   4239                     rotation = a.getFloat(attr, 0);
   4240                     transformSet = true;
   4241                     break;
   4242                 case com.android.internal.R.styleable.View_rotationX:
   4243                     rotationX = a.getFloat(attr, 0);
   4244                     transformSet = true;
   4245                     break;
   4246                 case com.android.internal.R.styleable.View_rotationY:
   4247                     rotationY = a.getFloat(attr, 0);
   4248                     transformSet = true;
   4249                     break;
   4250                 case com.android.internal.R.styleable.View_scaleX:
   4251                     sx = a.getFloat(attr, 1f);
   4252                     transformSet = true;
   4253                     break;
   4254                 case com.android.internal.R.styleable.View_scaleY:
   4255                     sy = a.getFloat(attr, 1f);
   4256                     transformSet = true;
   4257                     break;
   4258                 case com.android.internal.R.styleable.View_id:
   4259                     mID = a.getResourceId(attr, NO_ID);
   4260                     break;
   4261                 case com.android.internal.R.styleable.View_tag:
   4262                     mTag = a.getText(attr);
   4263                     break;
   4264                 case com.android.internal.R.styleable.View_fitsSystemWindows:
   4265                     if (a.getBoolean(attr, false)) {
   4266                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
   4267                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
   4268                     }
   4269                     break;
   4270                 case com.android.internal.R.styleable.View_focusable:
   4271                     if (a.getBoolean(attr, false)) {
   4272                         viewFlagValues |= FOCUSABLE;
   4273                         viewFlagMasks |= FOCUSABLE_MASK;
   4274                     }
   4275                     break;
   4276                 case com.android.internal.R.styleable.View_focusableInTouchMode:
   4277                     if (a.getBoolean(attr, false)) {
   4278                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
   4279                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
   4280                     }
   4281                     break;
   4282                 case com.android.internal.R.styleable.View_clickable:
   4283                     if (a.getBoolean(attr, false)) {
   4284                         viewFlagValues |= CLICKABLE;
   4285                         viewFlagMasks |= CLICKABLE;
   4286                     }
   4287                     break;
   4288                 case com.android.internal.R.styleable.View_longClickable:
   4289                     if (a.getBoolean(attr, false)) {
   4290                         viewFlagValues |= LONG_CLICKABLE;
   4291                         viewFlagMasks |= LONG_CLICKABLE;
   4292                     }
   4293                     break;
   4294                 case com.android.internal.R.styleable.View_contextClickable:
   4295                     if (a.getBoolean(attr, false)) {
   4296                         viewFlagValues |= CONTEXT_CLICKABLE;
   4297                         viewFlagMasks |= CONTEXT_CLICKABLE;
   4298                     }
   4299                     break;
   4300                 case com.android.internal.R.styleable.View_saveEnabled:
   4301                     if (!a.getBoolean(attr, true)) {
   4302                         viewFlagValues |= SAVE_DISABLED;
   4303                         viewFlagMasks |= SAVE_DISABLED_MASK;
   4304                     }
   4305                     break;
   4306                 case com.android.internal.R.styleable.View_duplicateParentState:
   4307                     if (a.getBoolean(attr, false)) {
   4308                         viewFlagValues |= DUPLICATE_PARENT_STATE;
   4309                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
   4310                     }
   4311                     break;
   4312                 case com.android.internal.R.styleable.View_visibility:
   4313                     final int visibility = a.getInt(attr, 0);
   4314                     if (visibility != 0) {
   4315                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
   4316                         viewFlagMasks |= VISIBILITY_MASK;
   4317                     }
   4318                     break;
   4319                 case com.android.internal.R.styleable.View_layoutDirection:
   4320                     // Clear any layout direction flags (included resolved bits) already set
   4321                     mPrivateFlags2 &=
   4322                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
   4323                     // Set the layout direction flags depending on the value of the attribute
   4324                     final int layoutDirection = a.getInt(attr, -1);
   4325                     final int value = (layoutDirection != -1) ?
   4326                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
   4327                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
   4328                     break;
   4329                 case com.android.internal.R.styleable.View_drawingCacheQuality:
   4330                     final int cacheQuality = a.getInt(attr, 0);
   4331                     if (cacheQuality != 0) {
   4332                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
   4333                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
   4334                     }
   4335                     break;
   4336                 case com.android.internal.R.styleable.View_contentDescription:
   4337                     setContentDescription(a.getString(attr));
   4338                     break;
   4339                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
   4340                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
   4341                     break;
   4342                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
   4343                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
   4344                     break;
   4345                 case com.android.internal.R.styleable.View_labelFor:
   4346                     setLabelFor(a.getResourceId(attr, NO_ID));
   4347                     break;
   4348                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
   4349                     if (!a.getBoolean(attr, true)) {
   4350                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
   4351                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
   4352                     }
   4353                     break;
   4354                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
   4355                     if (!a.getBoolean(attr, true)) {
   4356                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
   4357                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
   4358                     }
   4359                     break;
   4360                 case R.styleable.View_scrollbars:
   4361                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
   4362                     if (scrollbars != SCROLLBARS_NONE) {
   4363                         viewFlagValues |= scrollbars;
   4364                         viewFlagMasks |= SCROLLBARS_MASK;
   4365                         initializeScrollbars = true;
   4366                     }
   4367                     break;
   4368                 //noinspection deprecation
   4369                 case R.styleable.View_fadingEdge:
   4370                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
   4371                         // Ignore the attribute starting with ICS
   4372                         break;
   4373                     }
   4374                     // With builds < ICS, fall through and apply fading edges
   4375                 case R.styleable.View_requiresFadingEdge:
   4376                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
   4377                     if (fadingEdge != FADING_EDGE_NONE) {
   4378                         viewFlagValues |= fadingEdge;
   4379                         viewFlagMasks |= FADING_EDGE_MASK;
   4380                         initializeFadingEdgeInternal(a);
   4381                     }
   4382                     break;
   4383                 case R.styleable.View_scrollbarStyle:
   4384                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
   4385                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   4386                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
   4387                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
   4388                     }
   4389                     break;
   4390                 case R.styleable.View_isScrollContainer:
   4391                     setScrollContainer = true;
   4392                     if (a.getBoolean(attr, false)) {
   4393                         setScrollContainer(true);
   4394                     }
   4395                     break;
   4396                 case com.android.internal.R.styleable.View_keepScreenOn:
   4397                     if (a.getBoolean(attr, false)) {
   4398                         viewFlagValues |= KEEP_SCREEN_ON;
   4399                         viewFlagMasks |= KEEP_SCREEN_ON;
   4400                     }
   4401                     break;
   4402                 case R.styleable.View_filterTouchesWhenObscured:
   4403                     if (a.getBoolean(attr, false)) {
   4404                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
   4405                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
   4406                     }
   4407                     break;
   4408                 case R.styleable.View_nextFocusLeft:
   4409                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
   4410                     break;
   4411                 case R.styleable.View_nextFocusRight:
   4412                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
   4413                     break;
   4414                 case R.styleable.View_nextFocusUp:
   4415                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
   4416                     break;
   4417                 case R.styleable.View_nextFocusDown:
   4418                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
   4419                     break;
   4420                 case R.styleable.View_nextFocusForward:
   4421                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
   4422                     break;
   4423                 case R.styleable.View_minWidth:
   4424                     mMinWidth = a.getDimensionPixelSize(attr, 0);
   4425                     break;
   4426                 case R.styleable.View_minHeight:
   4427                     mMinHeight = a.getDimensionPixelSize(attr, 0);
   4428                     break;
   4429                 case R.styleable.View_onClick:
   4430                     if (context.isRestricted()) {
   4431                         throw new IllegalStateException("The android:onClick attribute cannot "
   4432                                 + "be used within a restricted context");
   4433                     }
   4434 
   4435                     final String handlerName = a.getString(attr);
   4436                     if (handlerName != null) {
   4437                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
   4438                     }
   4439                     break;
   4440                 case R.styleable.View_overScrollMode:
   4441                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
   4442                     break;
   4443                 case R.styleable.View_verticalScrollbarPosition:
   4444                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
   4445                     break;
   4446                 case R.styleable.View_layerType:
   4447                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
   4448                     break;
   4449                 case R.styleable.View_textDirection:
   4450                     // Clear any text direction flag already set
   4451                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   4452                     // Set the text direction flags depending on the value of the attribute
   4453                     final int textDirection = a.getInt(attr, -1);
   4454                     if (textDirection != -1) {
   4455                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
   4456                     }
   4457                     break;
   4458                 case R.styleable.View_textAlignment:
   4459                     // Clear any text alignment flag already set
   4460                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   4461                     // Set the text alignment flag depending on the value of the attribute
   4462                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
   4463                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
   4464                     break;
   4465                 case R.styleable.View_importantForAccessibility:
   4466                     setImportantForAccessibility(a.getInt(attr,
   4467                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
   4468                     break;
   4469                 case R.styleable.View_accessibilityLiveRegion:
   4470                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
   4471                     break;
   4472                 case R.styleable.View_transitionName:
   4473                     setTransitionName(a.getString(attr));
   4474                     break;
   4475                 case R.styleable.View_nestedScrollingEnabled:
   4476                     setNestedScrollingEnabled(a.getBoolean(attr, false));
   4477                     break;
   4478                 case R.styleable.View_stateListAnimator:
   4479                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
   4480                             a.getResourceId(attr, 0)));
   4481                     break;
   4482                 case R.styleable.View_backgroundTint:
   4483                     // This will get applied later during setBackground().
   4484                     if (mBackgroundTint == null) {
   4485                         mBackgroundTint = new TintInfo();
   4486                     }
   4487                     mBackgroundTint.mTintList = a.getColorStateList(
   4488                             R.styleable.View_backgroundTint);
   4489                     mBackgroundTint.mHasTintList = true;
   4490                     break;
   4491                 case R.styleable.View_backgroundTintMode:
   4492                     // This will get applied later during setBackground().
   4493                     if (mBackgroundTint == null) {
   4494                         mBackgroundTint = new TintInfo();
   4495                     }
   4496                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
   4497                             R.styleable.View_backgroundTintMode, -1), null);
   4498                     mBackgroundTint.mHasTintMode = true;
   4499                     break;
   4500                 case R.styleable.View_outlineProvider:
   4501                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
   4502                             PROVIDER_BACKGROUND));
   4503                     break;
   4504                 case R.styleable.View_foreground:
   4505                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4506                         setForeground(a.getDrawable(attr));
   4507                     }
   4508                     break;
   4509                 case R.styleable.View_foregroundGravity:
   4510                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4511                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
   4512                     }
   4513                     break;
   4514                 case R.styleable.View_foregroundTintMode:
   4515                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4516                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
   4517                     }
   4518                     break;
   4519                 case R.styleable.View_foregroundTint:
   4520                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4521                         setForegroundTintList(a.getColorStateList(attr));
   4522                     }
   4523                     break;
   4524                 case R.styleable.View_foregroundInsidePadding:
   4525                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4526                         if (mForegroundInfo == null) {
   4527                             mForegroundInfo = new ForegroundInfo();
   4528                         }
   4529                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
   4530                                 mForegroundInfo.mInsidePadding);
   4531                     }
   4532                     break;
   4533                 case R.styleable.View_scrollIndicators:
   4534                     final int scrollIndicators =
   4535                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
   4536                                     & SCROLL_INDICATORS_PFLAG3_MASK;
   4537                     if (scrollIndicators != 0) {
   4538                         mPrivateFlags3 |= scrollIndicators;
   4539                         initializeScrollIndicators = true;
   4540                     }
   4541                     break;
   4542                 case R.styleable.View_pointerIcon:
   4543                     final int resourceId = a.getResourceId(attr, 0);
   4544                     if (resourceId != 0) {
   4545                         setPointerIcon(PointerIcon.load(
   4546                                 context.getResources(), resourceId));
   4547                     } else {
   4548                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
   4549                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
   4550                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
   4551                         }
   4552                     }
   4553                     break;
   4554                 case R.styleable.View_forceHasOverlappingRendering:
   4555                     if (a.peekValue(attr) != null) {
   4556                         forceHasOverlappingRendering(a.getBoolean(attr, true));
   4557                     }
   4558                     break;
   4559 
   4560             }
   4561         }
   4562 
   4563         setOverScrollMode(overScrollMode);
   4564 
   4565         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
   4566         // the resolved layout direction). Those cached values will be used later during padding
   4567         // resolution.
   4568         mUserPaddingStart = startPadding;
   4569         mUserPaddingEnd = endPadding;
   4570 
   4571         if (background != null) {
   4572             setBackground(background);
   4573         }
   4574 
   4575         // setBackground above will record that padding is currently provided by the background.
   4576         // If we have padding specified via xml, record that here instead and use it.
   4577         mLeftPaddingDefined = leftPaddingDefined;
   4578         mRightPaddingDefined = rightPaddingDefined;
   4579 
   4580         if (padding >= 0) {
   4581             leftPadding = padding;
   4582             topPadding = padding;
   4583             rightPadding = padding;
   4584             bottomPadding = padding;
   4585             mUserPaddingLeftInitial = padding;
   4586             mUserPaddingRightInitial = padding;
   4587         }
   4588 
   4589         if (isRtlCompatibilityMode()) {
   4590             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
   4591             // left / right padding are used if defined (meaning here nothing to do). If they are not
   4592             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
   4593             // start / end and resolve them as left / right (layout direction is not taken into account).
   4594             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   4595             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   4596             // defined.
   4597             if (!mLeftPaddingDefined && startPaddingDefined) {
   4598                 leftPadding = startPadding;
   4599             }
   4600             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
   4601             if (!mRightPaddingDefined && endPaddingDefined) {
   4602                 rightPadding = endPadding;
   4603             }
   4604             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
   4605         } else {
   4606             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
   4607             // values defined. Otherwise, left /right values are used.
   4608             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   4609             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   4610             // defined.
   4611             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
   4612 
   4613             if (mLeftPaddingDefined && !hasRelativePadding) {
   4614                 mUserPaddingLeftInitial = leftPadding;
   4615             }
   4616             if (mRightPaddingDefined && !hasRelativePadding) {
   4617                 mUserPaddingRightInitial = rightPadding;
   4618             }
   4619         }
   4620 
   4621         internalSetPadding(
   4622                 mUserPaddingLeftInitial,
   4623                 topPadding >= 0 ? topPadding : mPaddingTop,
   4624                 mUserPaddingRightInitial,
   4625                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
   4626 
   4627         if (viewFlagMasks != 0) {
   4628             setFlags(viewFlagValues, viewFlagMasks);
   4629         }
   4630 
   4631         if (initializeScrollbars) {
   4632             initializeScrollbarsInternal(a);
   4633         }
   4634 
   4635         if (initializeScrollIndicators) {
   4636             initializeScrollIndicatorsInternal();
   4637         }
   4638 
   4639         a.recycle();
   4640 
   4641         // Needs to be called after mViewFlags is set
   4642         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   4643             recomputePadding();
   4644         }
   4645 
   4646         if (x != 0 || y != 0) {
   4647             scrollTo(x, y);
   4648         }
   4649 
   4650         if (transformSet) {
   4651             setTranslationX(tx);
   4652             setTranslationY(ty);
   4653             setTranslationZ(tz);
   4654             setElevation(elevation);
   4655             setRotation(rotation);
   4656             setRotationX(rotationX);
   4657             setRotationY(rotationY);
   4658             setScaleX(sx);
   4659             setScaleY(sy);
   4660         }
   4661 
   4662         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
   4663             setScrollContainer(true);
   4664         }
   4665 
   4666         computeOpaqueFlags();
   4667     }
   4668 
   4669     /**
   4670      * An implementation of OnClickListener that attempts to lazily load a
   4671      * named click handling method from a parent or ancestor context.
   4672      */
   4673     private static class DeclaredOnClickListener implements OnClickListener {
   4674         private final View mHostView;
   4675         private final String mMethodName;
   4676 
   4677         private Method mResolvedMethod;
   4678         private Context mResolvedContext;
   4679 
   4680         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
   4681             mHostView = hostView;
   4682             mMethodName = methodName;
   4683         }
   4684 
   4685         @Override
   4686         public void onClick(@NonNull View v) {
   4687             if (mResolvedMethod == null) {
   4688                 resolveMethod(mHostView.getContext(), mMethodName);
   4689             }
   4690 
   4691             try {
   4692                 mResolvedMethod.invoke(mResolvedContext, v);
   4693             } catch (IllegalAccessException e) {
   4694                 throw new IllegalStateException(
   4695                         "Could not execute non-public method for android:onClick", e);
   4696             } catch (InvocationTargetException e) {
   4697                 throw new IllegalStateException(
   4698                         "Could not execute method for android:onClick", e);
   4699             }
   4700         }
   4701 
   4702         @NonNull
   4703         private void resolveMethod(@Nullable Context context, @NonNull String name) {
   4704             while (context != null) {
   4705                 try {
   4706                     if (!context.isRestricted()) {
   4707                         final Method method = context.getClass().getMethod(mMethodName, View.class);
   4708                         if (method != null) {
   4709                             mResolvedMethod = method;
   4710                             mResolvedContext = context;
   4711                             return;
   4712                         }
   4713                     }
   4714                 } catch (NoSuchMethodException e) {
   4715                     // Failed to find method, keep searching up the hierarchy.
   4716                 }
   4717 
   4718                 if (context instanceof ContextWrapper) {
   4719                     context = ((ContextWrapper) context).getBaseContext();
   4720                 } else {
   4721                     // Can't search up the hierarchy, null out and fail.
   4722                     context = null;
   4723                 }
   4724             }
   4725 
   4726             final int id = mHostView.getId();
   4727             final String idText = id == NO_ID ? "" : " with id '"
   4728                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
   4729             throw new IllegalStateException("Could not find method " + mMethodName
   4730                     + "(View) in a parent or ancestor Context for android:onClick "
   4731                     + "attribute defined on view " + mHostView.getClass() + idText);
   4732         }
   4733     }
   4734 
   4735     /**
   4736      * Non-public constructor for use in testing
   4737      */
   4738     View() {
   4739         mResources = null;
   4740         mRenderNode = RenderNode.create(getClass().getName(), this);
   4741     }
   4742 
   4743     private static SparseArray<String> getAttributeMap() {
   4744         if (mAttributeMap == null) {
   4745             mAttributeMap = new SparseArray<>();
   4746         }
   4747         return mAttributeMap;
   4748     }
   4749 
   4750     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
   4751         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
   4752         final int indexCount = t.getIndexCount();
   4753         final String[] attributes = new String[(attrsCount + indexCount) * 2];
   4754 
   4755         int i = 0;
   4756 
   4757         // Store raw XML attributes.
   4758         for (int j = 0; j < attrsCount; ++j) {
   4759             attributes[i] = attrs.getAttributeName(j);
   4760             attributes[i + 1] = attrs.getAttributeValue(j);
   4761             i += 2;
   4762         }
   4763 
   4764         // Store resolved styleable attributes.
   4765         final Resources res = t.getResources();
   4766         final SparseArray<String> attributeMap = getAttributeMap();
   4767         for (int j = 0; j < indexCount; ++j) {
   4768             final int index = t.getIndex(j);
   4769             if (!t.hasValueOrEmpty(index)) {
   4770                 // Value is undefined. Skip it.
   4771                 continue;
   4772             }
   4773 
   4774             final int resourceId = t.getResourceId(index, 0);
   4775             if (resourceId == 0) {
   4776                 // Value is not a reference. Skip it.
   4777                 continue;
   4778             }
   4779 
   4780             String resourceName = attributeMap.get(resourceId);
   4781             if (resourceName == null) {
   4782                 try {
   4783                     resourceName = res.getResourceName(resourceId);
   4784                 } catch (Resources.NotFoundException e) {
   4785                     resourceName = "0x" + Integer.toHexString(resourceId);
   4786                 }
   4787                 attributeMap.put(resourceId, resourceName);
   4788             }
   4789 
   4790             attributes[i] = resourceName;
   4791             attributes[i + 1] = t.getString(index);
   4792             i += 2;
   4793         }
   4794 
   4795         // Trim to fit contents.
   4796         final String[] trimmed = new String[i];
   4797         System.arraycopy(attributes, 0, trimmed, 0, i);
   4798         mAttributes = trimmed;
   4799     }
   4800 
   4801     public String toString() {
   4802         StringBuilder out = new StringBuilder(128);
   4803         out.append(getClass().getName());
   4804         out.append('{');
   4805         out.append(Integer.toHexString(System.identityHashCode(this)));
   4806         out.append(' ');
   4807         switch (mViewFlags&VISIBILITY_MASK) {
   4808             case VISIBLE: out.append('V'); break;
   4809             case INVISIBLE: out.append('I'); break;
   4810             case GONE: out.append('G'); break;
   4811             default: out.append('.'); break;
   4812         }
   4813         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
   4814         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
   4815         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
   4816         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
   4817         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
   4818         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
   4819         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
   4820         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
   4821         out.append(' ');
   4822         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
   4823         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
   4824         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
   4825         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
   4826             out.append('p');
   4827         } else {
   4828             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
   4829         }
   4830         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
   4831         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
   4832         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
   4833         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
   4834         out.append(' ');
   4835         out.append(mLeft);
   4836         out.append(',');
   4837         out.append(mTop);
   4838         out.append('-');
   4839         out.append(mRight);
   4840         out.append(',');
   4841         out.append(mBottom);
   4842         final int id = getId();
   4843         if (id != NO_ID) {
   4844             out.append(" #");
   4845             out.append(Integer.toHexString(id));
   4846             final Resources r = mResources;
   4847             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
   4848                 try {
   4849                     String pkgname;
   4850                     switch (id&0xff000000) {
   4851                         case 0x7f000000:
   4852                             pkgname="app";
   4853                             break;
   4854                         case 0x01000000:
   4855                             pkgname="android";
   4856                             break;
   4857                         default:
   4858                             pkgname = r.getResourcePackageName(id);
   4859                             break;
   4860                     }
   4861                     String typename = r.getResourceTypeName(id);
   4862                     String entryname = r.getResourceEntryName(id);
   4863                     out.append(" ");
   4864                     out.append(pkgname);
   4865                     out.append(":");
   4866                     out.append(typename);
   4867                     out.append("/");
   4868                     out.append(entryname);
   4869                 } catch (Resources.NotFoundException e) {
   4870                 }
   4871             }
   4872         }
   4873         out.append("}");
   4874         return out.toString();
   4875     }
   4876 
   4877     /**
   4878      * <p>
   4879      * Initializes the fading edges from a given set of styled attributes. This
   4880      * method should be called by subclasses that need fading edges and when an
   4881      * instance of these subclasses is created programmatically rather than
   4882      * being inflated from XML. This method is automatically called when the XML
   4883      * is inflated.
   4884      * </p>
   4885      *
   4886      * @param a the styled attributes set to initialize the fading edges from
   4887      *
   4888      * @removed
   4889      */
   4890     protected void initializeFadingEdge(TypedArray a) {
   4891         // This method probably shouldn't have been included in the SDK to begin with.
   4892         // It relies on 'a' having been initialized using an attribute filter array that is
   4893         // not publicly available to the SDK. The old method has been renamed
   4894         // to initializeFadingEdgeInternal and hidden for framework use only;
   4895         // this one initializes using defaults to make it safe to call for apps.
   4896 
   4897         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   4898 
   4899         initializeFadingEdgeInternal(arr);
   4900 
   4901         arr.recycle();
   4902     }
   4903 
   4904     /**
   4905      * <p>
   4906      * Initializes the fading edges from a given set of styled attributes. This
   4907      * method should be called by subclasses that need fading edges and when an
   4908      * instance of these subclasses is created programmatically rather than
   4909      * being inflated from XML. This method is automatically called when the XML
   4910      * is inflated.
   4911      * </p>
   4912      *
   4913      * @param a the styled attributes set to initialize the fading edges from
   4914      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
   4915      */
   4916     protected void initializeFadingEdgeInternal(TypedArray a) {
   4917         initScrollCache();
   4918 
   4919         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
   4920                 R.styleable.View_fadingEdgeLength,
   4921                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
   4922     }
   4923 
   4924     /**
   4925      * Returns the size of the vertical faded edges used to indicate that more
   4926      * content in this view is visible.
   4927      *
   4928      * @return The size in pixels of the vertical faded edge or 0 if vertical
   4929      *         faded edges are not enabled for this view.
   4930      * @attr ref android.R.styleable#View_fadingEdgeLength
   4931      */
   4932     public int getVerticalFadingEdgeLength() {
   4933         if (isVerticalFadingEdgeEnabled()) {
   4934             ScrollabilityCache cache = mScrollCache;
   4935             if (cache != null) {
   4936                 return cache.fadingEdgeLength;
   4937             }
   4938         }
   4939         return 0;
   4940     }
   4941 
   4942     /**
   4943      * Set the size of the faded edge used to indicate that more content in this
   4944      * view is available.  Will not change whether the fading edge is enabled; use
   4945      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
   4946      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
   4947      * for the vertical or horizontal fading edges.
   4948      *
   4949      * @param length The size in pixels of the faded edge used to indicate that more
   4950      *        content in this view is visible.
   4951      */
   4952     public void setFadingEdgeLength(int length) {
   4953         initScrollCache();
   4954         mScrollCache.fadingEdgeLength = length;
   4955     }
   4956 
   4957     /**
   4958      * Returns the size of the horizontal faded edges used to indicate that more
   4959      * content in this view is visible.
   4960      *
   4961      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
   4962      *         faded edges are not enabled for this view.
   4963      * @attr ref android.R.styleable#View_fadingEdgeLength
   4964      */
   4965     public int getHorizontalFadingEdgeLength() {
   4966         if (isHorizontalFadingEdgeEnabled()) {
   4967             ScrollabilityCache cache = mScrollCache;
   4968             if (cache != null) {
   4969                 return cache.fadingEdgeLength;
   4970             }
   4971         }
   4972         return 0;
   4973     }
   4974 
   4975     /**
   4976      * Returns the width of the vertical scrollbar.
   4977      *
   4978      * @return The width in pixels of the vertical scrollbar or 0 if there
   4979      *         is no vertical scrollbar.
   4980      */
   4981     public int getVerticalScrollbarWidth() {
   4982         ScrollabilityCache cache = mScrollCache;
   4983         if (cache != null) {
   4984             ScrollBarDrawable scrollBar = cache.scrollBar;
   4985             if (scrollBar != null) {
   4986                 int size = scrollBar.getSize(true);
   4987                 if (size <= 0) {
   4988                     size = cache.scrollBarSize;
   4989                 }
   4990                 return size;
   4991             }
   4992             return 0;
   4993         }
   4994         return 0;
   4995     }
   4996 
   4997     /**
   4998      * Returns the height of the horizontal scrollbar.
   4999      *
   5000      * @return The height in pixels of the horizontal scrollbar or 0 if
   5001      *         there is no horizontal scrollbar.
   5002      */
   5003     protected int getHorizontalScrollbarHeight() {
   5004         ScrollabilityCache cache = mScrollCache;
   5005         if (cache != null) {
   5006             ScrollBarDrawable scrollBar = cache.scrollBar;
   5007             if (scrollBar != null) {
   5008                 int size = scrollBar.getSize(false);
   5009                 if (size <= 0) {
   5010                     size = cache.scrollBarSize;
   5011                 }
   5012                 return size;
   5013             }
   5014             return 0;
   5015         }
   5016         return 0;
   5017     }
   5018 
   5019     /**
   5020      * <p>
   5021      * Initializes the scrollbars from a given set of styled attributes. This
   5022      * method should be called by subclasses that need scrollbars and when an
   5023      * instance of these subclasses is created programmatically rather than
   5024      * being inflated from XML. This method is automatically called when the XML
   5025      * is inflated.
   5026      * </p>
   5027      *
   5028      * @param a the styled attributes set to initialize the scrollbars from
   5029      *
   5030      * @removed
   5031      */
   5032     protected void initializeScrollbars(TypedArray a) {
   5033         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
   5034         // using the View filter array which is not available to the SDK. As such, internal
   5035         // framework usage now uses initializeScrollbarsInternal and we grab a default
   5036         // TypedArray with the right filter instead here.
   5037         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   5038 
   5039         initializeScrollbarsInternal(arr);
   5040 
   5041         // We ignored the method parameter. Recycle the one we actually did use.
   5042         arr.recycle();
   5043     }
   5044 
   5045     /**
   5046      * <p>
   5047      * Initializes the scrollbars from a given set of styled attributes. This
   5048      * method should be called by subclasses that need scrollbars and when an
   5049      * instance of these subclasses is created programmatically rather than
   5050      * being inflated from XML. This method is automatically called when the XML
   5051      * is inflated.
   5052      * </p>
   5053      *
   5054      * @param a the styled attributes set to initialize the scrollbars from
   5055      * @hide
   5056      */
   5057     protected void initializeScrollbarsInternal(TypedArray a) {
   5058         initScrollCache();
   5059 
   5060         final ScrollabilityCache scrollabilityCache = mScrollCache;
   5061 
   5062         if (scrollabilityCache.scrollBar == null) {
   5063             scrollabilityCache.scrollBar = new ScrollBarDrawable();
   5064             scrollabilityCache.scrollBar.setState(getDrawableState());
   5065             scrollabilityCache.scrollBar.setCallback(this);
   5066         }
   5067 
   5068         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
   5069 
   5070         if (!fadeScrollbars) {
   5071             scrollabilityCache.state = ScrollabilityCache.ON;
   5072         }
   5073         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   5074 
   5075 
   5076         scrollabilityCache.scrollBarFadeDuration = a.getInt(
   5077                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
   5078                         .getScrollBarFadeDuration());
   5079         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
   5080                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
   5081                 ViewConfiguration.getScrollDefaultDelay());
   5082 
   5083 
   5084         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
   5085                 com.android.internal.R.styleable.View_scrollbarSize,
   5086                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
   5087 
   5088         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
   5089         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
   5090 
   5091         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
   5092         if (thumb != null) {
   5093             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
   5094         }
   5095 
   5096         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
   5097                 false);
   5098         if (alwaysDraw) {
   5099             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
   5100         }
   5101 
   5102         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
   5103         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
   5104 
   5105         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
   5106         if (thumb != null) {
   5107             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
   5108         }
   5109 
   5110         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
   5111                 false);
   5112         if (alwaysDraw) {
   5113             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
   5114         }
   5115 
   5116         // Apply layout direction to the new Drawables if needed
   5117         final int layoutDirection = getLayoutDirection();
   5118         if (track != null) {
   5119             track.setLayoutDirection(layoutDirection);
   5120         }
   5121         if (thumb != null) {
   5122             thumb.setLayoutDirection(layoutDirection);
   5123         }
   5124 
   5125         // Re-apply user/background padding so that scrollbar(s) get added
   5126         resolvePadding();
   5127     }
   5128 
   5129     private void initializeScrollIndicatorsInternal() {
   5130         // Some day maybe we'll break this into top/left/start/etc. and let the
   5131         // client control it. Until then, you can have any scroll indicator you
   5132         // want as long as it's a 1dp foreground-colored rectangle.
   5133         if (mScrollIndicatorDrawable == null) {
   5134             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
   5135         }
   5136     }
   5137 
   5138     /**
   5139      * <p>
   5140      * Initalizes the scrollability cache if necessary.
   5141      * </p>
   5142      */
   5143     private void initScrollCache() {
   5144         if (mScrollCache == null) {
   5145             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
   5146         }
   5147     }
   5148 
   5149     private ScrollabilityCache getScrollCache() {
   5150         initScrollCache();
   5151         return mScrollCache;
   5152     }
   5153 
   5154     /**
   5155      * Set the position of the vertical scroll bar. Should be one of
   5156      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
   5157      * {@link #SCROLLBAR_POSITION_RIGHT}.
   5158      *
   5159      * @param position Where the vertical scroll bar should be positioned.
   5160      */
   5161     public void setVerticalScrollbarPosition(int position) {
   5162         if (mVerticalScrollbarPosition != position) {
   5163             mVerticalScrollbarPosition = position;
   5164             computeOpaqueFlags();
   5165             resolvePadding();
   5166         }
   5167     }
   5168 
   5169     /**
   5170      * @return The position where the vertical scroll bar will show, if applicable.
   5171      * @see #setVerticalScrollbarPosition(int)
   5172      */
   5173     public int getVerticalScrollbarPosition() {
   5174         return mVerticalScrollbarPosition;
   5175     }
   5176 
   5177     boolean isOnScrollbar(float x, float y) {
   5178         if (mScrollCache == null) {
   5179             return false;
   5180         }
   5181         x += getScrollX();
   5182         y += getScrollY();
   5183         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
   5184             final Rect bounds = mScrollCache.mScrollBarBounds;
   5185             getVerticalScrollBarBounds(bounds);
   5186             if (bounds.contains((int)x, (int)y)) {
   5187                 return true;
   5188             }
   5189         }
   5190         if (isHorizontalScrollBarEnabled()) {
   5191             final Rect bounds = mScrollCache.mScrollBarBounds;
   5192             getHorizontalScrollBarBounds(bounds);
   5193             if (bounds.contains((int)x, (int)y)) {
   5194                 return true;
   5195             }
   5196         }
   5197         return false;
   5198     }
   5199 
   5200     boolean isOnScrollbarThumb(float x, float y) {
   5201         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
   5202     }
   5203 
   5204     private boolean isOnVerticalScrollbarThumb(float x, float y) {
   5205         if (mScrollCache == null) {
   5206             return false;
   5207         }
   5208         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
   5209             x += getScrollX();
   5210             y += getScrollY();
   5211             final Rect bounds = mScrollCache.mScrollBarBounds;
   5212             getVerticalScrollBarBounds(bounds);
   5213             final int range = computeVerticalScrollRange();
   5214             final int offset = computeVerticalScrollOffset();
   5215             final int extent = computeVerticalScrollExtent();
   5216             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
   5217                     extent, range);
   5218             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
   5219                     extent, range, offset);
   5220             final int thumbTop = bounds.top + thumbOffset;
   5221             if (x >= bounds.left && x <= bounds.right && y >= thumbTop
   5222                     && y <= thumbTop + thumbLength) {
   5223                 return true;
   5224             }
   5225         }
   5226         return false;
   5227     }
   5228 
   5229     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
   5230         if (mScrollCache == null) {
   5231             return false;
   5232         }
   5233         if (isHorizontalScrollBarEnabled()) {
   5234             x += getScrollX();
   5235             y += getScrollY();
   5236             final Rect bounds = mScrollCache.mScrollBarBounds;
   5237             getHorizontalScrollBarBounds(bounds);
   5238             final int range = computeHorizontalScrollRange();
   5239             final int offset = computeHorizontalScrollOffset();
   5240             final int extent = computeHorizontalScrollExtent();
   5241             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
   5242                     extent, range);
   5243             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
   5244                     extent, range, offset);
   5245             final int thumbLeft = bounds.left + thumbOffset;
   5246             if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
   5247                     && y <= bounds.bottom) {
   5248                 return true;
   5249             }
   5250         }
   5251         return false;
   5252     }
   5253 
   5254     boolean isDraggingScrollBar() {
   5255         return mScrollCache != null
   5256                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
   5257     }
   5258 
   5259     /**
   5260      * Sets the state of all scroll indicators.
   5261      * <p>
   5262      * See {@link #setScrollIndicators(int, int)} for usage information.
   5263      *
   5264      * @param indicators a bitmask of indicators that should be enabled, or
   5265      *                   {@code 0} to disable all indicators
   5266      * @see #setScrollIndicators(int, int)
   5267      * @see #getScrollIndicators()
   5268      * @attr ref android.R.styleable#View_scrollIndicators
   5269      */
   5270     public void setScrollIndicators(@ScrollIndicators int indicators) {
   5271         setScrollIndicators(indicators,
   5272                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
   5273     }
   5274 
   5275     /**
   5276      * Sets the state of the scroll indicators specified by the mask. To change
   5277      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
   5278      * <p>
   5279      * When a scroll indicator is enabled, it will be displayed if the view
   5280      * can scroll in the direction of the indicator.
   5281      * <p>
   5282      * Multiple indicator types may be enabled or disabled by passing the
   5283      * logical OR of the desired types. If multiple types are specified, they
   5284      * will all be set to the same enabled state.
   5285      * <p>
   5286      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
   5287      *
   5288      * @param indicators the indicator direction, or the logical OR of multiple
   5289      *             indicator directions. One or more of:
   5290      *             <ul>
   5291      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
   5292      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
   5293      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
   5294      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
   5295      *               <li>{@link #SCROLL_INDICATOR_START}</li>
   5296      *               <li>{@link #SCROLL_INDICATOR_END}</li>
   5297      *             </ul>
   5298      * @see #setScrollIndicators(int)
   5299      * @see #getScrollIndicators()
   5300      * @attr ref android.R.styleable#View_scrollIndicators
   5301      */
   5302     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
   5303         // Shift and sanitize mask.
   5304         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   5305         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
   5306 
   5307         // Shift and mask indicators.
   5308         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   5309         indicators &= mask;
   5310 
   5311         // Merge with non-masked flags.
   5312         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
   5313 
   5314         if (mPrivateFlags3 != updatedFlags) {
   5315             mPrivateFlags3 = updatedFlags;
   5316 
   5317             if (indicators != 0) {
   5318                 initializeScrollIndicatorsInternal();
   5319             }
   5320             invalidate();
   5321         }
   5322     }
   5323 
   5324     /**
   5325      * Returns a bitmask representing the enabled scroll indicators.
   5326      * <p>
   5327      * For example, if the top and left scroll indicators are enabled and all
   5328      * other indicators are disabled, the return value will be
   5329      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
   5330      * <p>
   5331      * To check whether the bottom scroll indicator is enabled, use the value
   5332      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
   5333      *
   5334      * @return a bitmask representing the enabled scroll indicators
   5335      */
   5336     @ScrollIndicators
   5337     public int getScrollIndicators() {
   5338         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
   5339                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   5340     }
   5341 
   5342     ListenerInfo getListenerInfo() {
   5343         if (mListenerInfo != null) {
   5344             return mListenerInfo;
   5345         }
   5346         mListenerInfo = new ListenerInfo();
   5347         return mListenerInfo;
   5348     }
   5349 
   5350     /**
   5351      * Register a callback to be invoked when the scroll X or Y positions of
   5352      * this view change.
   5353      * <p>
   5354      * <b>Note:</b> Some views handle scrolling independently from View and may
   5355      * have their own separate listeners for scroll-type events. For example,
   5356      * {@link android.widget.ListView ListView} allows clients to register an
   5357      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   5358      * to listen for changes in list scroll position.
   5359      *
   5360      * @param l The listener to notify when the scroll X or Y position changes.
   5361      * @see android.view.View#getScrollX()
   5362      * @see android.view.View#getScrollY()
   5363      */
   5364     public void setOnScrollChangeListener(OnScrollChangeListener l) {
   5365         getListenerInfo().mOnScrollChangeListener = l;
   5366     }
   5367 
   5368     /**
   5369      * Register a callback to be invoked when focus of this view changed.
   5370      *
   5371      * @param l The callback that will run.
   5372      */
   5373     public void setOnFocusChangeListener(OnFocusChangeListener l) {
   5374         getListenerInfo().mOnFocusChangeListener = l;
   5375     }
   5376 
   5377     /**
   5378      * Add a listener that will be called when the bounds of the view change due to
   5379      * layout processing.
   5380      *
   5381      * @param listener The listener that will be called when layout bounds change.
   5382      */
   5383     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
   5384         ListenerInfo li = getListenerInfo();
   5385         if (li.mOnLayoutChangeListeners == null) {
   5386             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
   5387         }
   5388         if (!li.mOnLayoutChangeListeners.contains(listener)) {
   5389             li.mOnLayoutChangeListeners.add(listener);
   5390         }
   5391     }
   5392 
   5393     /**
   5394      * Remove a listener for layout changes.
   5395      *
   5396      * @param listener The listener for layout bounds change.
   5397      */
   5398     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
   5399         ListenerInfo li = mListenerInfo;
   5400         if (li == null || li.mOnLayoutChangeListeners == null) {
   5401             return;
   5402         }
   5403         li.mOnLayoutChangeListeners.remove(listener);
   5404     }
   5405 
   5406     /**
   5407      * Add a listener for attach state changes.
   5408      *
   5409      * This listener will be called whenever this view is attached or detached
   5410      * from a window. Remove the listener using
   5411      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
   5412      *
   5413      * @param listener Listener to attach
   5414      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
   5415      */
   5416     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   5417         ListenerInfo li = getListenerInfo();
   5418         if (li.mOnAttachStateChangeListeners == null) {
   5419             li.mOnAttachStateChangeListeners
   5420                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
   5421         }
   5422         li.mOnAttachStateChangeListeners.add(listener);
   5423     }
   5424 
   5425     /**
   5426      * Remove a listener for attach state changes. The listener will receive no further
   5427      * notification of window attach/detach events.
   5428      *
   5429      * @param listener Listener to remove
   5430      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
   5431      */
   5432     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   5433         ListenerInfo li = mListenerInfo;
   5434         if (li == null || li.mOnAttachStateChangeListeners == null) {
   5435             return;
   5436         }
   5437         li.mOnAttachStateChangeListeners.remove(listener);
   5438     }
   5439 
   5440     /**
   5441      * Returns the focus-change callback registered for this view.
   5442      *
   5443      * @return The callback, or null if one is not registered.
   5444      */
   5445     public OnFocusChangeListener getOnFocusChangeListener() {
   5446         ListenerInfo li = mListenerInfo;
   5447         return li != null ? li.mOnFocusChangeListener : null;
   5448     }
   5449 
   5450     /**
   5451      * Register a callback to be invoked when this view is clicked. If this view is not
   5452      * clickable, it becomes clickable.
   5453      *
   5454      * @param l The callback that will run
   5455      *
   5456      * @see #setClickable(boolean)
   5457      */
   5458     public void setOnClickListener(@Nullable OnClickListener l) {
   5459         if (!isClickable()) {
   5460             setClickable(true);
   5461         }
   5462         getListenerInfo().mOnClickListener = l;
   5463     }
   5464 
   5465     /**
   5466      * Return whether this view has an attached OnClickListener.  Returns
   5467      * true if there is a listener, false if there is none.
   5468      */
   5469     public boolean hasOnClickListeners() {
   5470         ListenerInfo li = mListenerInfo;
   5471         return (li != null && li.mOnClickListener != null);
   5472     }
   5473 
   5474     /**
   5475      * Register a callback to be invoked when this view is clicked and held. If this view is not
   5476      * long clickable, it becomes long clickable.
   5477      *
   5478      * @param l The callback that will run
   5479      *
   5480      * @see #setLongClickable(boolean)
   5481      */
   5482     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
   5483         if (!isLongClickable()) {
   5484             setLongClickable(true);
   5485         }
   5486         getListenerInfo().mOnLongClickListener = l;
   5487     }
   5488 
   5489     /**
   5490      * Register a callback to be invoked when this view is context clicked. If the view is not
   5491      * context clickable, it becomes context clickable.
   5492      *
   5493      * @param l The callback that will run
   5494      * @see #setContextClickable(boolean)
   5495      */
   5496     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
   5497         if (!isContextClickable()) {
   5498             setContextClickable(true);
   5499         }
   5500         getListenerInfo().mOnContextClickListener = l;
   5501     }
   5502 
   5503     /**
   5504      * Register a callback to be invoked when the context menu for this view is
   5505      * being built. If this view is not long clickable, it becomes long clickable.
   5506      *
   5507      * @param l The callback that will run
   5508      *
   5509      */
   5510     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
   5511         if (!isLongClickable()) {
   5512             setLongClickable(true);
   5513         }
   5514         getListenerInfo().mOnCreateContextMenuListener = l;
   5515     }
   5516 
   5517     /**
   5518      * Set an observer to collect stats for each frame rendered for this view.
   5519      *
   5520      * @hide
   5521      */
   5522     public void addFrameMetricsListener(Window window,
   5523             Window.OnFrameMetricsAvailableListener listener,
   5524             Handler handler) {
   5525         if (mAttachInfo != null) {
   5526             if (mAttachInfo.mHardwareRenderer != null) {
   5527                 if (mFrameMetricsObservers == null) {
   5528                     mFrameMetricsObservers = new ArrayList<>();
   5529                 }
   5530 
   5531                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
   5532                         handler.getLooper(), listener);
   5533                 mFrameMetricsObservers.add(fmo);
   5534                 mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
   5535             } else {
   5536                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
   5537             }
   5538         } else {
   5539             if (mFrameMetricsObservers == null) {
   5540                 mFrameMetricsObservers = new ArrayList<>();
   5541             }
   5542 
   5543             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
   5544                     handler.getLooper(), listener);
   5545             mFrameMetricsObservers.add(fmo);
   5546         }
   5547     }
   5548 
   5549     /**
   5550      * Remove observer configured to collect frame stats for this view.
   5551      *
   5552      * @hide
   5553      */
   5554     public void removeFrameMetricsListener(
   5555             Window.OnFrameMetricsAvailableListener listener) {
   5556         ThreadedRenderer renderer = getHardwareRenderer();
   5557         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
   5558         if (fmo == null) {
   5559             throw new IllegalArgumentException(
   5560                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
   5561         }
   5562 
   5563         if (mFrameMetricsObservers != null) {
   5564             mFrameMetricsObservers.remove(fmo);
   5565             if (renderer != null) {
   5566                 renderer.removeFrameMetricsObserver(fmo);
   5567             }
   5568         }
   5569     }
   5570 
   5571     private void registerPendingFrameMetricsObservers() {
   5572         if (mFrameMetricsObservers != null) {
   5573             ThreadedRenderer renderer = getHardwareRenderer();
   5574             if (renderer != null) {
   5575                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
   5576                     renderer.addFrameMetricsObserver(fmo);
   5577                 }
   5578             } else {
   5579                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
   5580             }
   5581         }
   5582     }
   5583 
   5584     private FrameMetricsObserver findFrameMetricsObserver(
   5585             Window.OnFrameMetricsAvailableListener listener) {
   5586         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
   5587             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
   5588             if (observer.mListener == listener) {
   5589                 return observer;
   5590             }
   5591         }
   5592 
   5593         return null;
   5594     }
   5595 
   5596     /**
   5597      * Call this view's OnClickListener, if it is defined.  Performs all normal
   5598      * actions associated with clicking: reporting accessibility event, playing
   5599      * a sound, etc.
   5600      *
   5601      * @return True there was an assigned OnClickListener that was called, false
   5602      *         otherwise is returned.
   5603      */
   5604     public boolean performClick() {
   5605         final boolean result;
   5606         final ListenerInfo li = mListenerInfo;
   5607         if (li != null && li.mOnClickListener != null) {
   5608             playSoundEffect(SoundEffectConstants.CLICK);
   5609             li.mOnClickListener.onClick(this);
   5610             result = true;
   5611         } else {
   5612             result = false;
   5613         }
   5614 
   5615         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
   5616         return result;
   5617     }
   5618 
   5619     /**
   5620      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
   5621      * this only calls the listener, and does not do any associated clicking
   5622      * actions like reporting an accessibility event.
   5623      *
   5624      * @return True there was an assigned OnClickListener that was called, false
   5625      *         otherwise is returned.
   5626      */
   5627     public boolean callOnClick() {
   5628         ListenerInfo li = mListenerInfo;
   5629         if (li != null && li.mOnClickListener != null) {
   5630             li.mOnClickListener.onClick(this);
   5631             return true;
   5632         }
   5633         return false;
   5634     }
   5635 
   5636     /**
   5637      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   5638      * context menu if the OnLongClickListener did not consume the event.
   5639      *
   5640      * @return {@code true} if one of the above receivers consumed the event,
   5641      *         {@code false} otherwise
   5642      */
   5643     public boolean performLongClick() {
   5644         return performLongClickInternal(mLongClickX, mLongClickY);
   5645     }
   5646 
   5647     /**
   5648      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   5649      * context menu if the OnLongClickListener did not consume the event,
   5650      * anchoring it to an (x,y) coordinate.
   5651      *
   5652      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
   5653      *          to disable anchoring
   5654      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
   5655      *          to disable anchoring
   5656      * @return {@code true} if one of the above receivers consumed the event,
   5657      *         {@code false} otherwise
   5658      */
   5659     public boolean performLongClick(float x, float y) {
   5660         mLongClickX = x;
   5661         mLongClickY = y;
   5662         final boolean handled = performLongClick();
   5663         mLongClickX = Float.NaN;
   5664         mLongClickY = Float.NaN;
   5665         return handled;
   5666     }
   5667 
   5668     /**
   5669      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   5670      * context menu if the OnLongClickListener did not consume the event,
   5671      * optionally anchoring it to an (x,y) coordinate.
   5672      *
   5673      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
   5674      *          to disable anchoring
   5675      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
   5676      *          to disable anchoring
   5677      * @return {@code true} if one of the above receivers consumed the event,
   5678      *         {@code false} otherwise
   5679      */
   5680     private boolean performLongClickInternal(float x, float y) {
   5681         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
   5682 
   5683         boolean handled = false;
   5684         final ListenerInfo li = mListenerInfo;
   5685         if (li != null && li.mOnLongClickListener != null) {
   5686             handled = li.mOnLongClickListener.onLongClick(View.this);
   5687         }
   5688         if (!handled) {
   5689             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
   5690             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
   5691         }
   5692         if (handled) {
   5693             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
   5694         }
   5695         return handled;
   5696     }
   5697 
   5698     /**
   5699      * Call this view's OnContextClickListener, if it is defined.
   5700      *
   5701      * @param x the x coordinate of the context click
   5702      * @param y the y coordinate of the context click
   5703      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   5704      *         otherwise.
   5705      */
   5706     public boolean performContextClick(float x, float y) {
   5707         return performContextClick();
   5708     }
   5709 
   5710     /**
   5711      * Call this view's OnContextClickListener, if it is defined.
   5712      *
   5713      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   5714      *         otherwise.
   5715      */
   5716     public boolean performContextClick() {
   5717         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
   5718 
   5719         boolean handled = false;
   5720         ListenerInfo li = mListenerInfo;
   5721         if (li != null && li.mOnContextClickListener != null) {
   5722             handled = li.mOnContextClickListener.onContextClick(View.this);
   5723         }
   5724         if (handled) {
   5725             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
   5726         }
   5727         return handled;
   5728     }
   5729 
   5730     /**
   5731      * Performs button-related actions during a touch down event.
   5732      *
   5733      * @param event The event.
   5734      * @return True if the down was consumed.
   5735      *
   5736      * @hide
   5737      */
   5738     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
   5739         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
   5740             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
   5741             showContextMenu(event.getX(), event.getY());
   5742             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   5743             return true;
   5744         }
   5745         return false;
   5746     }
   5747 
   5748     /**
   5749      * Shows the context menu for this view.
   5750      *
   5751      * @return {@code true} if the context menu was shown, {@code false}
   5752      *         otherwise
   5753      * @see #showContextMenu(float, float)
   5754      */
   5755     public boolean showContextMenu() {
   5756         return getParent().showContextMenuForChild(this);
   5757     }
   5758 
   5759     /**
   5760      * Shows the context menu for this view anchored to the specified
   5761      * view-relative coordinate.
   5762      *
   5763      * @param x the X coordinate in pixels relative to the view to which the
   5764      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
   5765      * @param y the Y coordinate in pixels relative to the view to which the
   5766      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
   5767      * @return {@code true} if the context menu was shown, {@code false}
   5768      *         otherwise
   5769      */
   5770     public boolean showContextMenu(float x, float y) {
   5771         return getParent().showContextMenuForChild(this, x, y);
   5772     }
   5773 
   5774     /**
   5775      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
   5776      *
   5777      * @param callback Callback that will control the lifecycle of the action mode
   5778      * @return The new action mode if it is started, null otherwise
   5779      *
   5780      * @see ActionMode
   5781      * @see #startActionMode(android.view.ActionMode.Callback, int)
   5782      */
   5783     public ActionMode startActionMode(ActionMode.Callback callback) {
   5784         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
   5785     }
   5786 
   5787     /**
   5788      * Start an action mode with the given type.
   5789      *
   5790      * @param callback Callback that will control the lifecycle of the action mode
   5791      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
   5792      * @return The new action mode if it is started, null otherwise
   5793      *
   5794      * @see ActionMode
   5795      */
   5796     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
   5797         ViewParent parent = getParent();
   5798         if (parent == null) return null;
   5799         try {
   5800             return parent.startActionModeForChild(this, callback, type);
   5801         } catch (AbstractMethodError ame) {
   5802             // Older implementations of custom views might not implement this.
   5803             return parent.startActionModeForChild(this, callback);
   5804         }
   5805     }
   5806 
   5807     /**
   5808      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
   5809      * Context, creating a unique View identifier to retrieve the result.
   5810      *
   5811      * @param intent The Intent to be started.
   5812      * @param requestCode The request code to use.
   5813      * @hide
   5814      */
   5815     public void startActivityForResult(Intent intent, int requestCode) {
   5816         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
   5817         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
   5818     }
   5819 
   5820     /**
   5821      * If this View corresponds to the calling who, dispatches the activity result.
   5822      * @param who The identifier for the targeted View to receive the result.
   5823      * @param requestCode The integer request code originally supplied to
   5824      *                    startActivityForResult(), allowing you to identify who this
   5825      *                    result came from.
   5826      * @param resultCode The integer result code returned by the child activity
   5827      *                   through its setResult().
   5828      * @param data An Intent, which can return result data to the caller
   5829      *               (various data can be attached to Intent "extras").
   5830      * @return {@code true} if the activity result was dispatched.
   5831      * @hide
   5832      */
   5833     public boolean dispatchActivityResult(
   5834             String who, int requestCode, int resultCode, Intent data) {
   5835         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
   5836             onActivityResult(requestCode, resultCode, data);
   5837             mStartActivityRequestWho = null;
   5838             return true;
   5839         }
   5840         return false;
   5841     }
   5842 
   5843     /**
   5844      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
   5845      *
   5846      * @param requestCode The integer request code originally supplied to
   5847      *                    startActivityForResult(), allowing you to identify who this
   5848      *                    result came from.
   5849      * @param resultCode The integer result code returned by the child activity
   5850      *                   through its setResult().
   5851      * @param data An Intent, which can return result data to the caller
   5852      *               (various data can be attached to Intent "extras").
   5853      * @hide
   5854      */
   5855     public void onActivityResult(int requestCode, int resultCode, Intent data) {
   5856         // Do nothing.
   5857     }
   5858 
   5859     /**
   5860      * Register a callback to be invoked when a hardware key is pressed in this view.
   5861      * Key presses in software input methods will generally not trigger the methods of
   5862      * this listener.
   5863      * @param l the key listener to attach to this view
   5864      */
   5865     public void setOnKeyListener(OnKeyListener l) {
   5866         getListenerInfo().mOnKeyListener = l;
   5867     }
   5868 
   5869     /**
   5870      * Register a callback to be invoked when a touch event is sent to this view.
   5871      * @param l the touch listener to attach to this view
   5872      */
   5873     public void setOnTouchListener(OnTouchListener l) {
   5874         getListenerInfo().mOnTouchListener = l;
   5875     }
   5876 
   5877     /**
   5878      * Register a callback to be invoked when a generic motion event is sent to this view.
   5879      * @param l the generic motion listener to attach to this view
   5880      */
   5881     public void setOnGenericMotionListener(OnGenericMotionListener l) {
   5882         getListenerInfo().mOnGenericMotionListener = l;
   5883     }
   5884 
   5885     /**
   5886      * Register a callback to be invoked when a hover event is sent to this view.
   5887      * @param l the hover listener to attach to this view
   5888      */
   5889     public void setOnHoverListener(OnHoverListener l) {
   5890         getListenerInfo().mOnHoverListener = l;
   5891     }
   5892 
   5893     /**
   5894      * Register a drag event listener callback object for this View. The parameter is
   5895      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
   5896      * View, the system calls the
   5897      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
   5898      * @param l An implementation of {@link android.view.View.OnDragListener}.
   5899      */
   5900     public void setOnDragListener(OnDragListener l) {
   5901         getListenerInfo().mOnDragListener = l;
   5902     }
   5903 
   5904     /**
   5905      * Give this view focus. This will cause
   5906      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
   5907      *
   5908      * Note: this does not check whether this {@link View} should get focus, it just
   5909      * gives it focus no matter what.  It should only be called internally by framework
   5910      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
   5911      *
   5912      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
   5913      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
   5914      *        focus moved when requestFocus() is called. It may not always
   5915      *        apply, in which case use the default View.FOCUS_DOWN.
   5916      * @param previouslyFocusedRect The rectangle of the view that had focus
   5917      *        prior in this View's coordinate system.
   5918      */
   5919     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
   5920         if (DBG) {
   5921             System.out.println(this + " requestFocus()");
   5922         }
   5923 
   5924         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
   5925             mPrivateFlags |= PFLAG_FOCUSED;
   5926 
   5927             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
   5928 
   5929             if (mParent != null) {
   5930                 mParent.requestChildFocus(this, this);
   5931             }
   5932 
   5933             if (mAttachInfo != null) {
   5934                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
   5935             }
   5936 
   5937             onFocusChanged(true, direction, previouslyFocusedRect);
   5938             refreshDrawableState();
   5939         }
   5940     }
   5941 
   5942     /**
   5943      * Populates <code>outRect</code> with the hotspot bounds. By default,
   5944      * the hotspot bounds are identical to the screen bounds.
   5945      *
   5946      * @param outRect rect to populate with hotspot bounds
   5947      * @hide Only for internal use by views and widgets.
   5948      */
   5949     public void getHotspotBounds(Rect outRect) {
   5950         final Drawable background = getBackground();
   5951         if (background != null) {
   5952             background.getHotspotBounds(outRect);
   5953         } else {
   5954             getBoundsOnScreen(outRect);
   5955         }
   5956     }
   5957 
   5958     /**
   5959      * Request that a rectangle of this view be visible on the screen,
   5960      * scrolling if necessary just enough.
   5961      *
   5962      * <p>A View should call this if it maintains some notion of which part
   5963      * of its content is interesting.  For example, a text editing view
   5964      * should call this when its cursor moves.
   5965      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
   5966      * It should not be affected by which part of the View is currently visible or its scroll
   5967      * position.
   5968      *
   5969      * @param rectangle The rectangle in the View's content coordinate space
   5970      * @return Whether any parent scrolled.
   5971      */
   5972     public boolean requestRectangleOnScreen(Rect rectangle) {
   5973         return requestRectangleOnScreen(rectangle, false);
   5974     }
   5975 
   5976     /**
   5977      * Request that a rectangle of this view be visible on the screen,
   5978      * scrolling if necessary just enough.
   5979      *
   5980      * <p>A View should call this if it maintains some notion of which part
   5981      * of its content is interesting.  For example, a text editing view
   5982      * should call this when its cursor moves.
   5983      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
   5984      * It should not be affected by which part of the View is currently visible or its scroll
   5985      * position.
   5986      * <p>When <code>immediate</code> is set to true, scrolling will not be
   5987      * animated.
   5988      *
   5989      * @param rectangle The rectangle in the View's content coordinate space
   5990      * @param immediate True to forbid animated scrolling, false otherwise
   5991      * @return Whether any parent scrolled.
   5992      */
   5993     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
   5994         if (mParent == null) {
   5995             return false;
   5996         }
   5997 
   5998         View child = this;
   5999 
   6000         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
   6001         position.set(rectangle);
   6002 
   6003         ViewParent parent = mParent;
   6004         boolean scrolled = false;
   6005         while (parent != null) {
   6006             rectangle.set((int) position.left, (int) position.top,
   6007                     (int) position.right, (int) position.bottom);
   6008 
   6009             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
   6010 
   6011             if (!(parent instanceof View)) {
   6012                 break;
   6013             }
   6014 
   6015             // move it from child's content coordinate space to parent's content coordinate space
   6016             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
   6017 
   6018             child = (View) parent;
   6019             parent = child.getParent();
   6020         }
   6021 
   6022         return scrolled;
   6023     }
   6024 
   6025     /**
   6026      * Called when this view wants to give up focus. If focus is cleared
   6027      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
   6028      * <p>
   6029      * <strong>Note:</strong> When a View clears focus the framework is trying
   6030      * to give focus to the first focusable View from the top. Hence, if this
   6031      * View is the first from the top that can take focus, then all callbacks
   6032      * related to clearing focus will be invoked after which the framework will
   6033      * give focus to this view.
   6034      * </p>
   6035      */
   6036     public void clearFocus() {
   6037         if (DBG) {
   6038             System.out.println(this + " clearFocus()");
   6039         }
   6040 
   6041         clearFocusInternal(null, true, true);
   6042     }
   6043 
   6044     /**
   6045      * Clears focus from the view, optionally propagating the change up through
   6046      * the parent hierarchy and requesting that the root view place new focus.
   6047      *
   6048      * @param propagate whether to propagate the change up through the parent
   6049      *            hierarchy
   6050      * @param refocus when propagate is true, specifies whether to request the
   6051      *            root view place new focus
   6052      */
   6053     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
   6054         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   6055             mPrivateFlags &= ~PFLAG_FOCUSED;
   6056 
   6057             if (propagate && mParent != null) {
   6058                 mParent.clearChildFocus(this);
   6059             }
   6060 
   6061             onFocusChanged(false, 0, null);
   6062             refreshDrawableState();
   6063 
   6064             if (propagate && (!refocus || !rootViewRequestFocus())) {
   6065                 notifyGlobalFocusCleared(this);
   6066             }
   6067         }
   6068     }
   6069 
   6070     void notifyGlobalFocusCleared(View oldFocus) {
   6071         if (oldFocus != null && mAttachInfo != null) {
   6072             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
   6073         }
   6074     }
   6075 
   6076     boolean rootViewRequestFocus() {
   6077         final View root = getRootView();
   6078         return root != null && root.requestFocus();
   6079     }
   6080 
   6081     /**
   6082      * Called internally by the view system when a new view is getting focus.
   6083      * This is what clears the old focus.
   6084      * <p>
   6085      * <b>NOTE:</b> The parent view's focused child must be updated manually
   6086      * after calling this method. Otherwise, the view hierarchy may be left in
   6087      * an inconstent state.
   6088      */
   6089     void unFocus(View focused) {
   6090         if (DBG) {
   6091             System.out.println(this + " unFocus()");
   6092         }
   6093 
   6094         clearFocusInternal(focused, false, false);
   6095     }
   6096 
   6097     /**
   6098      * Returns true if this view has focus itself, or is the ancestor of the
   6099      * view that has focus.
   6100      *
   6101      * @return True if this view has or contains focus, false otherwise.
   6102      */
   6103     @ViewDebug.ExportedProperty(category = "focus")
   6104     public boolean hasFocus() {
   6105         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   6106     }
   6107 
   6108     /**
   6109      * Returns true if this view is focusable or if it contains a reachable View
   6110      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
   6111      * is a View whose parents do not block descendants focus.
   6112      *
   6113      * Only {@link #VISIBLE} views are considered focusable.
   6114      *
   6115      * @return True if the view is focusable or if the view contains a focusable
   6116      *         View, false otherwise.
   6117      *
   6118      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
   6119      * @see ViewGroup#getTouchscreenBlocksFocus()
   6120      */
   6121     public boolean hasFocusable() {
   6122         if (!isFocusableInTouchMode()) {
   6123             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
   6124                 final ViewGroup g = (ViewGroup) p;
   6125                 if (g.shouldBlockFocusForTouchscreen()) {
   6126                     return false;
   6127                 }
   6128             }
   6129         }
   6130         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
   6131     }
   6132 
   6133     /**
   6134      * Called by the view system when the focus state of this view changes.
   6135      * When the focus change event is caused by directional navigation, direction
   6136      * and previouslyFocusedRect provide insight into where the focus is coming from.
   6137      * When overriding, be sure to call up through to the super class so that
   6138      * the standard focus handling will occur.
   6139      *
   6140      * @param gainFocus True if the View has focus; false otherwise.
   6141      * @param direction The direction focus has moved when requestFocus()
   6142      *                  is called to give this view focus. Values are
   6143      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
   6144      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
   6145      *                  It may not always apply, in which case use the default.
   6146      * @param previouslyFocusedRect The rectangle, in this view's coordinate
   6147      *        system, of the previously focused view.  If applicable, this will be
   6148      *        passed in as finer grained information about where the focus is coming
   6149      *        from (in addition to direction).  Will be <code>null</code> otherwise.
   6150      */
   6151     @CallSuper
   6152     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
   6153             @Nullable Rect previouslyFocusedRect) {
   6154         if (gainFocus) {
   6155             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
   6156         } else {
   6157             notifyViewAccessibilityStateChangedIfNeeded(
   6158                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   6159         }
   6160 
   6161         InputMethodManager imm = InputMethodManager.peekInstance();
   6162         if (!gainFocus) {
   6163             if (isPressed()) {
   6164                 setPressed(false);
   6165             }
   6166             if (imm != null && mAttachInfo != null
   6167                     && mAttachInfo.mHasWindowFocus) {
   6168                 imm.focusOut(this);
   6169             }
   6170             onFocusLost();
   6171         } else if (imm != null && mAttachInfo != null
   6172                 && mAttachInfo.mHasWindowFocus) {
   6173             imm.focusIn(this);
   6174         }
   6175 
   6176         invalidate(true);
   6177         ListenerInfo li = mListenerInfo;
   6178         if (li != null && li.mOnFocusChangeListener != null) {
   6179             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
   6180         }
   6181 
   6182         if (mAttachInfo != null) {
   6183             mAttachInfo.mKeyDispatchState.reset(this);
   6184         }
   6185     }
   6186 
   6187     /**
   6188      * Sends an accessibility event of the given type. If accessibility is
   6189      * not enabled this method has no effect. The default implementation calls
   6190      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
   6191      * to populate information about the event source (this View), then calls
   6192      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
   6193      * populate the text content of the event source including its descendants,
   6194      * and last calls
   6195      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
   6196      * on its parent to request sending of the event to interested parties.
   6197      * <p>
   6198      * If an {@link AccessibilityDelegate} has been specified via calling
   6199      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6200      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
   6201      * responsible for handling this call.
   6202      * </p>
   6203      *
   6204      * @param eventType The type of the event to send, as defined by several types from
   6205      * {@link android.view.accessibility.AccessibilityEvent}, such as
   6206      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
   6207      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
   6208      *
   6209      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   6210      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   6211      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
   6212      * @see AccessibilityDelegate
   6213      */
   6214     public void sendAccessibilityEvent(int eventType) {
   6215         if (mAccessibilityDelegate != null) {
   6216             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
   6217         } else {
   6218             sendAccessibilityEventInternal(eventType);
   6219         }
   6220     }
   6221 
   6222     /**
   6223      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
   6224      * {@link AccessibilityEvent} to make an announcement which is related to some
   6225      * sort of a context change for which none of the events representing UI transitions
   6226      * is a good fit. For example, announcing a new page in a book. If accessibility
   6227      * is not enabled this method does nothing.
   6228      *
   6229      * @param text The announcement text.
   6230      */
   6231     public void announceForAccessibility(CharSequence text) {
   6232         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
   6233             AccessibilityEvent event = AccessibilityEvent.obtain(
   6234                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
   6235             onInitializeAccessibilityEvent(event);
   6236             event.getText().add(text);
   6237             event.setContentDescription(null);
   6238             mParent.requestSendAccessibilityEvent(this, event);
   6239         }
   6240     }
   6241 
   6242     /**
   6243      * @see #sendAccessibilityEvent(int)
   6244      *
   6245      * Note: Called from the default {@link AccessibilityDelegate}.
   6246      *
   6247      * @hide
   6248      */
   6249     public void sendAccessibilityEventInternal(int eventType) {
   6250         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   6251             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
   6252         }
   6253     }
   6254 
   6255     /**
   6256      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
   6257      * takes as an argument an empty {@link AccessibilityEvent} and does not
   6258      * perform a check whether accessibility is enabled.
   6259      * <p>
   6260      * If an {@link AccessibilityDelegate} has been specified via calling
   6261      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6262      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
   6263      * is responsible for handling this call.
   6264      * </p>
   6265      *
   6266      * @param event The event to send.
   6267      *
   6268      * @see #sendAccessibilityEvent(int)
   6269      */
   6270     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
   6271         if (mAccessibilityDelegate != null) {
   6272             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   6273         } else {
   6274             sendAccessibilityEventUncheckedInternal(event);
   6275         }
   6276     }
   6277 
   6278     /**
   6279      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
   6280      *
   6281      * Note: Called from the default {@link AccessibilityDelegate}.
   6282      *
   6283      * @hide
   6284      */
   6285     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
   6286         if (!isShown()) {
   6287             return;
   6288         }
   6289         onInitializeAccessibilityEvent(event);
   6290         // Only a subset of accessibility events populates text content.
   6291         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
   6292             dispatchPopulateAccessibilityEvent(event);
   6293         }
   6294         // In the beginning we called #isShown(), so we know that getParent() is not null.
   6295         getParent().requestSendAccessibilityEvent(this, event);
   6296     }
   6297 
   6298     /**
   6299      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
   6300      * to its children for adding their text content to the event. Note that the
   6301      * event text is populated in a separate dispatch path since we add to the
   6302      * event not only the text of the source but also the text of all its descendants.
   6303      * A typical implementation will call
   6304      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
   6305      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   6306      * on each child. Override this method if custom population of the event text
   6307      * content is required.
   6308      * <p>
   6309      * If an {@link AccessibilityDelegate} has been specified via calling
   6310      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6311      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
   6312      * is responsible for handling this call.
   6313      * </p>
   6314      * <p>
   6315      * <em>Note:</em> Accessibility events of certain types are not dispatched for
   6316      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
   6317      * </p>
   6318      *
   6319      * @param event The event.
   6320      *
   6321      * @return True if the event population was completed.
   6322      */
   6323     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
   6324         if (mAccessibilityDelegate != null) {
   6325             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
   6326         } else {
   6327             return dispatchPopulateAccessibilityEventInternal(event);
   6328         }
   6329     }
   6330 
   6331     /**
   6332      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   6333      *
   6334      * Note: Called from the default {@link AccessibilityDelegate}.
   6335      *
   6336      * @hide
   6337      */
   6338     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   6339         onPopulateAccessibilityEvent(event);
   6340         return false;
   6341     }
   6342 
   6343     /**
   6344      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   6345      * giving a chance to this View to populate the accessibility event with its
   6346      * text content. While this method is free to modify event
   6347      * attributes other than text content, doing so should normally be performed in
   6348      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
   6349      * <p>
   6350      * Example: Adding formatted date string to an accessibility event in addition
   6351      *          to the text added by the super implementation:
   6352      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   6353      *     super.onPopulateAccessibilityEvent(event);
   6354      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
   6355      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
   6356      *         mCurrentDate.getTimeInMillis(), flags);
   6357      *     event.getText().add(selectedDateUtterance);
   6358      * }</pre>
   6359      * <p>
   6360      * If an {@link AccessibilityDelegate} has been specified via calling
   6361      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6362      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
   6363      * is responsible for handling this call.
   6364      * </p>
   6365      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   6366      * information to the event, in case the default implementation has basic information to add.
   6367      * </p>
   6368      *
   6369      * @param event The accessibility event which to populate.
   6370      *
   6371      * @see #sendAccessibilityEvent(int)
   6372      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   6373      */
   6374     @CallSuper
   6375     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   6376         if (mAccessibilityDelegate != null) {
   6377             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
   6378         } else {
   6379             onPopulateAccessibilityEventInternal(event);
   6380         }
   6381     }
   6382 
   6383     /**
   6384      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
   6385      *
   6386      * Note: Called from the default {@link AccessibilityDelegate}.
   6387      *
   6388      * @hide
   6389      */
   6390     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   6391     }
   6392 
   6393     /**
   6394      * Initializes an {@link AccessibilityEvent} with information about
   6395      * this View which is the event source. In other words, the source of
   6396      * an accessibility event is the view whose state change triggered firing
   6397      * the event.
   6398      * <p>
   6399      * Example: Setting the password property of an event in addition
   6400      *          to properties set by the super implementation:
   6401      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   6402      *     super.onInitializeAccessibilityEvent(event);
   6403      *     event.setPassword(true);
   6404      * }</pre>
   6405      * <p>
   6406      * If an {@link AccessibilityDelegate} has been specified via calling
   6407      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6408      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
   6409      * is responsible for handling this call.
   6410      * </p>
   6411      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   6412      * information to the event, in case the default implementation has basic information to add.
   6413      * </p>
   6414      * @param event The event to initialize.
   6415      *
   6416      * @see #sendAccessibilityEvent(int)
   6417      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   6418      */
   6419     @CallSuper
   6420     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   6421         if (mAccessibilityDelegate != null) {
   6422             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
   6423         } else {
   6424             onInitializeAccessibilityEventInternal(event);
   6425         }
   6426     }
   6427 
   6428     /**
   6429      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   6430      *
   6431      * Note: Called from the default {@link AccessibilityDelegate}.
   6432      *
   6433      * @hide
   6434      */
   6435     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
   6436         event.setSource(this);
   6437         event.setClassName(getAccessibilityClassName());
   6438         event.setPackageName(getContext().getPackageName());
   6439         event.setEnabled(isEnabled());
   6440         event.setContentDescription(mContentDescription);
   6441 
   6442         switch (event.getEventType()) {
   6443             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
   6444                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
   6445                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
   6446                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
   6447                 event.setItemCount(focusablesTempList.size());
   6448                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
   6449                 if (mAttachInfo != null) {
   6450                     focusablesTempList.clear();
   6451                 }
   6452             } break;
   6453             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
   6454                 CharSequence text = getIterableTextForAccessibility();
   6455                 if (text != null && text.length() > 0) {
   6456                     event.setFromIndex(getAccessibilitySelectionStart());
   6457                     event.setToIndex(getAccessibilitySelectionEnd());
   6458                     event.setItemCount(text.length());
   6459                 }
   6460             } break;
   6461         }
   6462     }
   6463 
   6464     /**
   6465      * Returns an {@link AccessibilityNodeInfo} representing this view from the
   6466      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   6467      * This method is responsible for obtaining an accessibility node info from a
   6468      * pool of reusable instances and calling
   6469      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
   6470      * initialize the former.
   6471      * <p>
   6472      * Note: The client is responsible for recycling the obtained instance by calling
   6473      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
   6474      * </p>
   6475      *
   6476      * @return A populated {@link AccessibilityNodeInfo}.
   6477      *
   6478      * @see AccessibilityNodeInfo
   6479      */
   6480     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
   6481         if (mAccessibilityDelegate != null) {
   6482             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
   6483         } else {
   6484             return createAccessibilityNodeInfoInternal();
   6485         }
   6486     }
   6487 
   6488     /**
   6489      * @see #createAccessibilityNodeInfo()
   6490      *
   6491      * @hide
   6492      */
   6493     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
   6494         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   6495         if (provider != null) {
   6496             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
   6497         } else {
   6498             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
   6499             onInitializeAccessibilityNodeInfo(info);
   6500             return info;
   6501         }
   6502     }
   6503 
   6504     /**
   6505      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
   6506      * The base implementation sets:
   6507      * <ul>
   6508      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
   6509      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
   6510      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
   6511      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
   6512      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
   6513      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
   6514      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
   6515      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
   6516      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
   6517      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
   6518      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
   6519      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
   6520      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
   6521      * </ul>
   6522      * <p>
   6523      * Subclasses should override this method, call the super implementation,
   6524      * and set additional attributes.
   6525      * </p>
   6526      * <p>
   6527      * If an {@link AccessibilityDelegate} has been specified via calling
   6528      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6529      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
   6530      * is responsible for handling this call.
   6531      * </p>
   6532      *
   6533      * @param info The instance to initialize.
   6534      */
   6535     @CallSuper
   6536     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
   6537         if (mAccessibilityDelegate != null) {
   6538             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
   6539         } else {
   6540             onInitializeAccessibilityNodeInfoInternal(info);
   6541         }
   6542     }
   6543 
   6544     /**
   6545      * Gets the location of this view in screen coordinates.
   6546      *
   6547      * @param outRect The output location
   6548      * @hide
   6549      */
   6550     public void getBoundsOnScreen(Rect outRect) {
   6551         getBoundsOnScreen(outRect, false);
   6552     }
   6553 
   6554     /**
   6555      * Gets the location of this view in screen coordinates.
   6556      *
   6557      * @param outRect The output location
   6558      * @param clipToParent Whether to clip child bounds to the parent ones.
   6559      * @hide
   6560      */
   6561     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
   6562         if (mAttachInfo == null) {
   6563             return;
   6564         }
   6565 
   6566         RectF position = mAttachInfo.mTmpTransformRect;
   6567         position.set(0, 0, mRight - mLeft, mBottom - mTop);
   6568 
   6569         if (!hasIdentityMatrix()) {
   6570             getMatrix().mapRect(position);
   6571         }
   6572 
   6573         position.offset(mLeft, mTop);
   6574 
   6575         ViewParent parent = mParent;
   6576         while (parent instanceof View) {
   6577             View parentView = (View) parent;
   6578 
   6579             position.offset(-parentView.mScrollX, -parentView.mScrollY);
   6580 
   6581             if (clipToParent) {
   6582                 position.left = Math.max(position.left, 0);
   6583                 position.top = Math.max(position.top, 0);
   6584                 position.right = Math.min(position.right, parentView.getWidth());
   6585                 position.bottom = Math.min(position.bottom, parentView.getHeight());
   6586             }
   6587 
   6588             if (!parentView.hasIdentityMatrix()) {
   6589                 parentView.getMatrix().mapRect(position);
   6590             }
   6591 
   6592             position.offset(parentView.mLeft, parentView.mTop);
   6593 
   6594             parent = parentView.mParent;
   6595         }
   6596 
   6597         if (parent instanceof ViewRootImpl) {
   6598             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
   6599             position.offset(0, -viewRootImpl.mCurScrollY);
   6600         }
   6601 
   6602         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
   6603 
   6604         outRect.set(Math.round(position.left), Math.round(position.top),
   6605                 Math.round(position.right), Math.round(position.bottom));
   6606     }
   6607 
   6608     /**
   6609      * Return the class name of this object to be used for accessibility purposes.
   6610      * Subclasses should only override this if they are implementing something that
   6611      * should be seen as a completely new class of view when used by accessibility,
   6612      * unrelated to the class it is deriving from.  This is used to fill in
   6613      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
   6614      */
   6615     public CharSequence getAccessibilityClassName() {
   6616         return View.class.getName();
   6617     }
   6618 
   6619     /**
   6620      * Called when assist structure is being retrieved from a view as part of
   6621      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
   6622      * @param structure Fill in with structured view data.  The default implementation
   6623      * fills in all data that can be inferred from the view itself.
   6624      */
   6625     public void onProvideStructure(ViewStructure structure) {
   6626         final int id = mID;
   6627         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
   6628                 && (id&0x0000ffff) != 0) {
   6629             String pkg, type, entry;
   6630             try {
   6631                 final Resources res = getResources();
   6632                 entry = res.getResourceEntryName(id);
   6633                 type = res.getResourceTypeName(id);
   6634                 pkg = res.getResourcePackageName(id);
   6635             } catch (Resources.NotFoundException e) {
   6636                 entry = type = pkg = null;
   6637             }
   6638             structure.setId(id, pkg, type, entry);
   6639         } else {
   6640             structure.setId(id, null, null, null);
   6641         }
   6642         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
   6643         if (!hasIdentityMatrix()) {
   6644             structure.setTransformation(getMatrix());
   6645         }
   6646         structure.setElevation(getZ());
   6647         structure.setVisibility(getVisibility());
   6648         structure.setEnabled(isEnabled());
   6649         if (isClickable()) {
   6650             structure.setClickable(true);
   6651         }
   6652         if (isFocusable()) {
   6653             structure.setFocusable(true);
   6654         }
   6655         if (isFocused()) {
   6656             structure.setFocused(true);
   6657         }
   6658         if (isAccessibilityFocused()) {
   6659             structure.setAccessibilityFocused(true);
   6660         }
   6661         if (isSelected()) {
   6662             structure.setSelected(true);
   6663         }
   6664         if (isActivated()) {
   6665             structure.setActivated(true);
   6666         }
   6667         if (isLongClickable()) {
   6668             structure.setLongClickable(true);
   6669         }
   6670         if (this instanceof Checkable) {
   6671             structure.setCheckable(true);
   6672             if (((Checkable)this).isChecked()) {
   6673                 structure.setChecked(true);
   6674             }
   6675         }
   6676         if (isContextClickable()) {
   6677             structure.setContextClickable(true);
   6678         }
   6679         structure.setClassName(getAccessibilityClassName().toString());
   6680         structure.setContentDescription(getContentDescription());
   6681     }
   6682 
   6683     /**
   6684      * Called when assist structure is being retrieved from a view as part of
   6685      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
   6686      * generate additional virtual structure under this view.  The defaullt implementation
   6687      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
   6688      * view's virtual accessibility nodes, if any.  You can override this for a more
   6689      * optimal implementation providing this data.
   6690      */
   6691     public void onProvideVirtualStructure(ViewStructure structure) {
   6692         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   6693         if (provider != null) {
   6694             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
   6695             structure.setChildCount(1);
   6696             ViewStructure root = structure.newChild(0);
   6697             populateVirtualStructure(root, provider, info);
   6698             info.recycle();
   6699         }
   6700     }
   6701 
   6702     private void populateVirtualStructure(ViewStructure structure,
   6703             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
   6704         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
   6705                 null, null, null);
   6706         Rect rect = structure.getTempRect();
   6707         info.getBoundsInParent(rect);
   6708         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
   6709         structure.setVisibility(VISIBLE);
   6710         structure.setEnabled(info.isEnabled());
   6711         if (info.isClickable()) {
   6712             structure.setClickable(true);
   6713         }
   6714         if (info.isFocusable()) {
   6715             structure.setFocusable(true);
   6716         }
   6717         if (info.isFocused()) {
   6718             structure.setFocused(true);
   6719         }
   6720         if (info.isAccessibilityFocused()) {
   6721             structure.setAccessibilityFocused(true);
   6722         }
   6723         if (info.isSelected()) {
   6724             structure.setSelected(true);
   6725         }
   6726         if (info.isLongClickable()) {
   6727             structure.setLongClickable(true);
   6728         }
   6729         if (info.isCheckable()) {
   6730             structure.setCheckable(true);
   6731             if (info.isChecked()) {
   6732                 structure.setChecked(true);
   6733             }
   6734         }
   6735         if (info.isContextClickable()) {
   6736             structure.setContextClickable(true);
   6737         }
   6738         CharSequence cname = info.getClassName();
   6739         structure.setClassName(cname != null ? cname.toString() : null);
   6740         structure.setContentDescription(info.getContentDescription());
   6741         if (info.getText() != null || info.getError() != null) {
   6742             structure.setText(info.getText(), info.getTextSelectionStart(),
   6743                     info.getTextSelectionEnd());
   6744         }
   6745         final int NCHILDREN = info.getChildCount();
   6746         if (NCHILDREN > 0) {
   6747             structure.setChildCount(NCHILDREN);
   6748             for (int i=0; i<NCHILDREN; i++) {
   6749                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
   6750                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
   6751                 ViewStructure child = structure.newChild(i);
   6752                 populateVirtualStructure(child, provider, cinfo);
   6753                 cinfo.recycle();
   6754             }
   6755         }
   6756     }
   6757 
   6758     /**
   6759      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
   6760      * implementation calls {@link #onProvideStructure} and
   6761      * {@link #onProvideVirtualStructure}.
   6762      */
   6763     public void dispatchProvideStructure(ViewStructure structure) {
   6764         if (!isAssistBlocked()) {
   6765             onProvideStructure(structure);
   6766             onProvideVirtualStructure(structure);
   6767         } else {
   6768             structure.setClassName(getAccessibilityClassName().toString());
   6769             structure.setAssistBlocked(true);
   6770         }
   6771     }
   6772 
   6773     /**
   6774      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   6775      *
   6776      * Note: Called from the default {@link AccessibilityDelegate}.
   6777      *
   6778      * @hide
   6779      */
   6780     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
   6781         if (mAttachInfo == null) {
   6782             return;
   6783         }
   6784 
   6785         Rect bounds = mAttachInfo.mTmpInvalRect;
   6786 
   6787         getDrawingRect(bounds);
   6788         info.setBoundsInParent(bounds);
   6789 
   6790         getBoundsOnScreen(bounds, true);
   6791         info.setBoundsInScreen(bounds);
   6792 
   6793         ViewParent parent = getParentForAccessibility();
   6794         if (parent instanceof View) {
   6795             info.setParent((View) parent);
   6796         }
   6797 
   6798         if (mID != View.NO_ID) {
   6799             View rootView = getRootView();
   6800             if (rootView == null) {
   6801                 rootView = this;
   6802             }
   6803 
   6804             View label = rootView.findLabelForView(this, mID);
   6805             if (label != null) {
   6806                 info.setLabeledBy(label);
   6807             }
   6808 
   6809             if ((mAttachInfo.mAccessibilityFetchFlags
   6810                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
   6811                     && Resources.resourceHasPackage(mID)) {
   6812                 try {
   6813                     String viewId = getResources().getResourceName(mID);
   6814                     info.setViewIdResourceName(viewId);
   6815                 } catch (Resources.NotFoundException nfe) {
   6816                     /* ignore */
   6817                 }
   6818             }
   6819         }
   6820 
   6821         if (mLabelForId != View.NO_ID) {
   6822             View rootView = getRootView();
   6823             if (rootView == null) {
   6824                 rootView = this;
   6825             }
   6826             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
   6827             if (labeled != null) {
   6828                 info.setLabelFor(labeled);
   6829             }
   6830         }
   6831 
   6832         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
   6833             View rootView = getRootView();
   6834             if (rootView == null) {
   6835                 rootView = this;
   6836             }
   6837             View next = rootView.findViewInsideOutShouldExist(this,
   6838                     mAccessibilityTraversalBeforeId);
   6839             if (next != null && next.includeForAccessibility()) {
   6840                 info.setTraversalBefore(next);
   6841             }
   6842         }
   6843 
   6844         if (mAccessibilityTraversalAfterId != View.NO_ID) {
   6845             View rootView = getRootView();
   6846             if (rootView == null) {
   6847                 rootView = this;
   6848             }
   6849             View next = rootView.findViewInsideOutShouldExist(this,
   6850                     mAccessibilityTraversalAfterId);
   6851             if (next != null && next.includeForAccessibility()) {
   6852                 info.setTraversalAfter(next);
   6853             }
   6854         }
   6855 
   6856         info.setVisibleToUser(isVisibleToUser());
   6857 
   6858         if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
   6859                 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
   6860             info.setImportantForAccessibility(isImportantForAccessibility());
   6861         } else {
   6862             info.setImportantForAccessibility(true);
   6863         }
   6864 
   6865         info.setPackageName(mContext.getPackageName());
   6866         info.setClassName(getAccessibilityClassName());
   6867         info.setContentDescription(getContentDescription());
   6868 
   6869         info.setEnabled(isEnabled());
   6870         info.setClickable(isClickable());
   6871         info.setFocusable(isFocusable());
   6872         info.setFocused(isFocused());
   6873         info.setAccessibilityFocused(isAccessibilityFocused());
   6874         info.setSelected(isSelected());
   6875         info.setLongClickable(isLongClickable());
   6876         info.setContextClickable(isContextClickable());
   6877         info.setLiveRegion(getAccessibilityLiveRegion());
   6878 
   6879         // TODO: These make sense only if we are in an AdapterView but all
   6880         // views can be selected. Maybe from accessibility perspective
   6881         // we should report as selectable view in an AdapterView.
   6882         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
   6883         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
   6884 
   6885         if (isFocusable()) {
   6886             if (isFocused()) {
   6887                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
   6888             } else {
   6889                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
   6890             }
   6891         }
   6892 
   6893         if (!isAccessibilityFocused()) {
   6894             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
   6895         } else {
   6896             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
   6897         }
   6898 
   6899         if (isClickable() && isEnabled()) {
   6900             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
   6901         }
   6902 
   6903         if (isLongClickable() && isEnabled()) {
   6904             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
   6905         }
   6906 
   6907         if (isContextClickable() && isEnabled()) {
   6908             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
   6909         }
   6910 
   6911         CharSequence text = getIterableTextForAccessibility();
   6912         if (text != null && text.length() > 0) {
   6913             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
   6914 
   6915             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
   6916             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
   6917             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
   6918             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
   6919                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
   6920                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
   6921         }
   6922 
   6923         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
   6924         populateAccessibilityNodeInfoDrawingOrderInParent(info);
   6925     }
   6926 
   6927     /**
   6928      * Determine the order in which this view will be drawn relative to its siblings for a11y
   6929      *
   6930      * @param info The info whose drawing order should be populated
   6931      */
   6932     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
   6933         /*
   6934          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
   6935          * drawing order may not be well-defined, and some Views with custom drawing order may
   6936          * not be initialized sufficiently to respond properly getChildDrawingOrder.
   6937          */
   6938         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
   6939             info.setDrawingOrder(0);
   6940             return;
   6941         }
   6942         int drawingOrderInParent = 1;
   6943         // Iterate up the hierarchy if parents are not important for a11y
   6944         View viewAtDrawingLevel = this;
   6945         final ViewParent parent = getParentForAccessibility();
   6946         while (viewAtDrawingLevel != parent) {
   6947             final ViewParent currentParent = viewAtDrawingLevel.getParent();
   6948             if (!(currentParent instanceof ViewGroup)) {
   6949                 // Should only happen for the Decor
   6950                 drawingOrderInParent = 0;
   6951                 break;
   6952             } else {
   6953                 final ViewGroup parentGroup = (ViewGroup) currentParent;
   6954                 final int childCount = parentGroup.getChildCount();
   6955                 if (childCount > 1) {
   6956                     List<View> preorderedList = parentGroup.buildOrderedChildList();
   6957                     if (preorderedList != null) {
   6958                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
   6959                         for (int i = 0; i < childDrawIndex; i++) {
   6960                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
   6961                         }
   6962                     } else {
   6963                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
   6964                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
   6965                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
   6966                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
   6967                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
   6968                         if (childDrawIndex != 0) {
   6969                             for (int i = 0; i < numChildrenToIterate; i++) {
   6970                                 final int otherDrawIndex = (customOrder ?
   6971                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
   6972                                 if (otherDrawIndex < childDrawIndex) {
   6973                                     drawingOrderInParent +=
   6974                                             numViewsForAccessibility(parentGroup.getChildAt(i));
   6975                                 }
   6976                             }
   6977                         }
   6978                     }
   6979                 }
   6980             }
   6981             viewAtDrawingLevel = (View) currentParent;
   6982         }
   6983         info.setDrawingOrder(drawingOrderInParent);
   6984     }
   6985 
   6986     private static int numViewsForAccessibility(View view) {
   6987         if (view != null) {
   6988             if (view.includeForAccessibility()) {
   6989                 return 1;
   6990             } else if (view instanceof ViewGroup) {
   6991                 return ((ViewGroup) view).getNumChildrenForAccessibility();
   6992             }
   6993         }
   6994         return 0;
   6995     }
   6996 
   6997     private View findLabelForView(View view, int labeledId) {
   6998         if (mMatchLabelForPredicate == null) {
   6999             mMatchLabelForPredicate = new MatchLabelForPredicate();
   7000         }
   7001         mMatchLabelForPredicate.mLabeledId = labeledId;
   7002         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
   7003     }
   7004 
   7005     /**
   7006      * Computes whether this view is visible to the user. Such a view is
   7007      * attached, visible, all its predecessors are visible, it is not clipped
   7008      * entirely by its predecessors, and has an alpha greater than zero.
   7009      *
   7010      * @return Whether the view is visible on the screen.
   7011      *
   7012      * @hide
   7013      */
   7014     protected boolean isVisibleToUser() {
   7015         return isVisibleToUser(null);
   7016     }
   7017 
   7018     /**
   7019      * Computes whether the given portion of this view is visible to the user.
   7020      * Such a view is attached, visible, all its predecessors are visible,
   7021      * has an alpha greater than zero, and the specified portion is not
   7022      * clipped entirely by its predecessors.
   7023      *
   7024      * @param boundInView the portion of the view to test; coordinates should be relative; may be
   7025      *                    <code>null</code>, and the entire view will be tested in this case.
   7026      *                    When <code>true</code> is returned by the function, the actual visible
   7027      *                    region will be stored in this parameter; that is, if boundInView is fully
   7028      *                    contained within the view, no modification will be made, otherwise regions
   7029      *                    outside of the visible area of the view will be clipped.
   7030      *
   7031      * @return Whether the specified portion of the view is visible on the screen.
   7032      *
   7033      * @hide
   7034      */
   7035     protected boolean isVisibleToUser(Rect boundInView) {
   7036         if (mAttachInfo != null) {
   7037             // Attached to invisible window means this view is not visible.
   7038             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
   7039                 return false;
   7040             }
   7041             // An invisible predecessor or one with alpha zero means
   7042             // that this view is not visible to the user.
   7043             Object current = this;
   7044             while (current instanceof View) {
   7045                 View view = (View) current;
   7046                 // We have attach info so this view is attached and there is no
   7047                 // need to check whether we reach to ViewRootImpl on the way up.
   7048                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
   7049                         view.getVisibility() != VISIBLE) {
   7050                     return false;
   7051                 }
   7052                 current = view.mParent;
   7053             }
   7054             // Check if the view is entirely covered by its predecessors.
   7055             Rect visibleRect = mAttachInfo.mTmpInvalRect;
   7056             Point offset = mAttachInfo.mPoint;
   7057             if (!getGlobalVisibleRect(visibleRect, offset)) {
   7058                 return false;
   7059             }
   7060             // Check if the visible portion intersects the rectangle of interest.
   7061             if (boundInView != null) {
   7062                 visibleRect.offset(-offset.x, -offset.y);
   7063                 return boundInView.intersect(visibleRect);
   7064             }
   7065             return true;
   7066         }
   7067         return false;
   7068     }
   7069 
   7070     /**
   7071      * Returns the delegate for implementing accessibility support via
   7072      * composition. For more details see {@link AccessibilityDelegate}.
   7073      *
   7074      * @return The delegate, or null if none set.
   7075      *
   7076      * @hide
   7077      */
   7078     public AccessibilityDelegate getAccessibilityDelegate() {
   7079         return mAccessibilityDelegate;
   7080     }
   7081 
   7082     /**
   7083      * Sets a delegate for implementing accessibility support via composition
   7084      * (as opposed to inheritance). For more details, see
   7085      * {@link AccessibilityDelegate}.
   7086      * <p>
   7087      * <strong>Note:</strong> On platform versions prior to
   7088      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
   7089      * views in the {@code android.widget.*} package are called <i>before</i>
   7090      * host methods. This prevents certain properties such as class name from
   7091      * being modified by overriding
   7092      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
   7093      * as any changes will be overwritten by the host class.
   7094      * <p>
   7095      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
   7096      * methods are called <i>after</i> host methods, which all properties to be
   7097      * modified without being overwritten by the host class.
   7098      *
   7099      * @param delegate the object to which accessibility method calls should be
   7100      *                 delegated
   7101      * @see AccessibilityDelegate
   7102      */
   7103     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
   7104         mAccessibilityDelegate = delegate;
   7105     }
   7106 
   7107     /**
   7108      * Gets the provider for managing a virtual view hierarchy rooted at this View
   7109      * and reported to {@link android.accessibilityservice.AccessibilityService}s
   7110      * that explore the window content.
   7111      * <p>
   7112      * If this method returns an instance, this instance is responsible for managing
   7113      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
   7114      * View including the one representing the View itself. Similarly the returned
   7115      * instance is responsible for performing accessibility actions on any virtual
   7116      * view or the root view itself.
   7117      * </p>
   7118      * <p>
   7119      * If an {@link AccessibilityDelegate} has been specified via calling
   7120      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7121      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
   7122      * is responsible for handling this call.
   7123      * </p>
   7124      *
   7125      * @return The provider.
   7126      *
   7127      * @see AccessibilityNodeProvider
   7128      */
   7129     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
   7130         if (mAccessibilityDelegate != null) {
   7131             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
   7132         } else {
   7133             return null;
   7134         }
   7135     }
   7136 
   7137     /**
   7138      * Gets the unique identifier of this view on the screen for accessibility purposes.
   7139      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
   7140      *
   7141      * @return The view accessibility id.
   7142      *
   7143      * @hide
   7144      */
   7145     public int getAccessibilityViewId() {
   7146         if (mAccessibilityViewId == NO_ID) {
   7147             mAccessibilityViewId = sNextAccessibilityViewId++;
   7148         }
   7149         return mAccessibilityViewId;
   7150     }
   7151 
   7152     /**
   7153      * Gets the unique identifier of the window in which this View reseides.
   7154      *
   7155      * @return The window accessibility id.
   7156      *
   7157      * @hide
   7158      */
   7159     public int getAccessibilityWindowId() {
   7160         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
   7161                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
   7162     }
   7163 
   7164     /**
   7165      * Returns the {@link View}'s content description.
   7166      * <p>
   7167      * <strong>Note:</strong> Do not override this method, as it will have no
   7168      * effect on the content description presented to accessibility services.
   7169      * You must call {@link #setContentDescription(CharSequence)} to modify the
   7170      * content description.
   7171      *
   7172      * @return the content description
   7173      * @see #setContentDescription(CharSequence)
   7174      * @attr ref android.R.styleable#View_contentDescription
   7175      */
   7176     @ViewDebug.ExportedProperty(category = "accessibility")
   7177     public CharSequence getContentDescription() {
   7178         return mContentDescription;
   7179     }
   7180 
   7181     /**
   7182      * Sets the {@link View}'s content description.
   7183      * <p>
   7184      * A content description briefly describes the view and is primarily used
   7185      * for accessibility support to determine how a view should be presented to
   7186      * the user. In the case of a view with no textual representation, such as
   7187      * {@link android.widget.ImageButton}, a useful content description
   7188      * explains what the view does. For example, an image button with a phone
   7189      * icon that is used to place a call may use "Call" as its content
   7190      * description. An image of a floppy disk that is used to save a file may
   7191      * use "Save".
   7192      *
   7193      * @param contentDescription The content description.
   7194      * @see #getContentDescription()
   7195      * @attr ref android.R.styleable#View_contentDescription
   7196      */
   7197     @RemotableViewMethod
   7198     public void setContentDescription(CharSequence contentDescription) {
   7199         if (mContentDescription == null) {
   7200             if (contentDescription == null) {
   7201                 return;
   7202             }
   7203         } else if (mContentDescription.equals(contentDescription)) {
   7204             return;
   7205         }
   7206         mContentDescription = contentDescription;
   7207         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
   7208         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
   7209             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
   7210             notifySubtreeAccessibilityStateChangedIfNeeded();
   7211         } else {
   7212             notifyViewAccessibilityStateChangedIfNeeded(
   7213                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
   7214         }
   7215     }
   7216 
   7217     /**
   7218      * Sets the id of a view before which this one is visited in accessibility traversal.
   7219      * A screen-reader must visit the content of this view before the content of the one
   7220      * it precedes. For example, if view B is set to be before view A, then a screen-reader
   7221      * will traverse the entire content of B before traversing the entire content of A,
   7222      * regardles of what traversal strategy it is using.
   7223      * <p>
   7224      * Views that do not have specified before/after relationships are traversed in order
   7225      * determined by the screen-reader.
   7226      * </p>
   7227      * <p>
   7228      * Setting that this view is before a view that is not important for accessibility
   7229      * or if this view is not important for accessibility will have no effect as the
   7230      * screen-reader is not aware of unimportant views.
   7231      * </p>
   7232      *
   7233      * @param beforeId The id of a view this one precedes in accessibility traversal.
   7234      *
   7235      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
   7236      *
   7237      * @see #setImportantForAccessibility(int)
   7238      */
   7239     @RemotableViewMethod
   7240     public void setAccessibilityTraversalBefore(int beforeId) {
   7241         if (mAccessibilityTraversalBeforeId == beforeId) {
   7242             return;
   7243         }
   7244         mAccessibilityTraversalBeforeId = beforeId;
   7245         notifyViewAccessibilityStateChangedIfNeeded(
   7246                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   7247     }
   7248 
   7249     /**
   7250      * Gets the id of a view before which this one is visited in accessibility traversal.
   7251      *
   7252      * @return The id of a view this one precedes in accessibility traversal if
   7253      *         specified, otherwise {@link #NO_ID}.
   7254      *
   7255      * @see #setAccessibilityTraversalBefore(int)
   7256      */
   7257     public int getAccessibilityTraversalBefore() {
   7258         return mAccessibilityTraversalBeforeId;
   7259     }
   7260 
   7261     /**
   7262      * Sets the id of a view after which this one is visited in accessibility traversal.
   7263      * A screen-reader must visit the content of the other view before the content of this
   7264      * one. For example, if view B is set to be after view A, then a screen-reader
   7265      * will traverse the entire content of A before traversing the entire content of B,
   7266      * regardles of what traversal strategy it is using.
   7267      * <p>
   7268      * Views that do not have specified before/after relationships are traversed in order
   7269      * determined by the screen-reader.
   7270      * </p>
   7271      * <p>
   7272      * Setting that this view is after a view that is not important for accessibility
   7273      * or if this view is not important for accessibility will have no effect as the
   7274      * screen-reader is not aware of unimportant views.
   7275      * </p>
   7276      *
   7277      * @param afterId The id of a view this one succedees in accessibility traversal.
   7278      *
   7279      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
   7280      *
   7281      * @see #setImportantForAccessibility(int)
   7282      */
   7283     @RemotableViewMethod
   7284     public void setAccessibilityTraversalAfter(int afterId) {
   7285         if (mAccessibilityTraversalAfterId == afterId) {
   7286             return;
   7287         }
   7288         mAccessibilityTraversalAfterId = afterId;
   7289         notifyViewAccessibilityStateChangedIfNeeded(
   7290                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   7291     }
   7292 
   7293     /**
   7294      * Gets the id of a view after which this one is visited in accessibility traversal.
   7295      *
   7296      * @return The id of a view this one succeedes in accessibility traversal if
   7297      *         specified, otherwise {@link #NO_ID}.
   7298      *
   7299      * @see #setAccessibilityTraversalAfter(int)
   7300      */
   7301     public int getAccessibilityTraversalAfter() {
   7302         return mAccessibilityTraversalAfterId;
   7303     }
   7304 
   7305     /**
   7306      * Gets the id of a view for which this view serves as a label for
   7307      * accessibility purposes.
   7308      *
   7309      * @return The labeled view id.
   7310      */
   7311     @ViewDebug.ExportedProperty(category = "accessibility")
   7312     public int getLabelFor() {
   7313         return mLabelForId;
   7314     }
   7315 
   7316     /**
   7317      * Sets the id of a view for which this view serves as a label for
   7318      * accessibility purposes.
   7319      *
   7320      * @param id The labeled view id.
   7321      */
   7322     @RemotableViewMethod
   7323     public void setLabelFor(@IdRes int id) {
   7324         if (mLabelForId == id) {
   7325             return;
   7326         }
   7327         mLabelForId = id;
   7328         if (mLabelForId != View.NO_ID
   7329                 && mID == View.NO_ID) {
   7330             mID = generateViewId();
   7331         }
   7332         notifyViewAccessibilityStateChangedIfNeeded(
   7333                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   7334     }
   7335 
   7336     /**
   7337      * Invoked whenever this view loses focus, either by losing window focus or by losing
   7338      * focus within its window. This method can be used to clear any state tied to the
   7339      * focus. For instance, if a button is held pressed with the trackball and the window
   7340      * loses focus, this method can be used to cancel the press.
   7341      *
   7342      * Subclasses of View overriding this method should always call super.onFocusLost().
   7343      *
   7344      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
   7345      * @see #onWindowFocusChanged(boolean)
   7346      *
   7347      * @hide pending API council approval
   7348      */
   7349     @CallSuper
   7350     protected void onFocusLost() {
   7351         resetPressedState();
   7352     }
   7353 
   7354     private void resetPressedState() {
   7355         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   7356             return;
   7357         }
   7358 
   7359         if (isPressed()) {
   7360             setPressed(false);
   7361 
   7362             if (!mHasPerformedLongPress) {
   7363                 removeLongPressCallback();
   7364             }
   7365         }
   7366     }
   7367 
   7368     /**
   7369      * Returns true if this view has focus
   7370      *
   7371      * @return True if this view has focus, false otherwise.
   7372      */
   7373     @ViewDebug.ExportedProperty(category = "focus")
   7374     public boolean isFocused() {
   7375         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   7376     }
   7377 
   7378     /**
   7379      * Find the view in the hierarchy rooted at this view that currently has
   7380      * focus.
   7381      *
   7382      * @return The view that currently has focus, or null if no focused view can
   7383      *         be found.
   7384      */
   7385     public View findFocus() {
   7386         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
   7387     }
   7388 
   7389     /**
   7390      * Indicates whether this view is one of the set of scrollable containers in
   7391      * its window.
   7392      *
   7393      * @return whether this view is one of the set of scrollable containers in
   7394      * its window
   7395      *
   7396      * @attr ref android.R.styleable#View_isScrollContainer
   7397      */
   7398     public boolean isScrollContainer() {
   7399         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
   7400     }
   7401 
   7402     /**
   7403      * Change whether this view is one of the set of scrollable containers in
   7404      * its window.  This will be used to determine whether the window can
   7405      * resize or must pan when a soft input area is open -- scrollable
   7406      * containers allow the window to use resize mode since the container
   7407      * will appropriately shrink.
   7408      *
   7409      * @attr ref android.R.styleable#View_isScrollContainer
   7410      */
   7411     public void setScrollContainer(boolean isScrollContainer) {
   7412         if (isScrollContainer) {
   7413             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
   7414                 mAttachInfo.mScrollContainers.add(this);
   7415                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   7416             }
   7417             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
   7418         } else {
   7419             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   7420                 mAttachInfo.mScrollContainers.remove(this);
   7421             }
   7422             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
   7423         }
   7424     }
   7425 
   7426     /**
   7427      * Returns the quality of the drawing cache.
   7428      *
   7429      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   7430      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   7431      *
   7432      * @see #setDrawingCacheQuality(int)
   7433      * @see #setDrawingCacheEnabled(boolean)
   7434      * @see #isDrawingCacheEnabled()
   7435      *
   7436      * @attr ref android.R.styleable#View_drawingCacheQuality
   7437      */
   7438     @DrawingCacheQuality
   7439     public int getDrawingCacheQuality() {
   7440         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
   7441     }
   7442 
   7443     /**
   7444      * Set the drawing cache quality of this view. This value is used only when the
   7445      * drawing cache is enabled
   7446      *
   7447      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   7448      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   7449      *
   7450      * @see #getDrawingCacheQuality()
   7451      * @see #setDrawingCacheEnabled(boolean)
   7452      * @see #isDrawingCacheEnabled()
   7453      *
   7454      * @attr ref android.R.styleable#View_drawingCacheQuality
   7455      */
   7456     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
   7457         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
   7458     }
   7459 
   7460     /**
   7461      * Returns whether the screen should remain on, corresponding to the current
   7462      * value of {@link #KEEP_SCREEN_ON}.
   7463      *
   7464      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
   7465      *
   7466      * @see #setKeepScreenOn(boolean)
   7467      *
   7468      * @attr ref android.R.styleable#View_keepScreenOn
   7469      */
   7470     public boolean getKeepScreenOn() {
   7471         return (mViewFlags & KEEP_SCREEN_ON) != 0;
   7472     }
   7473 
   7474     /**
   7475      * Controls whether the screen should remain on, modifying the
   7476      * value of {@link #KEEP_SCREEN_ON}.
   7477      *
   7478      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
   7479      *
   7480      * @see #getKeepScreenOn()
   7481      *
   7482      * @attr ref android.R.styleable#View_keepScreenOn
   7483      */
   7484     public void setKeepScreenOn(boolean keepScreenOn) {
   7485         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
   7486     }
   7487 
   7488     /**
   7489      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   7490      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7491      *
   7492      * @attr ref android.R.styleable#View_nextFocusLeft
   7493      */
   7494     public int getNextFocusLeftId() {
   7495         return mNextFocusLeftId;
   7496     }
   7497 
   7498     /**
   7499      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   7500      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
   7501      * decide automatically.
   7502      *
   7503      * @attr ref android.R.styleable#View_nextFocusLeft
   7504      */
   7505     public void setNextFocusLeftId(int nextFocusLeftId) {
   7506         mNextFocusLeftId = nextFocusLeftId;
   7507     }
   7508 
   7509     /**
   7510      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   7511      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7512      *
   7513      * @attr ref android.R.styleable#View_nextFocusRight
   7514      */
   7515     public int getNextFocusRightId() {
   7516         return mNextFocusRightId;
   7517     }
   7518 
   7519     /**
   7520      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   7521      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
   7522      * decide automatically.
   7523      *
   7524      * @attr ref android.R.styleable#View_nextFocusRight
   7525      */
   7526     public void setNextFocusRightId(int nextFocusRightId) {
   7527         mNextFocusRightId = nextFocusRightId;
   7528     }
   7529 
   7530     /**
   7531      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   7532      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7533      *
   7534      * @attr ref android.R.styleable#View_nextFocusUp
   7535      */
   7536     public int getNextFocusUpId() {
   7537         return mNextFocusUpId;
   7538     }
   7539 
   7540     /**
   7541      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   7542      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
   7543      * decide automatically.
   7544      *
   7545      * @attr ref android.R.styleable#View_nextFocusUp
   7546      */
   7547     public void setNextFocusUpId(int nextFocusUpId) {
   7548         mNextFocusUpId = nextFocusUpId;
   7549     }
   7550 
   7551     /**
   7552      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   7553      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7554      *
   7555      * @attr ref android.R.styleable#View_nextFocusDown
   7556      */
   7557     public int getNextFocusDownId() {
   7558         return mNextFocusDownId;
   7559     }
   7560 
   7561     /**
   7562      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   7563      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
   7564      * decide automatically.
   7565      *
   7566      * @attr ref android.R.styleable#View_nextFocusDown
   7567      */
   7568     public void setNextFocusDownId(int nextFocusDownId) {
   7569         mNextFocusDownId = nextFocusDownId;
   7570     }
   7571 
   7572     /**
   7573      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   7574      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7575      *
   7576      * @attr ref android.R.styleable#View_nextFocusForward
   7577      */
   7578     public int getNextFocusForwardId() {
   7579         return mNextFocusForwardId;
   7580     }
   7581 
   7582     /**
   7583      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   7584      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
   7585      * decide automatically.
   7586      *
   7587      * @attr ref android.R.styleable#View_nextFocusForward
   7588      */
   7589     public void setNextFocusForwardId(int nextFocusForwardId) {
   7590         mNextFocusForwardId = nextFocusForwardId;
   7591     }
   7592 
   7593     /**
   7594      * Returns the visibility of this view and all of its ancestors
   7595      *
   7596      * @return True if this view and all of its ancestors are {@link #VISIBLE}
   7597      */
   7598     public boolean isShown() {
   7599         View current = this;
   7600         //noinspection ConstantConditions
   7601         do {
   7602             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   7603                 return false;
   7604             }
   7605             ViewParent parent = current.mParent;
   7606             if (parent == null) {
   7607                 return false; // We are not attached to the view root
   7608             }
   7609             if (!(parent instanceof View)) {
   7610                 return true;
   7611             }
   7612             current = (View) parent;
   7613         } while (current != null);
   7614 
   7615         return false;
   7616     }
   7617 
   7618     /**
   7619      * Called by the view hierarchy when the content insets for a window have
   7620      * changed, to allow it to adjust its content to fit within those windows.
   7621      * The content insets tell you the space that the status bar, input method,
   7622      * and other system windows infringe on the application's window.
   7623      *
   7624      * <p>You do not normally need to deal with this function, since the default
   7625      * window decoration given to applications takes care of applying it to the
   7626      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   7627      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
   7628      * and your content can be placed under those system elements.  You can then
   7629      * use this method within your view hierarchy if you have parts of your UI
   7630      * which you would like to ensure are not being covered.
   7631      *
   7632      * <p>The default implementation of this method simply applies the content
   7633      * insets to the view's padding, consuming that content (modifying the
   7634      * insets to be 0), and returning true.  This behavior is off by default, but can
   7635      * be enabled through {@link #setFitsSystemWindows(boolean)}.
   7636      *
   7637      * <p>This function's traversal down the hierarchy is depth-first.  The same content
   7638      * insets object is propagated down the hierarchy, so any changes made to it will
   7639      * be seen by all following views (including potentially ones above in
   7640      * the hierarchy since this is a depth-first traversal).  The first view
   7641      * that returns true will abort the entire traversal.
   7642      *
   7643      * <p>The default implementation works well for a situation where it is
   7644      * used with a container that covers the entire window, allowing it to
   7645      * apply the appropriate insets to its content on all edges.  If you need
   7646      * a more complicated layout (such as two different views fitting system
   7647      * windows, one on the top of the window, and one on the bottom),
   7648      * you can override the method and handle the insets however you would like.
   7649      * Note that the insets provided by the framework are always relative to the
   7650      * far edges of the window, not accounting for the location of the called view
   7651      * within that window.  (In fact when this method is called you do not yet know
   7652      * where the layout will place the view, as it is done before layout happens.)
   7653      *
   7654      * <p>Note: unlike many View methods, there is no dispatch phase to this
   7655      * call.  If you are overriding it in a ViewGroup and want to allow the
   7656      * call to continue to your children, you must be sure to call the super
   7657      * implementation.
   7658      *
   7659      * <p>Here is a sample layout that makes use of fitting system windows
   7660      * to have controls for a video view placed inside of the window decorations
   7661      * that it hides and shows.  This can be used with code like the second
   7662      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
   7663      *
   7664      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
   7665      *
   7666      * @param insets Current content insets of the window.  Prior to
   7667      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
   7668      * the insets or else you and Android will be unhappy.
   7669      *
   7670      * @return {@code true} if this view applied the insets and it should not
   7671      * continue propagating further down the hierarchy, {@code false} otherwise.
   7672      * @see #getFitsSystemWindows()
   7673      * @see #setFitsSystemWindows(boolean)
   7674      * @see #setSystemUiVisibility(int)
   7675      *
   7676      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
   7677      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
   7678      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
   7679      * to implement handling their own insets.
   7680      */
   7681     protected boolean fitSystemWindows(Rect insets) {
   7682         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
   7683             if (insets == null) {
   7684                 // Null insets by definition have already been consumed.
   7685                 // This call cannot apply insets since there are none to apply,
   7686                 // so return false.
   7687                 return false;
   7688             }
   7689             // If we're not in the process of dispatching the newer apply insets call,
   7690             // that means we're not in the compatibility path. Dispatch into the newer
   7691             // apply insets path and take things from there.
   7692             try {
   7693                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
   7694                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
   7695             } finally {
   7696                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
   7697             }
   7698         } else {
   7699             // We're being called from the newer apply insets path.
   7700             // Perform the standard fallback behavior.
   7701             return fitSystemWindowsInt(insets);
   7702         }
   7703     }
   7704 
   7705     private boolean fitSystemWindowsInt(Rect insets) {
   7706         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
   7707             mUserPaddingStart = UNDEFINED_PADDING;
   7708             mUserPaddingEnd = UNDEFINED_PADDING;
   7709             Rect localInsets = sThreadLocal.get();
   7710             if (localInsets == null) {
   7711                 localInsets = new Rect();
   7712                 sThreadLocal.set(localInsets);
   7713             }
   7714             boolean res = computeFitSystemWindows(insets, localInsets);
   7715             mUserPaddingLeftInitial = localInsets.left;
   7716             mUserPaddingRightInitial = localInsets.right;
   7717             internalSetPadding(localInsets.left, localInsets.top,
   7718                     localInsets.right, localInsets.bottom);
   7719             return res;
   7720         }
   7721         return false;
   7722     }
   7723 
   7724     /**
   7725      * Called when the view should apply {@link WindowInsets} according to its internal policy.
   7726      *
   7727      * <p>This method should be overridden by views that wish to apply a policy different from or
   7728      * in addition to the default behavior. Clients that wish to force a view subtree
   7729      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
   7730      *
   7731      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
   7732      * it will be called during dispatch instead of this method. The listener may optionally
   7733      * call this method from its own implementation if it wishes to apply the view's default
   7734      * insets policy in addition to its own.</p>
   7735      *
   7736      * <p>Implementations of this method should either return the insets parameter unchanged
   7737      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
   7738      * that this view applied itself. This allows new inset types added in future platform
   7739      * versions to pass through existing implementations unchanged without being erroneously
   7740      * consumed.</p>
   7741      *
   7742      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
   7743      * property is set then the view will consume the system window insets and apply them
   7744      * as padding for the view.</p>
   7745      *
   7746      * @param insets Insets to apply
   7747      * @return The supplied insets with any applied insets consumed
   7748      */
   7749     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
   7750         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
   7751             // We weren't called from within a direct call to fitSystemWindows,
   7752             // call into it as a fallback in case we're in a class that overrides it
   7753             // and has logic to perform.
   7754             if (fitSystemWindows(insets.getSystemWindowInsets())) {
   7755                 return insets.consumeSystemWindowInsets();
   7756             }
   7757         } else {
   7758             // We were called from within a direct call to fitSystemWindows.
   7759             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
   7760                 return insets.consumeSystemWindowInsets();
   7761             }
   7762         }
   7763         return insets;
   7764     }
   7765 
   7766     /**
   7767      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
   7768      * window insets to this view. The listener's
   7769      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   7770      * method will be called instead of the view's
   7771      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   7772      *
   7773      * @param listener Listener to set
   7774      *
   7775      * @see #onApplyWindowInsets(WindowInsets)
   7776      */
   7777     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
   7778         getListenerInfo().mOnApplyWindowInsetsListener = listener;
   7779     }
   7780 
   7781     /**
   7782      * Request to apply the given window insets to this view or another view in its subtree.
   7783      *
   7784      * <p>This method should be called by clients wishing to apply insets corresponding to areas
   7785      * obscured by window decorations or overlays. This can include the status and navigation bars,
   7786      * action bars, input methods and more. New inset categories may be added in the future.
   7787      * The method returns the insets provided minus any that were applied by this view or its
   7788      * children.</p>
   7789      *
   7790      * <p>Clients wishing to provide custom behavior should override the
   7791      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
   7792      * {@link OnApplyWindowInsetsListener} via the
   7793      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
   7794      * method.</p>
   7795      *
   7796      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
   7797      * </p>
   7798      *
   7799      * @param insets Insets to apply
   7800      * @return The provided insets minus the insets that were consumed
   7801      */
   7802     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
   7803         try {
   7804             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
   7805             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
   7806                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
   7807             } else {
   7808                 return onApplyWindowInsets(insets);
   7809             }
   7810         } finally {
   7811             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
   7812         }
   7813     }
   7814 
   7815     /**
   7816      * Compute the view's coordinate within the surface.
   7817      *
   7818      * <p>Computes the coordinates of this view in its surface. The argument
   7819      * must be an array of two integers. After the method returns, the array
   7820      * contains the x and y location in that order.</p>
   7821      * @hide
   7822      * @param location an array of two integers in which to hold the coordinates
   7823      */
   7824     public void getLocationInSurface(@Size(2) int[] location) {
   7825         getLocationInWindow(location);
   7826         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
   7827             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
   7828             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
   7829         }
   7830     }
   7831 
   7832     /**
   7833      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
   7834      * only available if the view is attached.
   7835      *
   7836      * @return WindowInsets from the top of the view hierarchy or null if View is detached
   7837      */
   7838     public WindowInsets getRootWindowInsets() {
   7839         if (mAttachInfo != null) {
   7840             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
   7841         }
   7842         return null;
   7843     }
   7844 
   7845     /**
   7846      * @hide Compute the insets that should be consumed by this view and the ones
   7847      * that should propagate to those under it.
   7848      */
   7849     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
   7850         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
   7851                 || mAttachInfo == null
   7852                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
   7853                         && !mAttachInfo.mOverscanRequested)) {
   7854             outLocalInsets.set(inoutInsets);
   7855             inoutInsets.set(0, 0, 0, 0);
   7856             return true;
   7857         } else {
   7858             // The application wants to take care of fitting system window for
   7859             // the content...  however we still need to take care of any overscan here.
   7860             final Rect overscan = mAttachInfo.mOverscanInsets;
   7861             outLocalInsets.set(overscan);
   7862             inoutInsets.left -= overscan.left;
   7863             inoutInsets.top -= overscan.top;
   7864             inoutInsets.right -= overscan.right;
   7865             inoutInsets.bottom -= overscan.bottom;
   7866             return false;
   7867         }
   7868     }
   7869 
   7870     /**
   7871      * Compute insets that should be consumed by this view and the ones that should propagate
   7872      * to those under it.
   7873      *
   7874      * @param in Insets currently being processed by this View, likely received as a parameter
   7875      *           to {@link #onApplyWindowInsets(WindowInsets)}.
   7876      * @param outLocalInsets A Rect that will receive the insets that should be consumed
   7877      *                       by this view
   7878      * @return Insets that should be passed along to views under this one
   7879      */
   7880     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
   7881         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
   7882                 || mAttachInfo == null
   7883                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
   7884             outLocalInsets.set(in.getSystemWindowInsets());
   7885             return in.consumeSystemWindowInsets();
   7886         } else {
   7887             outLocalInsets.set(0, 0, 0, 0);
   7888             return in;
   7889         }
   7890     }
   7891 
   7892     /**
   7893      * Sets whether or not this view should account for system screen decorations
   7894      * such as the status bar and inset its content; that is, controlling whether
   7895      * the default implementation of {@link #fitSystemWindows(Rect)} will be
   7896      * executed.  See that method for more details.
   7897      *
   7898      * <p>Note that if you are providing your own implementation of
   7899      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
   7900      * flag to true -- your implementation will be overriding the default
   7901      * implementation that checks this flag.
   7902      *
   7903      * @param fitSystemWindows If true, then the default implementation of
   7904      * {@link #fitSystemWindows(Rect)} will be executed.
   7905      *
   7906      * @attr ref android.R.styleable#View_fitsSystemWindows
   7907      * @see #getFitsSystemWindows()
   7908      * @see #fitSystemWindows(Rect)
   7909      * @see #setSystemUiVisibility(int)
   7910      */
   7911     public void setFitsSystemWindows(boolean fitSystemWindows) {
   7912         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
   7913     }
   7914 
   7915     /**
   7916      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
   7917      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
   7918      * will be executed.
   7919      *
   7920      * @return {@code true} if the default implementation of
   7921      * {@link #fitSystemWindows(Rect)} will be executed.
   7922      *
   7923      * @attr ref android.R.styleable#View_fitsSystemWindows
   7924      * @see #setFitsSystemWindows(boolean)
   7925      * @see #fitSystemWindows(Rect)
   7926      * @see #setSystemUiVisibility(int)
   7927      */
   7928     @ViewDebug.ExportedProperty
   7929     public boolean getFitsSystemWindows() {
   7930         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
   7931     }
   7932 
   7933     /** @hide */
   7934     public boolean fitsSystemWindows() {
   7935         return getFitsSystemWindows();
   7936     }
   7937 
   7938     /**
   7939      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
   7940      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
   7941      */
   7942     public void requestFitSystemWindows() {
   7943         if (mParent != null) {
   7944             mParent.requestFitSystemWindows();
   7945         }
   7946     }
   7947 
   7948     /**
   7949      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
   7950      */
   7951     public void requestApplyInsets() {
   7952         requestFitSystemWindows();
   7953     }
   7954 
   7955     /**
   7956      * For use by PhoneWindow to make its own system window fitting optional.
   7957      * @hide
   7958      */
   7959     public void makeOptionalFitsSystemWindows() {
   7960         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
   7961     }
   7962 
   7963     /**
   7964      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
   7965      * treat them as such.
   7966      * @hide
   7967      */
   7968     public void getOutsets(Rect outOutsetRect) {
   7969         if (mAttachInfo != null) {
   7970             outOutsetRect.set(mAttachInfo.mOutsets);
   7971         } else {
   7972             outOutsetRect.setEmpty();
   7973         }
   7974     }
   7975 
   7976     /**
   7977      * Returns the visibility status for this view.
   7978      *
   7979      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   7980      * @attr ref android.R.styleable#View_visibility
   7981      */
   7982     @ViewDebug.ExportedProperty(mapping = {
   7983         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
   7984         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
   7985         @ViewDebug.IntToString(from = GONE,      to = "GONE")
   7986     })
   7987     @Visibility
   7988     public int getVisibility() {
   7989         return mViewFlags & VISIBILITY_MASK;
   7990     }
   7991 
   7992     /**
   7993      * Set the enabled state of this view.
   7994      *
   7995      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   7996      * @attr ref android.R.styleable#View_visibility
   7997      */
   7998     @RemotableViewMethod
   7999     public void setVisibility(@Visibility int visibility) {
   8000         setFlags(visibility, VISIBILITY_MASK);
   8001     }
   8002 
   8003     /**
   8004      * Returns the enabled status for this view. The interpretation of the
   8005      * enabled state varies by subclass.
   8006      *
   8007      * @return True if this view is enabled, false otherwise.
   8008      */
   8009     @ViewDebug.ExportedProperty
   8010     public boolean isEnabled() {
   8011         return (mViewFlags & ENABLED_MASK) == ENABLED;
   8012     }
   8013 
   8014     /**
   8015      * Set the enabled state of this view. The interpretation of the enabled
   8016      * state varies by subclass.
   8017      *
   8018      * @param enabled True if this view is enabled, false otherwise.
   8019      */
   8020     @RemotableViewMethod
   8021     public void setEnabled(boolean enabled) {
   8022         if (enabled == isEnabled()) return;
   8023 
   8024         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
   8025 
   8026         /*
   8027          * The View most likely has to change its appearance, so refresh
   8028          * the drawable state.
   8029          */
   8030         refreshDrawableState();
   8031 
   8032         // Invalidate too, since the default behavior for views is to be
   8033         // be drawn at 50% alpha rather than to change the drawable.
   8034         invalidate(true);
   8035 
   8036         if (!enabled) {
   8037             cancelPendingInputEvents();
   8038         }
   8039     }
   8040 
   8041     /**
   8042      * Set whether this view can receive the focus.
   8043      *
   8044      * Setting this to false will also ensure that this view is not focusable
   8045      * in touch mode.
   8046      *
   8047      * @param focusable If true, this view can receive the focus.
   8048      *
   8049      * @see #setFocusableInTouchMode(boolean)
   8050      * @attr ref android.R.styleable#View_focusable
   8051      */
   8052     public void setFocusable(boolean focusable) {
   8053         if (!focusable) {
   8054             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
   8055         }
   8056         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
   8057     }
   8058 
   8059     /**
   8060      * Set whether this view can receive focus while in touch mode.
   8061      *
   8062      * Setting this to true will also ensure that this view is focusable.
   8063      *
   8064      * @param focusableInTouchMode If true, this view can receive the focus while
   8065      *   in touch mode.
   8066      *
   8067      * @see #setFocusable(boolean)
   8068      * @attr ref android.R.styleable#View_focusableInTouchMode
   8069      */
   8070     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
   8071         // Focusable in touch mode should always be set before the focusable flag
   8072         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
   8073         // which, in touch mode, will not successfully request focus on this view
   8074         // because the focusable in touch mode flag is not set
   8075         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
   8076         if (focusableInTouchMode) {
   8077             setFlags(FOCUSABLE, FOCUSABLE_MASK);
   8078         }
   8079     }
   8080 
   8081     /**
   8082      * Set whether this view should have sound effects enabled for events such as
   8083      * clicking and touching.
   8084      *
   8085      * <p>You may wish to disable sound effects for a view if you already play sounds,
   8086      * for instance, a dial key that plays dtmf tones.
   8087      *
   8088      * @param soundEffectsEnabled whether sound effects are enabled for this view.
   8089      * @see #isSoundEffectsEnabled()
   8090      * @see #playSoundEffect(int)
   8091      * @attr ref android.R.styleable#View_soundEffectsEnabled
   8092      */
   8093     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
   8094         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
   8095     }
   8096 
   8097     /**
   8098      * @return whether this view should have sound effects enabled for events such as
   8099      *     clicking and touching.
   8100      *
   8101      * @see #setSoundEffectsEnabled(boolean)
   8102      * @see #playSoundEffect(int)
   8103      * @attr ref android.R.styleable#View_soundEffectsEnabled
   8104      */
   8105     @ViewDebug.ExportedProperty
   8106     public boolean isSoundEffectsEnabled() {
   8107         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
   8108     }
   8109 
   8110     /**
   8111      * Set whether this view should have haptic feedback for events such as
   8112      * long presses.
   8113      *
   8114      * <p>You may wish to disable haptic feedback if your view already controls
   8115      * its own haptic feedback.
   8116      *
   8117      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
   8118      * @see #isHapticFeedbackEnabled()
   8119      * @see #performHapticFeedback(int)
   8120      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   8121      */
   8122     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
   8123         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
   8124     }
   8125 
   8126     /**
   8127      * @return whether this view should have haptic feedback enabled for events
   8128      * long presses.
   8129      *
   8130      * @see #setHapticFeedbackEnabled(boolean)
   8131      * @see #performHapticFeedback(int)
   8132      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   8133      */
   8134     @ViewDebug.ExportedProperty
   8135     public boolean isHapticFeedbackEnabled() {
   8136         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
   8137     }
   8138 
   8139     /**
   8140      * Returns the layout direction for this view.
   8141      *
   8142      * @return One of {@link #LAYOUT_DIRECTION_LTR},
   8143      *   {@link #LAYOUT_DIRECTION_RTL},
   8144      *   {@link #LAYOUT_DIRECTION_INHERIT} or
   8145      *   {@link #LAYOUT_DIRECTION_LOCALE}.
   8146      *
   8147      * @attr ref android.R.styleable#View_layoutDirection
   8148      *
   8149      * @hide
   8150      */
   8151     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   8152         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
   8153         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
   8154         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
   8155         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
   8156     })
   8157     @LayoutDir
   8158     public int getRawLayoutDirection() {
   8159         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   8160     }
   8161 
   8162     /**
   8163      * Set the layout direction for this view. This will propagate a reset of layout direction
   8164      * resolution to the view's children and resolve layout direction for this view.
   8165      *
   8166      * @param layoutDirection the layout direction to set. Should be one of:
   8167      *
   8168      * {@link #LAYOUT_DIRECTION_LTR},
   8169      * {@link #LAYOUT_DIRECTION_RTL},
   8170      * {@link #LAYOUT_DIRECTION_INHERIT},
   8171      * {@link #LAYOUT_DIRECTION_LOCALE}.
   8172      *
   8173      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
   8174      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   8175      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
   8176      *
   8177      * @attr ref android.R.styleable#View_layoutDirection
   8178      */
   8179     @RemotableViewMethod
   8180     public void setLayoutDirection(@LayoutDir int layoutDirection) {
   8181         if (getRawLayoutDirection() != layoutDirection) {
   8182             // Reset the current layout direction and the resolved one
   8183             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
   8184             resetRtlProperties();
   8185             // Set the new layout direction (filtered)
   8186             mPrivateFlags2 |=
   8187                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
   8188             // We need to resolve all RTL properties as they all depend on layout direction
   8189             resolveRtlPropertiesIfNeeded();
   8190             requestLayout();
   8191             invalidate(true);
   8192         }
   8193     }
   8194 
   8195     /**
   8196      * Returns the resolved layout direction for this view.
   8197      *
   8198      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
   8199      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
   8200      *
   8201      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
   8202      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
   8203      *
   8204      * @attr ref android.R.styleable#View_layoutDirection
   8205      */
   8206     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   8207         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
   8208         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
   8209     })
   8210     @ResolvedLayoutDir
   8211     public int getLayoutDirection() {
   8212         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   8213         if (targetSdkVersion < JELLY_BEAN_MR1) {
   8214             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   8215             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
   8216         }
   8217         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
   8218                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
   8219     }
   8220 
   8221     /**
   8222      * Indicates whether or not this view's layout is right-to-left. This is resolved from
   8223      * layout attribute and/or the inherited value from the parent
   8224      *
   8225      * @return true if the layout is right-to-left.
   8226      *
   8227      * @hide
   8228      */
   8229     @ViewDebug.ExportedProperty(category = "layout")
   8230     public boolean isLayoutRtl() {
   8231         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
   8232     }
   8233 
   8234     /**
   8235      * Indicates whether the view is currently tracking transient state that the
   8236      * app should not need to concern itself with saving and restoring, but that
   8237      * the framework should take special note to preserve when possible.
   8238      *
   8239      * <p>A view with transient state cannot be trivially rebound from an external
   8240      * data source, such as an adapter binding item views in a list. This may be
   8241      * because the view is performing an animation, tracking user selection
   8242      * of content, or similar.</p>
   8243      *
   8244      * @return true if the view has transient state
   8245      */
   8246     @ViewDebug.ExportedProperty(category = "layout")
   8247     public boolean hasTransientState() {
   8248         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
   8249     }
   8250 
   8251     /**
   8252      * Set whether this view is currently tracking transient state that the
   8253      * framework should attempt to preserve when possible. This flag is reference counted,
   8254      * so every call to setHasTransientState(true) should be paired with a later call
   8255      * to setHasTransientState(false).
   8256      *
   8257      * <p>A view with transient state cannot be trivially rebound from an external
   8258      * data source, such as an adapter binding item views in a list. This may be
   8259      * because the view is performing an animation, tracking user selection
   8260      * of content, or similar.</p>
   8261      *
   8262      * @param hasTransientState true if this view has transient state
   8263      */
   8264     public void setHasTransientState(boolean hasTransientState) {
   8265         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
   8266                 mTransientStateCount - 1;
   8267         if (mTransientStateCount < 0) {
   8268             mTransientStateCount = 0;
   8269             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
   8270                     "unmatched pair of setHasTransientState calls");
   8271         } else if ((hasTransientState && mTransientStateCount == 1) ||
   8272                 (!hasTransientState && mTransientStateCount == 0)) {
   8273             // update flag if we've just incremented up from 0 or decremented down to 0
   8274             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
   8275                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
   8276             if (mParent != null) {
   8277                 try {
   8278                     mParent.childHasTransientStateChanged(this, hasTransientState);
   8279                 } catch (AbstractMethodError e) {
   8280                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   8281                             " does not fully implement ViewParent", e);
   8282                 }
   8283             }
   8284         }
   8285     }
   8286 
   8287     /**
   8288      * Returns true if this view is currently attached to a window.
   8289      */
   8290     public boolean isAttachedToWindow() {
   8291         return mAttachInfo != null;
   8292     }
   8293 
   8294     /**
   8295      * Returns true if this view has been through at least one layout since it
   8296      * was last attached to or detached from a window.
   8297      */
   8298     public boolean isLaidOut() {
   8299         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
   8300     }
   8301 
   8302     /**
   8303      * If this view doesn't do any drawing on its own, set this flag to
   8304      * allow further optimizations. By default, this flag is not set on
   8305      * View, but could be set on some View subclasses such as ViewGroup.
   8306      *
   8307      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
   8308      * you should clear this flag.
   8309      *
   8310      * @param willNotDraw whether or not this View draw on its own
   8311      */
   8312     public void setWillNotDraw(boolean willNotDraw) {
   8313         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
   8314     }
   8315 
   8316     /**
   8317      * Returns whether or not this View draws on its own.
   8318      *
   8319      * @return true if this view has nothing to draw, false otherwise
   8320      */
   8321     @ViewDebug.ExportedProperty(category = "drawing")
   8322     public boolean willNotDraw() {
   8323         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
   8324     }
   8325 
   8326     /**
   8327      * When a View's drawing cache is enabled, drawing is redirected to an
   8328      * offscreen bitmap. Some views, like an ImageView, must be able to
   8329      * bypass this mechanism if they already draw a single bitmap, to avoid
   8330      * unnecessary usage of the memory.
   8331      *
   8332      * @param willNotCacheDrawing true if this view does not cache its
   8333      *        drawing, false otherwise
   8334      */
   8335     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
   8336         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
   8337     }
   8338 
   8339     /**
   8340      * Returns whether or not this View can cache its drawing or not.
   8341      *
   8342      * @return true if this view does not cache its drawing, false otherwise
   8343      */
   8344     @ViewDebug.ExportedProperty(category = "drawing")
   8345     public boolean willNotCacheDrawing() {
   8346         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
   8347     }
   8348 
   8349     /**
   8350      * Indicates whether this view reacts to click events or not.
   8351      *
   8352      * @return true if the view is clickable, false otherwise
   8353      *
   8354      * @see #setClickable(boolean)
   8355      * @attr ref android.R.styleable#View_clickable
   8356      */
   8357     @ViewDebug.ExportedProperty
   8358     public boolean isClickable() {
   8359         return (mViewFlags & CLICKABLE) == CLICKABLE;
   8360     }
   8361 
   8362     /**
   8363      * Enables or disables click events for this view. When a view
   8364      * is clickable it will change its state to "pressed" on every click.
   8365      * Subclasses should set the view clickable to visually react to
   8366      * user's clicks.
   8367      *
   8368      * @param clickable true to make the view clickable, false otherwise
   8369      *
   8370      * @see #isClickable()
   8371      * @attr ref android.R.styleable#View_clickable
   8372      */
   8373     public void setClickable(boolean clickable) {
   8374         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
   8375     }
   8376 
   8377     /**
   8378      * Indicates whether this view reacts to long click events or not.
   8379      *
   8380      * @return true if the view is long clickable, false otherwise
   8381      *
   8382      * @see #setLongClickable(boolean)
   8383      * @attr ref android.R.styleable#View_longClickable
   8384      */
   8385     public boolean isLongClickable() {
   8386         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   8387     }
   8388 
   8389     /**
   8390      * Enables or disables long click events for this view. When a view is long
   8391      * clickable it reacts to the user holding down the button for a longer
   8392      * duration than a tap. This event can either launch the listener or a
   8393      * context menu.
   8394      *
   8395      * @param longClickable true to make the view long clickable, false otherwise
   8396      * @see #isLongClickable()
   8397      * @attr ref android.R.styleable#View_longClickable
   8398      */
   8399     public void setLongClickable(boolean longClickable) {
   8400         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
   8401     }
   8402 
   8403     /**
   8404      * Indicates whether this view reacts to context clicks or not.
   8405      *
   8406      * @return true if the view is context clickable, false otherwise
   8407      * @see #setContextClickable(boolean)
   8408      * @attr ref android.R.styleable#View_contextClickable
   8409      */
   8410     public boolean isContextClickable() {
   8411         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   8412     }
   8413 
   8414     /**
   8415      * Enables or disables context clicking for this view. This event can launch the listener.
   8416      *
   8417      * @param contextClickable true to make the view react to a context click, false otherwise
   8418      * @see #isContextClickable()
   8419      * @attr ref android.R.styleable#View_contextClickable
   8420      */
   8421     public void setContextClickable(boolean contextClickable) {
   8422         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
   8423     }
   8424 
   8425     /**
   8426      * Sets the pressed state for this view and provides a touch coordinate for
   8427      * animation hinting.
   8428      *
   8429      * @param pressed Pass true to set the View's internal state to "pressed",
   8430      *            or false to reverts the View's internal state from a
   8431      *            previously set "pressed" state.
   8432      * @param x The x coordinate of the touch that caused the press
   8433      * @param y The y coordinate of the touch that caused the press
   8434      */
   8435     private void setPressed(boolean pressed, float x, float y) {
   8436         if (pressed) {
   8437             drawableHotspotChanged(x, y);
   8438         }
   8439 
   8440         setPressed(pressed);
   8441     }
   8442 
   8443     /**
   8444      * Sets the pressed state for this view.
   8445      *
   8446      * @see #isClickable()
   8447      * @see #setClickable(boolean)
   8448      *
   8449      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
   8450      *        the View's internal state from a previously set "pressed" state.
   8451      */
   8452     public void setPressed(boolean pressed) {
   8453         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
   8454 
   8455         if (pressed) {
   8456             mPrivateFlags |= PFLAG_PRESSED;
   8457         } else {
   8458             mPrivateFlags &= ~PFLAG_PRESSED;
   8459         }
   8460 
   8461         if (needsRefresh) {
   8462             refreshDrawableState();
   8463         }
   8464         dispatchSetPressed(pressed);
   8465     }
   8466 
   8467     /**
   8468      * Dispatch setPressed to all of this View's children.
   8469      *
   8470      * @see #setPressed(boolean)
   8471      *
   8472      * @param pressed The new pressed state
   8473      */
   8474     protected void dispatchSetPressed(boolean pressed) {
   8475     }
   8476 
   8477     /**
   8478      * Indicates whether the view is currently in pressed state. Unless
   8479      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
   8480      * the pressed state.
   8481      *
   8482      * @see #setPressed(boolean)
   8483      * @see #isClickable()
   8484      * @see #setClickable(boolean)
   8485      *
   8486      * @return true if the view is currently pressed, false otherwise
   8487      */
   8488     @ViewDebug.ExportedProperty
   8489     public boolean isPressed() {
   8490         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
   8491     }
   8492 
   8493     /**
   8494      * @hide
   8495      * Indicates whether this view will participate in data collection through
   8496      * {@link ViewStructure}.  If true, it will not provide any data
   8497      * for itself or its children.  If false, the normal data collection will be allowed.
   8498      *
   8499      * @return Returns false if assist data collection is not blocked, else true.
   8500      *
   8501      * @see #setAssistBlocked(boolean)
   8502      * @attr ref android.R.styleable#View_assistBlocked
   8503      */
   8504     public boolean isAssistBlocked() {
   8505         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
   8506     }
   8507 
   8508     /**
   8509      * @hide
   8510      * Controls whether assist data collection from this view and its children is enabled
   8511      * (that is, whether {@link #onProvideStructure} and
   8512      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
   8513      * allowing normal assist collection.  Setting this to false will disable assist collection.
   8514      *
   8515      * @param enabled Set to true to <em>disable</em> assist data collection, or false
   8516      * (the default) to allow it.
   8517      *
   8518      * @see #isAssistBlocked()
   8519      * @see #onProvideStructure
   8520      * @see #onProvideVirtualStructure
   8521      * @attr ref android.R.styleable#View_assistBlocked
   8522      */
   8523     public void setAssistBlocked(boolean enabled) {
   8524         if (enabled) {
   8525             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
   8526         } else {
   8527             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
   8528         }
   8529     }
   8530 
   8531     /**
   8532      * Indicates whether this view will save its state (that is,
   8533      * whether its {@link #onSaveInstanceState} method will be called).
   8534      *
   8535      * @return Returns true if the view state saving is enabled, else false.
   8536      *
   8537      * @see #setSaveEnabled(boolean)
   8538      * @attr ref android.R.styleable#View_saveEnabled
   8539      */
   8540     public boolean isSaveEnabled() {
   8541         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
   8542     }
   8543 
   8544     /**
   8545      * Controls whether the saving of this view's state is
   8546      * enabled (that is, whether its {@link #onSaveInstanceState} method
   8547      * will be called).  Note that even if freezing is enabled, the
   8548      * view still must have an id assigned to it (via {@link #setId(int)})
   8549      * for its state to be saved.  This flag can only disable the
   8550      * saving of this view; any child views may still have their state saved.
   8551      *
   8552      * @param enabled Set to false to <em>disable</em> state saving, or true
   8553      * (the default) to allow it.
   8554      *
   8555      * @see #isSaveEnabled()
   8556      * @see #setId(int)
   8557      * @see #onSaveInstanceState()
   8558      * @attr ref android.R.styleable#View_saveEnabled
   8559      */
   8560     public void setSaveEnabled(boolean enabled) {
   8561         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
   8562     }
   8563 
   8564     /**
   8565      * Gets whether the framework should discard touches when the view's
   8566      * window is obscured by another visible window.
   8567      * Refer to the {@link View} security documentation for more details.
   8568      *
   8569      * @return True if touch filtering is enabled.
   8570      *
   8571      * @see #setFilterTouchesWhenObscured(boolean)
   8572      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   8573      */
   8574     @ViewDebug.ExportedProperty
   8575     public boolean getFilterTouchesWhenObscured() {
   8576         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
   8577     }
   8578 
   8579     /**
   8580      * Sets whether the framework should discard touches when the view's
   8581      * window is obscured by another visible window.
   8582      * Refer to the {@link View} security documentation for more details.
   8583      *
   8584      * @param enabled True if touch filtering should be enabled.
   8585      *
   8586      * @see #getFilterTouchesWhenObscured
   8587      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   8588      */
   8589     public void setFilterTouchesWhenObscured(boolean enabled) {
   8590         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
   8591                 FILTER_TOUCHES_WHEN_OBSCURED);
   8592     }
   8593 
   8594     /**
   8595      * Indicates whether the entire hierarchy under this view will save its
   8596      * state when a state saving traversal occurs from its parent.  The default
   8597      * is true; if false, these views will not be saved unless
   8598      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   8599      *
   8600      * @return Returns true if the view state saving from parent is enabled, else false.
   8601      *
   8602      * @see #setSaveFromParentEnabled(boolean)
   8603      */
   8604     public boolean isSaveFromParentEnabled() {
   8605         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
   8606     }
   8607 
   8608     /**
   8609      * Controls whether the entire hierarchy under this view will save its
   8610      * state when a state saving traversal occurs from its parent.  The default
   8611      * is true; if false, these views will not be saved unless
   8612      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   8613      *
   8614      * @param enabled Set to false to <em>disable</em> state saving, or true
   8615      * (the default) to allow it.
   8616      *
   8617      * @see #isSaveFromParentEnabled()
   8618      * @see #setId(int)
   8619      * @see #onSaveInstanceState()
   8620      */
   8621     public void setSaveFromParentEnabled(boolean enabled) {
   8622         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
   8623     }
   8624 
   8625 
   8626     /**
   8627      * Returns whether this View is able to take focus.
   8628      *
   8629      * @return True if this view can take focus, or false otherwise.
   8630      * @attr ref android.R.styleable#View_focusable
   8631      */
   8632     @ViewDebug.ExportedProperty(category = "focus")
   8633     public final boolean isFocusable() {
   8634         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
   8635     }
   8636 
   8637     /**
   8638      * When a view is focusable, it may not want to take focus when in touch mode.
   8639      * For example, a button would like focus when the user is navigating via a D-pad
   8640      * so that the user can click on it, but once the user starts touching the screen,
   8641      * the button shouldn't take focus
   8642      * @return Whether the view is focusable in touch mode.
   8643      * @attr ref android.R.styleable#View_focusableInTouchMode
   8644      */
   8645     @ViewDebug.ExportedProperty
   8646     public final boolean isFocusableInTouchMode() {
   8647         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
   8648     }
   8649 
   8650     /**
   8651      * Find the nearest view in the specified direction that can take focus.
   8652      * This does not actually give focus to that view.
   8653      *
   8654      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   8655      *
   8656      * @return The nearest focusable in the specified direction, or null if none
   8657      *         can be found.
   8658      */
   8659     public View focusSearch(@FocusRealDirection int direction) {
   8660         if (mParent != null) {
   8661             return mParent.focusSearch(this, direction);
   8662         } else {
   8663             return null;
   8664         }
   8665     }
   8666 
   8667     /**
   8668      * This method is the last chance for the focused view and its ancestors to
   8669      * respond to an arrow key. This is called when the focused view did not
   8670      * consume the key internally, nor could the view system find a new view in
   8671      * the requested direction to give focus to.
   8672      *
   8673      * @param focused The currently focused view.
   8674      * @param direction The direction focus wants to move. One of FOCUS_UP,
   8675      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
   8676      * @return True if the this view consumed this unhandled move.
   8677      */
   8678     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
   8679         return false;
   8680     }
   8681 
   8682     /**
   8683      * If a user manually specified the next view id for a particular direction,
   8684      * use the root to look up the view.
   8685      * @param root The root view of the hierarchy containing this view.
   8686      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
   8687      * or FOCUS_BACKWARD.
   8688      * @return The user specified next view, or null if there is none.
   8689      */
   8690     View findUserSetNextFocus(View root, @FocusDirection int direction) {
   8691         switch (direction) {
   8692             case FOCUS_LEFT:
   8693                 if (mNextFocusLeftId == View.NO_ID) return null;
   8694                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
   8695             case FOCUS_RIGHT:
   8696                 if (mNextFocusRightId == View.NO_ID) return null;
   8697                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
   8698             case FOCUS_UP:
   8699                 if (mNextFocusUpId == View.NO_ID) return null;
   8700                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
   8701             case FOCUS_DOWN:
   8702                 if (mNextFocusDownId == View.NO_ID) return null;
   8703                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
   8704             case FOCUS_FORWARD:
   8705                 if (mNextFocusForwardId == View.NO_ID) return null;
   8706                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
   8707             case FOCUS_BACKWARD: {
   8708                 if (mID == View.NO_ID) return null;
   8709                 final int id = mID;
   8710                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
   8711                     @Override
   8712                     public boolean apply(View t) {
   8713                         return t.mNextFocusForwardId == id;
   8714                     }
   8715                 });
   8716             }
   8717         }
   8718         return null;
   8719     }
   8720 
   8721     private View findViewInsideOutShouldExist(View root, int id) {
   8722         if (mMatchIdPredicate == null) {
   8723             mMatchIdPredicate = new MatchIdPredicate();
   8724         }
   8725         mMatchIdPredicate.mId = id;
   8726         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
   8727         if (result == null) {
   8728             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
   8729         }
   8730         return result;
   8731     }
   8732 
   8733     /**
   8734      * Find and return all focusable views that are descendants of this view,
   8735      * possibly including this view if it is focusable itself.
   8736      *
   8737      * @param direction The direction of the focus
   8738      * @return A list of focusable views
   8739      */
   8740     public ArrayList<View> getFocusables(@FocusDirection int direction) {
   8741         ArrayList<View> result = new ArrayList<View>(24);
   8742         addFocusables(result, direction);
   8743         return result;
   8744     }
   8745 
   8746     /**
   8747      * Add any focusable views that are descendants of this view (possibly
   8748      * including this view if it is focusable itself) to views.  If we are in touch mode,
   8749      * only add views that are also focusable in touch mode.
   8750      *
   8751      * @param views Focusable views found so far
   8752      * @param direction The direction of the focus
   8753      */
   8754     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
   8755         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
   8756     }
   8757 
   8758     /**
   8759      * Adds any focusable views that are descendants of this view (possibly
   8760      * including this view if it is focusable itself) to views. This method
   8761      * adds all focusable views regardless if we are in touch mode or
   8762      * only views focusable in touch mode if we are in touch mode or
   8763      * only views that can take accessibility focus if accessibility is enabled
   8764      * depending on the focusable mode parameter.
   8765      *
   8766      * @param views Focusable views found so far or null if all we are interested is
   8767      *        the number of focusables.
   8768      * @param direction The direction of the focus.
   8769      * @param focusableMode The type of focusables to be added.
   8770      *
   8771      * @see #FOCUSABLES_ALL
   8772      * @see #FOCUSABLES_TOUCH_MODE
   8773      */
   8774     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
   8775             @FocusableMode int focusableMode) {
   8776         if (views == null) {
   8777             return;
   8778         }
   8779         if (!isFocusable()) {
   8780             return;
   8781         }
   8782         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
   8783                 && !isFocusableInTouchMode()) {
   8784             return;
   8785         }
   8786         views.add(this);
   8787     }
   8788 
   8789     /**
   8790      * Finds the Views that contain given text. The containment is case insensitive.
   8791      * The search is performed by either the text that the View renders or the content
   8792      * description that describes the view for accessibility purposes and the view does
   8793      * not render or both. Clients can specify how the search is to be performed via
   8794      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
   8795      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
   8796      *
   8797      * @param outViews The output list of matching Views.
   8798      * @param searched The text to match against.
   8799      *
   8800      * @see #FIND_VIEWS_WITH_TEXT
   8801      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
   8802      * @see #setContentDescription(CharSequence)
   8803      */
   8804     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
   8805             @FindViewFlags int flags) {
   8806         if (getAccessibilityNodeProvider() != null) {
   8807             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
   8808                 outViews.add(this);
   8809             }
   8810         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
   8811                 && (searched != null && searched.length() > 0)
   8812                 && (mContentDescription != null && mContentDescription.length() > 0)) {
   8813             String searchedLowerCase = searched.toString().toLowerCase();
   8814             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
   8815             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
   8816                 outViews.add(this);
   8817             }
   8818         }
   8819     }
   8820 
   8821     /**
   8822      * Find and return all touchable views that are descendants of this view,
   8823      * possibly including this view if it is touchable itself.
   8824      *
   8825      * @return A list of touchable views
   8826      */
   8827     public ArrayList<View> getTouchables() {
   8828         ArrayList<View> result = new ArrayList<View>();
   8829         addTouchables(result);
   8830         return result;
   8831     }
   8832 
   8833     /**
   8834      * Add any touchable views that are descendants of this view (possibly
   8835      * including this view if it is touchable itself) to views.
   8836      *
   8837      * @param views Touchable views found so far
   8838      */
   8839     public void addTouchables(ArrayList<View> views) {
   8840         final int viewFlags = mViewFlags;
   8841 
   8842         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   8843                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
   8844                 && (viewFlags & ENABLED_MASK) == ENABLED) {
   8845             views.add(this);
   8846         }
   8847     }
   8848 
   8849     /**
   8850      * Returns whether this View is accessibility focused.
   8851      *
   8852      * @return True if this View is accessibility focused.
   8853      */
   8854     public boolean isAccessibilityFocused() {
   8855         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
   8856     }
   8857 
   8858     /**
   8859      * Call this to try to give accessibility focus to this view.
   8860      *
   8861      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
   8862      * returns false or the view is no visible or the view already has accessibility
   8863      * focus.
   8864      *
   8865      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8866      * have focus, and you want your parent to look for the next one.
   8867      *
   8868      * @return Whether this view actually took accessibility focus.
   8869      *
   8870      * @hide
   8871      */
   8872     public boolean requestAccessibilityFocus() {
   8873         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
   8874         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
   8875             return false;
   8876         }
   8877         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   8878             return false;
   8879         }
   8880         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
   8881             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
   8882             ViewRootImpl viewRootImpl = getViewRootImpl();
   8883             if (viewRootImpl != null) {
   8884                 viewRootImpl.setAccessibilityFocus(this, null);
   8885             }
   8886             invalidate();
   8887             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
   8888             return true;
   8889         }
   8890         return false;
   8891     }
   8892 
   8893     /**
   8894      * Call this to try to clear accessibility focus of this view.
   8895      *
   8896      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8897      * have focus, and you want your parent to look for the next one.
   8898      *
   8899      * @hide
   8900      */
   8901     public void clearAccessibilityFocus() {
   8902         clearAccessibilityFocusNoCallbacks(0);
   8903 
   8904         // Clear the global reference of accessibility focus if this view or
   8905         // any of its descendants had accessibility focus. This will NOT send
   8906         // an event or update internal state if focus is cleared from a
   8907         // descendant view, which may leave views in inconsistent states.
   8908         final ViewRootImpl viewRootImpl = getViewRootImpl();
   8909         if (viewRootImpl != null) {
   8910             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
   8911             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   8912                 viewRootImpl.setAccessibilityFocus(null, null);
   8913             }
   8914         }
   8915     }
   8916 
   8917     private void sendAccessibilityHoverEvent(int eventType) {
   8918         // Since we are not delivering to a client accessibility events from not
   8919         // important views (unless the clinet request that) we need to fire the
   8920         // event from the deepest view exposed to the client. As a consequence if
   8921         // the user crosses a not exposed view the client will see enter and exit
   8922         // of the exposed predecessor followed by and enter and exit of that same
   8923         // predecessor when entering and exiting the not exposed descendant. This
   8924         // is fine since the client has a clear idea which view is hovered at the
   8925         // price of a couple more events being sent. This is a simple and
   8926         // working solution.
   8927         View source = this;
   8928         while (true) {
   8929             if (source.includeForAccessibility()) {
   8930                 source.sendAccessibilityEvent(eventType);
   8931                 return;
   8932             }
   8933             ViewParent parent = source.getParent();
   8934             if (parent instanceof View) {
   8935                 source = (View) parent;
   8936             } else {
   8937                 return;
   8938             }
   8939         }
   8940     }
   8941 
   8942     /**
   8943      * Clears accessibility focus without calling any callback methods
   8944      * normally invoked in {@link #clearAccessibilityFocus()}. This method
   8945      * is used separately from that one for clearing accessibility focus when
   8946      * giving this focus to another view.
   8947      *
   8948      * @param action The action, if any, that led to focus being cleared. Set to
   8949      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
   8950      * the window.
   8951      */
   8952     void clearAccessibilityFocusNoCallbacks(int action) {
   8953         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
   8954             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
   8955             invalidate();
   8956             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   8957                 AccessibilityEvent event = AccessibilityEvent.obtain(
   8958                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
   8959                 event.setAction(action);
   8960                 if (mAccessibilityDelegate != null) {
   8961                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   8962                 } else {
   8963                     sendAccessibilityEventUnchecked(event);
   8964                 }
   8965             }
   8966         }
   8967     }
   8968 
   8969     /**
   8970      * Call this to try to give focus to a specific view or to one of its
   8971      * descendants.
   8972      *
   8973      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   8974      * false), or if it is focusable and it is not focusable in touch mode
   8975      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   8976      *
   8977      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8978      * have focus, and you want your parent to look for the next one.
   8979      *
   8980      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
   8981      * {@link #FOCUS_DOWN} and <code>null</code>.
   8982      *
   8983      * @return Whether this view or one of its descendants actually took focus.
   8984      */
   8985     public final boolean requestFocus() {
   8986         return requestFocus(View.FOCUS_DOWN);
   8987     }
   8988 
   8989     /**
   8990      * Call this to try to give focus to a specific view or to one of its
   8991      * descendants and give it a hint about what direction focus is heading.
   8992      *
   8993      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   8994      * false), or if it is focusable and it is not focusable in touch mode
   8995      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   8996      *
   8997      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8998      * have focus, and you want your parent to look for the next one.
   8999      *
   9000      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
   9001      * <code>null</code> set for the previously focused rectangle.
   9002      *
   9003      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   9004      * @return Whether this view or one of its descendants actually took focus.
   9005      */
   9006     public final boolean requestFocus(int direction) {
   9007         return requestFocus(direction, null);
   9008     }
   9009 
   9010     /**
   9011      * Call this to try to give focus to a specific view or to one of its descendants
   9012      * and give it hints about the direction and a specific rectangle that the focus
   9013      * is coming from.  The rectangle can help give larger views a finer grained hint
   9014      * about where focus is coming from, and therefore, where to show selection, or
   9015      * forward focus change internally.
   9016      *
   9017      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   9018      * false), or if it is focusable and it is not focusable in touch mode
   9019      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   9020      *
   9021      * A View will not take focus if it is not visible.
   9022      *
   9023      * A View will not take focus if one of its parents has
   9024      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
   9025      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
   9026      *
   9027      * See also {@link #focusSearch(int)}, which is what you call to say that you
   9028      * have focus, and you want your parent to look for the next one.
   9029      *
   9030      * You may wish to override this method if your custom {@link View} has an internal
   9031      * {@link View} that it wishes to forward the request to.
   9032      *
   9033      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   9034      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
   9035      *        to give a finer grained hint about where focus is coming from.  May be null
   9036      *        if there is no hint.
   9037      * @return Whether this view or one of its descendants actually took focus.
   9038      */
   9039     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
   9040         return requestFocusNoSearch(direction, previouslyFocusedRect);
   9041     }
   9042 
   9043     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
   9044         // need to be focusable
   9045         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
   9046                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   9047             return false;
   9048         }
   9049 
   9050         // need to be focusable in touch mode if in touch mode
   9051         if (isInTouchMode() &&
   9052             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
   9053                return false;
   9054         }
   9055 
   9056         // need to not have any parents blocking us
   9057         if (hasAncestorThatBlocksDescendantFocus()) {
   9058             return false;
   9059         }
   9060 
   9061         handleFocusGainInternal(direction, previouslyFocusedRect);
   9062         return true;
   9063     }
   9064 
   9065     /**
   9066      * Call this to try to give focus to a specific view or to one of its descendants. This is a
   9067      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
   9068      * touch mode to request focus when they are touched.
   9069      *
   9070      * @return Whether this view or one of its descendants actually took focus.
   9071      *
   9072      * @see #isInTouchMode()
   9073      *
   9074      */
   9075     public final boolean requestFocusFromTouch() {
   9076         // Leave touch mode if we need to
   9077         if (isInTouchMode()) {
   9078             ViewRootImpl viewRoot = getViewRootImpl();
   9079             if (viewRoot != null) {
   9080                 viewRoot.ensureTouchMode(false);
   9081             }
   9082         }
   9083         return requestFocus(View.FOCUS_DOWN);
   9084     }
   9085 
   9086     /**
   9087      * @return Whether any ancestor of this view blocks descendant focus.
   9088      */
   9089     private boolean hasAncestorThatBlocksDescendantFocus() {
   9090         final boolean focusableInTouchMode = isFocusableInTouchMode();
   9091         ViewParent ancestor = mParent;
   9092         while (ancestor instanceof ViewGroup) {
   9093             final ViewGroup vgAncestor = (ViewGroup) ancestor;
   9094             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
   9095                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
   9096                 return true;
   9097             } else {
   9098                 ancestor = vgAncestor.getParent();
   9099             }
   9100         }
   9101         return false;
   9102     }
   9103 
   9104     /**
   9105      * Gets the mode for determining whether this View is important for accessibility
   9106      * which is if it fires accessibility events and if it is reported to
   9107      * accessibility services that query the screen.
   9108      *
   9109      * @return The mode for determining whether a View is important for accessibility.
   9110      *
   9111      * @attr ref android.R.styleable#View_importantForAccessibility
   9112      *
   9113      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   9114      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   9115      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   9116      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   9117      */
   9118     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
   9119             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
   9120             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
   9121             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
   9122             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
   9123                     to = "noHideDescendants")
   9124         })
   9125     public int getImportantForAccessibility() {
   9126         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   9127                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   9128     }
   9129 
   9130     /**
   9131      * Sets the live region mode for this view. This indicates to accessibility
   9132      * services whether they should automatically notify the user about changes
   9133      * to the view's content description or text, or to the content descriptions
   9134      * or text of the view's children (where applicable).
   9135      * <p>
   9136      * For example, in a login screen with a TextView that displays an "incorrect
   9137      * password" notification, that view should be marked as a live region with
   9138      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   9139      * <p>
   9140      * To disable change notifications for this view, use
   9141      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
   9142      * mode for most views.
   9143      * <p>
   9144      * To indicate that the user should be notified of changes, use
   9145      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   9146      * <p>
   9147      * If the view's changes should interrupt ongoing speech and notify the user
   9148      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
   9149      *
   9150      * @param mode The live region mode for this view, one of:
   9151      *        <ul>
   9152      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
   9153      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
   9154      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
   9155      *        </ul>
   9156      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   9157      */
   9158     public void setAccessibilityLiveRegion(int mode) {
   9159         if (mode != getAccessibilityLiveRegion()) {
   9160             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   9161             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
   9162                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   9163             notifyViewAccessibilityStateChangedIfNeeded(
   9164                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9165         }
   9166     }
   9167 
   9168     /**
   9169      * Gets the live region mode for this View.
   9170      *
   9171      * @return The live region mode for the view.
   9172      *
   9173      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   9174      *
   9175      * @see #setAccessibilityLiveRegion(int)
   9176      */
   9177     public int getAccessibilityLiveRegion() {
   9178         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
   9179                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   9180     }
   9181 
   9182     /**
   9183      * Sets how to determine whether this view is important for accessibility
   9184      * which is if it fires accessibility events and if it is reported to
   9185      * accessibility services that query the screen.
   9186      *
   9187      * @param mode How to determine whether this view is important for accessibility.
   9188      *
   9189      * @attr ref android.R.styleable#View_importantForAccessibility
   9190      *
   9191      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   9192      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   9193      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   9194      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   9195      */
   9196     public void setImportantForAccessibility(int mode) {
   9197         final int oldMode = getImportantForAccessibility();
   9198         if (mode != oldMode) {
   9199             final boolean hideDescendants =
   9200                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
   9201 
   9202             // If this node or its descendants are no longer important, try to
   9203             // clear accessibility focus.
   9204             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
   9205                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
   9206                 if (focusHost != null) {
   9207                     focusHost.clearAccessibilityFocus();
   9208                 }
   9209             }
   9210 
   9211             // If we're moving between AUTO and another state, we might not need
   9212             // to send a subtree changed notification. We'll store the computed
   9213             // importance, since we'll need to check it later to make sure.
   9214             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
   9215                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   9216             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
   9217             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   9218             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
   9219                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   9220             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
   9221                 notifySubtreeAccessibilityStateChangedIfNeeded();
   9222             } else {
   9223                 notifyViewAccessibilityStateChangedIfNeeded(
   9224                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9225             }
   9226         }
   9227     }
   9228 
   9229     /**
   9230      * Returns the view within this view's hierarchy that is hosting
   9231      * accessibility focus.
   9232      *
   9233      * @param searchDescendants whether to search for focus in descendant views
   9234      * @return the view hosting accessibility focus, or {@code null}
   9235      */
   9236     private View findAccessibilityFocusHost(boolean searchDescendants) {
   9237         if (isAccessibilityFocusedViewOrHost()) {
   9238             return this;
   9239         }
   9240 
   9241         if (searchDescendants) {
   9242             final ViewRootImpl viewRoot = getViewRootImpl();
   9243             if (viewRoot != null) {
   9244                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
   9245                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   9246                     return focusHost;
   9247                 }
   9248             }
   9249         }
   9250 
   9251         return null;
   9252     }
   9253 
   9254     /**
   9255      * Computes whether this view should be exposed for accessibility. In
   9256      * general, views that are interactive or provide information are exposed
   9257      * while views that serve only as containers are hidden.
   9258      * <p>
   9259      * If an ancestor of this view has importance
   9260      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
   9261      * returns <code>false</code>.
   9262      * <p>
   9263      * Otherwise, the value is computed according to the view's
   9264      * {@link #getImportantForAccessibility()} value:
   9265      * <ol>
   9266      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
   9267      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
   9268      * </code>
   9269      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
   9270      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
   9271      * view satisfies any of the following:
   9272      * <ul>
   9273      * <li>Is actionable, e.g. {@link #isClickable()},
   9274      * {@link #isLongClickable()}, or {@link #isFocusable()}
   9275      * <li>Has an {@link AccessibilityDelegate}
   9276      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
   9277      * {@link OnKeyListener}, etc.
   9278      * <li>Is an accessibility live region, e.g.
   9279      * {@link #getAccessibilityLiveRegion()} is not
   9280      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
   9281      * </ul>
   9282      * </ol>
   9283      *
   9284      * @return Whether the view is exposed for accessibility.
   9285      * @see #setImportantForAccessibility(int)
   9286      * @see #getImportantForAccessibility()
   9287      */
   9288     public boolean isImportantForAccessibility() {
   9289         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   9290                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   9291         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
   9292                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   9293             return false;
   9294         }
   9295 
   9296         // Check parent mode to ensure we're not hidden.
   9297         ViewParent parent = mParent;
   9298         while (parent instanceof View) {
   9299             if (((View) parent).getImportantForAccessibility()
   9300                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   9301                 return false;
   9302             }
   9303             parent = parent.getParent();
   9304         }
   9305 
   9306         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
   9307                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
   9308                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
   9309     }
   9310 
   9311     /**
   9312      * Gets the parent for accessibility purposes. Note that the parent for
   9313      * accessibility is not necessary the immediate parent. It is the first
   9314      * predecessor that is important for accessibility.
   9315      *
   9316      * @return The parent for accessibility purposes.
   9317      */
   9318     public ViewParent getParentForAccessibility() {
   9319         if (mParent instanceof View) {
   9320             View parentView = (View) mParent;
   9321             if (parentView.includeForAccessibility()) {
   9322                 return mParent;
   9323             } else {
   9324                 return mParent.getParentForAccessibility();
   9325             }
   9326         }
   9327         return null;
   9328     }
   9329 
   9330     /**
   9331      * Adds the children of this View relevant for accessibility to the given list
   9332      * as output. Since some Views are not important for accessibility the added
   9333      * child views are not necessarily direct children of this view, rather they are
   9334      * the first level of descendants important for accessibility.
   9335      *
   9336      * @param outChildren The output list that will receive children for accessibility.
   9337      */
   9338     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
   9339 
   9340     }
   9341 
   9342     /**
   9343      * Whether to regard this view for accessibility. A view is regarded for
   9344      * accessibility if it is important for accessibility or the querying
   9345      * accessibility service has explicitly requested that view not
   9346      * important for accessibility are regarded.
   9347      *
   9348      * @return Whether to regard the view for accessibility.
   9349      *
   9350      * @hide
   9351      */
   9352     public boolean includeForAccessibility() {
   9353         if (mAttachInfo != null) {
   9354             return (mAttachInfo.mAccessibilityFetchFlags
   9355                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
   9356                     || isImportantForAccessibility();
   9357         }
   9358         return false;
   9359     }
   9360 
   9361     /**
   9362      * Returns whether the View is considered actionable from
   9363      * accessibility perspective. Such view are important for
   9364      * accessibility.
   9365      *
   9366      * @return True if the view is actionable for accessibility.
   9367      *
   9368      * @hide
   9369      */
   9370     public boolean isActionableForAccessibility() {
   9371         return (isClickable() || isLongClickable() || isFocusable());
   9372     }
   9373 
   9374     /**
   9375      * Returns whether the View has registered callbacks which makes it
   9376      * important for accessibility.
   9377      *
   9378      * @return True if the view is actionable for accessibility.
   9379      */
   9380     private boolean hasListenersForAccessibility() {
   9381         ListenerInfo info = getListenerInfo();
   9382         return mTouchDelegate != null || info.mOnKeyListener != null
   9383                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
   9384                 || info.mOnHoverListener != null || info.mOnDragListener != null;
   9385     }
   9386 
   9387     /**
   9388      * Notifies that the accessibility state of this view changed. The change
   9389      * is local to this view and does not represent structural changes such
   9390      * as children and parent. For example, the view became focusable. The
   9391      * notification is at at most once every
   9392      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   9393      * to avoid unnecessary load to the system. Also once a view has a pending
   9394      * notification this method is a NOP until the notification has been sent.
   9395      *
   9396      * @hide
   9397      */
   9398     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
   9399         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   9400             return;
   9401         }
   9402         if (mSendViewStateChangedAccessibilityEvent == null) {
   9403             mSendViewStateChangedAccessibilityEvent =
   9404                     new SendViewStateChangedAccessibilityEvent();
   9405         }
   9406         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
   9407     }
   9408 
   9409     /**
   9410      * Notifies that the accessibility state of this view changed. The change
   9411      * is *not* local to this view and does represent structural changes such
   9412      * as children and parent. For example, the view size changed. The
   9413      * notification is at at most once every
   9414      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   9415      * to avoid unnecessary load to the system. Also once a view has a pending
   9416      * notification this method is a NOP until the notification has been sent.
   9417      *
   9418      * @hide
   9419      */
   9420     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
   9421         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   9422             return;
   9423         }
   9424         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
   9425             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   9426             if (mParent != null) {
   9427                 try {
   9428                     mParent.notifySubtreeAccessibilityStateChanged(
   9429                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
   9430                 } catch (AbstractMethodError e) {
   9431                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   9432                             " does not fully implement ViewParent", e);
   9433                 }
   9434             }
   9435         }
   9436     }
   9437 
   9438     /**
   9439      * Change the visibility of the View without triggering any other changes. This is
   9440      * important for transitions, where visibility changes should not adjust focus or
   9441      * trigger a new layout. This is only used when the visibility has already been changed
   9442      * and we need a transient value during an animation. When the animation completes,
   9443      * the original visibility value is always restored.
   9444      *
   9445      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   9446      * @hide
   9447      */
   9448     public void setTransitionVisibility(@Visibility int visibility) {
   9449         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
   9450     }
   9451 
   9452     /**
   9453      * Reset the flag indicating the accessibility state of the subtree rooted
   9454      * at this view changed.
   9455      */
   9456     void resetSubtreeAccessibilityStateChanged() {
   9457         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   9458     }
   9459 
   9460     /**
   9461      * Report an accessibility action to this view's parents for delegated processing.
   9462      *
   9463      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
   9464      * call this method to delegate an accessibility action to a supporting parent. If the parent
   9465      * returns true from its
   9466      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
   9467      * method this method will return true to signify that the action was consumed.</p>
   9468      *
   9469      * <p>This method is useful for implementing nested scrolling child views. If
   9470      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
   9471      * a custom view implementation may invoke this method to allow a parent to consume the
   9472      * scroll first. If this method returns true the custom view should skip its own scrolling
   9473      * behavior.</p>
   9474      *
   9475      * @param action Accessibility action to delegate
   9476      * @param arguments Optional action arguments
   9477      * @return true if the action was consumed by a parent
   9478      */
   9479     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
   9480         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
   9481             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
   9482                 return true;
   9483             }
   9484         }
   9485         return false;
   9486     }
   9487 
   9488     /**
   9489      * Performs the specified accessibility action on the view. For
   9490      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   9491      * <p>
   9492      * If an {@link AccessibilityDelegate} has been specified via calling
   9493      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   9494      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
   9495      * is responsible for handling this call.
   9496      * </p>
   9497      *
   9498      * <p>The default implementation will delegate
   9499      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
   9500      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
   9501      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
   9502      *
   9503      * @param action The action to perform.
   9504      * @param arguments Optional action arguments.
   9505      * @return Whether the action was performed.
   9506      */
   9507     public boolean performAccessibilityAction(int action, Bundle arguments) {
   9508       if (mAccessibilityDelegate != null) {
   9509           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
   9510       } else {
   9511           return performAccessibilityActionInternal(action, arguments);
   9512       }
   9513     }
   9514 
   9515    /**
   9516     * @see #performAccessibilityAction(int, Bundle)
   9517     *
   9518     * Note: Called from the default {@link AccessibilityDelegate}.
   9519     *
   9520     * @hide
   9521     */
   9522     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
   9523         if (isNestedScrollingEnabled()
   9524                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
   9525                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
   9526                 || action == R.id.accessibilityActionScrollUp
   9527                 || action == R.id.accessibilityActionScrollLeft
   9528                 || action == R.id.accessibilityActionScrollDown
   9529                 || action == R.id.accessibilityActionScrollRight)) {
   9530             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
   9531                 return true;
   9532             }
   9533         }
   9534 
   9535         switch (action) {
   9536             case AccessibilityNodeInfo.ACTION_CLICK: {
   9537                 if (isClickable()) {
   9538                     performClick();
   9539                     return true;
   9540                 }
   9541             } break;
   9542             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
   9543                 if (isLongClickable()) {
   9544                     performLongClick();
   9545                     return true;
   9546                 }
   9547             } break;
   9548             case AccessibilityNodeInfo.ACTION_FOCUS: {
   9549                 if (!hasFocus()) {
   9550                     // Get out of touch mode since accessibility
   9551                     // wants to move focus around.
   9552                     getViewRootImpl().ensureTouchMode(false);
   9553                     return requestFocus();
   9554                 }
   9555             } break;
   9556             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
   9557                 if (hasFocus()) {
   9558                     clearFocus();
   9559                     return !isFocused();
   9560                 }
   9561             } break;
   9562             case AccessibilityNodeInfo.ACTION_SELECT: {
   9563                 if (!isSelected()) {
   9564                     setSelected(true);
   9565                     return isSelected();
   9566                 }
   9567             } break;
   9568             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
   9569                 if (isSelected()) {
   9570                     setSelected(false);
   9571                     return !isSelected();
   9572                 }
   9573             } break;
   9574             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
   9575                 if (!isAccessibilityFocused()) {
   9576                     return requestAccessibilityFocus();
   9577                 }
   9578             } break;
   9579             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
   9580                 if (isAccessibilityFocused()) {
   9581                     clearAccessibilityFocus();
   9582                     return true;
   9583                 }
   9584             } break;
   9585             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
   9586                 if (arguments != null) {
   9587                     final int granularity = arguments.getInt(
   9588                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   9589                     final boolean extendSelection = arguments.getBoolean(
   9590                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   9591                     return traverseAtGranularity(granularity, true, extendSelection);
   9592                 }
   9593             } break;
   9594             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
   9595                 if (arguments != null) {
   9596                     final int granularity = arguments.getInt(
   9597                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   9598                     final boolean extendSelection = arguments.getBoolean(
   9599                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   9600                     return traverseAtGranularity(granularity, false, extendSelection);
   9601                 }
   9602             } break;
   9603             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
   9604                 CharSequence text = getIterableTextForAccessibility();
   9605                 if (text == null) {
   9606                     return false;
   9607                 }
   9608                 final int start = (arguments != null) ? arguments.getInt(
   9609                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
   9610                 final int end = (arguments != null) ? arguments.getInt(
   9611                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
   9612                 // Only cursor position can be specified (selection length == 0)
   9613                 if ((getAccessibilitySelectionStart() != start
   9614                         || getAccessibilitySelectionEnd() != end)
   9615                         && (start == end)) {
   9616                     setAccessibilitySelection(start, end);
   9617                     notifyViewAccessibilityStateChangedIfNeeded(
   9618                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9619                     return true;
   9620                 }
   9621             } break;
   9622             case R.id.accessibilityActionShowOnScreen: {
   9623                 if (mAttachInfo != null) {
   9624                     final Rect r = mAttachInfo.mTmpInvalRect;
   9625                     getDrawingRect(r);
   9626                     return requestRectangleOnScreen(r, true);
   9627                 }
   9628             } break;
   9629             case R.id.accessibilityActionContextClick: {
   9630                 if (isContextClickable()) {
   9631                     performContextClick();
   9632                     return true;
   9633                 }
   9634             } break;
   9635         }
   9636         return false;
   9637     }
   9638 
   9639     private boolean traverseAtGranularity(int granularity, boolean forward,
   9640             boolean extendSelection) {
   9641         CharSequence text = getIterableTextForAccessibility();
   9642         if (text == null || text.length() == 0) {
   9643             return false;
   9644         }
   9645         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
   9646         if (iterator == null) {
   9647             return false;
   9648         }
   9649         int current = getAccessibilitySelectionEnd();
   9650         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   9651             current = forward ? 0 : text.length();
   9652         }
   9653         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
   9654         if (range == null) {
   9655             return false;
   9656         }
   9657         final int segmentStart = range[0];
   9658         final int segmentEnd = range[1];
   9659         int selectionStart;
   9660         int selectionEnd;
   9661         if (extendSelection && isAccessibilitySelectionExtendable()) {
   9662             selectionStart = getAccessibilitySelectionStart();
   9663             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   9664                 selectionStart = forward ? segmentStart : segmentEnd;
   9665             }
   9666             selectionEnd = forward ? segmentEnd : segmentStart;
   9667         } else {
   9668             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
   9669         }
   9670         setAccessibilitySelection(selectionStart, selectionEnd);
   9671         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
   9672                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
   9673         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
   9674         return true;
   9675     }
   9676 
   9677     /**
   9678      * Gets the text reported for accessibility purposes.
   9679      *
   9680      * @return The accessibility text.
   9681      *
   9682      * @hide
   9683      */
   9684     public CharSequence getIterableTextForAccessibility() {
   9685         return getContentDescription();
   9686     }
   9687 
   9688     /**
   9689      * Gets whether accessibility selection can be extended.
   9690      *
   9691      * @return If selection is extensible.
   9692      *
   9693      * @hide
   9694      */
   9695     public boolean isAccessibilitySelectionExtendable() {
   9696         return false;
   9697     }
   9698 
   9699     /**
   9700      * @hide
   9701      */
   9702     public int getAccessibilitySelectionStart() {
   9703         return mAccessibilityCursorPosition;
   9704     }
   9705 
   9706     /**
   9707      * @hide
   9708      */
   9709     public int getAccessibilitySelectionEnd() {
   9710         return getAccessibilitySelectionStart();
   9711     }
   9712 
   9713     /**
   9714      * @hide
   9715      */
   9716     public void setAccessibilitySelection(int start, int end) {
   9717         if (start ==  end && end == mAccessibilityCursorPosition) {
   9718             return;
   9719         }
   9720         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
   9721             mAccessibilityCursorPosition = start;
   9722         } else {
   9723             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   9724         }
   9725         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
   9726     }
   9727 
   9728     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
   9729             int fromIndex, int toIndex) {
   9730         if (mParent == null) {
   9731             return;
   9732         }
   9733         AccessibilityEvent event = AccessibilityEvent.obtain(
   9734                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
   9735         onInitializeAccessibilityEvent(event);
   9736         onPopulateAccessibilityEvent(event);
   9737         event.setFromIndex(fromIndex);
   9738         event.setToIndex(toIndex);
   9739         event.setAction(action);
   9740         event.setMovementGranularity(granularity);
   9741         mParent.requestSendAccessibilityEvent(this, event);
   9742     }
   9743 
   9744     /**
   9745      * @hide
   9746      */
   9747     public TextSegmentIterator getIteratorForGranularity(int granularity) {
   9748         switch (granularity) {
   9749             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
   9750                 CharSequence text = getIterableTextForAccessibility();
   9751                 if (text != null && text.length() > 0) {
   9752                     CharacterTextSegmentIterator iterator =
   9753                         CharacterTextSegmentIterator.getInstance(
   9754                                 mContext.getResources().getConfiguration().locale);
   9755                     iterator.initialize(text.toString());
   9756                     return iterator;
   9757                 }
   9758             } break;
   9759             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
   9760                 CharSequence text = getIterableTextForAccessibility();
   9761                 if (text != null && text.length() > 0) {
   9762                     WordTextSegmentIterator iterator =
   9763                         WordTextSegmentIterator.getInstance(
   9764                                 mContext.getResources().getConfiguration().locale);
   9765                     iterator.initialize(text.toString());
   9766                     return iterator;
   9767                 }
   9768             } break;
   9769             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
   9770                 CharSequence text = getIterableTextForAccessibility();
   9771                 if (text != null && text.length() > 0) {
   9772                     ParagraphTextSegmentIterator iterator =
   9773                         ParagraphTextSegmentIterator.getInstance();
   9774                     iterator.initialize(text.toString());
   9775                     return iterator;
   9776                 }
   9777             } break;
   9778         }
   9779         return null;
   9780     }
   9781 
   9782     /**
   9783      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
   9784      * and {@link #onFinishTemporaryDetach()}.
   9785      */
   9786     public final boolean isTemporarilyDetached() {
   9787         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
   9788     }
   9789 
   9790     /**
   9791      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
   9792      * a container View.
   9793      */
   9794     @CallSuper
   9795     public void dispatchStartTemporaryDetach() {
   9796         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
   9797         onStartTemporaryDetach();
   9798     }
   9799 
   9800     /**
   9801      * This is called when a container is going to temporarily detach a child, with
   9802      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
   9803      * It will either be followed by {@link #onFinishTemporaryDetach()} or
   9804      * {@link #onDetachedFromWindow()} when the container is done.
   9805      */
   9806     public void onStartTemporaryDetach() {
   9807         removeUnsetPressCallback();
   9808         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   9809     }
   9810 
   9811     /**
   9812      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
   9813      * a container View.
   9814      */
   9815     @CallSuper
   9816     public void dispatchFinishTemporaryDetach() {
   9817         onFinishTemporaryDetach();
   9818         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
   9819     }
   9820 
   9821     /**
   9822      * Called after {@link #onStartTemporaryDetach} when the container is done
   9823      * changing the view.
   9824      */
   9825     public void onFinishTemporaryDetach() {
   9826     }
   9827 
   9828     /**
   9829      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
   9830      * for this view's window.  Returns null if the view is not currently attached
   9831      * to the window.  Normally you will not need to use this directly, but
   9832      * just use the standard high-level event callbacks like
   9833      * {@link #onKeyDown(int, KeyEvent)}.
   9834      */
   9835     public KeyEvent.DispatcherState getKeyDispatcherState() {
   9836         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
   9837     }
   9838 
   9839     /**
   9840      * Dispatch a key event before it is processed by any input method
   9841      * associated with the view hierarchy.  This can be used to intercept
   9842      * key events in special situations before the IME consumes them; a
   9843      * typical example would be handling the BACK key to update the application's
   9844      * UI instead of allowing the IME to see it and close itself.
   9845      *
   9846      * @param event The key event to be dispatched.
   9847      * @return True if the event was handled, false otherwise.
   9848      */
   9849     public boolean dispatchKeyEventPreIme(KeyEvent event) {
   9850         return onKeyPreIme(event.getKeyCode(), event);
   9851     }
   9852 
   9853     /**
   9854      * Dispatch a key event to the next view on the focus path. This path runs
   9855      * from the top of the view tree down to the currently focused view. If this
   9856      * view has focus, it will dispatch to itself. Otherwise it will dispatch
   9857      * the next node down the focus path. This method also fires any key
   9858      * listeners.
   9859      *
   9860      * @param event The key event to be dispatched.
   9861      * @return True if the event was handled, false otherwise.
   9862      */
   9863     public boolean dispatchKeyEvent(KeyEvent event) {
   9864         if (mInputEventConsistencyVerifier != null) {
   9865             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
   9866         }
   9867 
   9868         // Give any attached key listener a first crack at the event.
   9869         //noinspection SimplifiableIfStatement
   9870         ListenerInfo li = mListenerInfo;
   9871         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   9872                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
   9873             return true;
   9874         }
   9875 
   9876         if (event.dispatch(this, mAttachInfo != null
   9877                 ? mAttachInfo.mKeyDispatchState : null, this)) {
   9878             return true;
   9879         }
   9880 
   9881         if (mInputEventConsistencyVerifier != null) {
   9882             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   9883         }
   9884         return false;
   9885     }
   9886 
   9887     /**
   9888      * Dispatches a key shortcut event.
   9889      *
   9890      * @param event The key event to be dispatched.
   9891      * @return True if the event was handled by the view, false otherwise.
   9892      */
   9893     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   9894         return onKeyShortcut(event.getKeyCode(), event);
   9895     }
   9896 
   9897     /**
   9898      * Pass the touch screen motion event down to the target view, or this
   9899      * view if it is the target.
   9900      *
   9901      * @param event The motion event to be dispatched.
   9902      * @return True if the event was handled by the view, false otherwise.
   9903      */
   9904     public boolean dispatchTouchEvent(MotionEvent event) {
   9905         // If the event should be handled by accessibility focus first.
   9906         if (event.isTargetAccessibilityFocus()) {
   9907             // We don't have focus or no virtual descendant has it, do not handle the event.
   9908             if (!isAccessibilityFocusedViewOrHost()) {
   9909                 return false;
   9910             }
   9911             // We have focus and got the event, then use normal event dispatch.
   9912             event.setTargetAccessibilityFocus(false);
   9913         }
   9914 
   9915         boolean result = false;
   9916 
   9917         if (mInputEventConsistencyVerifier != null) {
   9918             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
   9919         }
   9920 
   9921         final int actionMasked = event.getActionMasked();
   9922         if (actionMasked == MotionEvent.ACTION_DOWN) {
   9923             // Defensive cleanup for new gesture
   9924             stopNestedScroll();
   9925         }
   9926 
   9927         if (onFilterTouchEventForSecurity(event)) {
   9928             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
   9929                 result = true;
   9930             }
   9931             //noinspection SimplifiableIfStatement
   9932             ListenerInfo li = mListenerInfo;
   9933             if (li != null && li.mOnTouchListener != null
   9934                     && (mViewFlags & ENABLED_MASK) == ENABLED
   9935                     && li.mOnTouchListener.onTouch(this, event)) {
   9936                 result = true;
   9937             }
   9938 
   9939             if (!result && onTouchEvent(event)) {
   9940                 result = true;
   9941             }
   9942         }
   9943 
   9944         if (!result && mInputEventConsistencyVerifier != null) {
   9945             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   9946         }
   9947 
   9948         // Clean up after nested scrolls if this is the end of a gesture;
   9949         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
   9950         // of the gesture.
   9951         if (actionMasked == MotionEvent.ACTION_UP ||
   9952                 actionMasked == MotionEvent.ACTION_CANCEL ||
   9953                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
   9954             stopNestedScroll();
   9955         }
   9956 
   9957         return result;
   9958     }
   9959 
   9960     boolean isAccessibilityFocusedViewOrHost() {
   9961         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
   9962                 .getAccessibilityFocusedHost() == this);
   9963     }
   9964 
   9965     /**
   9966      * Filter the touch event to apply security policies.
   9967      *
   9968      * @param event The motion event to be filtered.
   9969      * @return True if the event should be dispatched, false if the event should be dropped.
   9970      *
   9971      * @see #getFilterTouchesWhenObscured
   9972      */
   9973     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
   9974         //noinspection RedundantIfStatement
   9975         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
   9976                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
   9977             // Window is obscured, drop this touch.
   9978             return false;
   9979         }
   9980         return true;
   9981     }
   9982 
   9983     /**
   9984      * Pass a trackball motion event down to the focused view.
   9985      *
   9986      * @param event The motion event to be dispatched.
   9987      * @return True if the event was handled by the view, false otherwise.
   9988      */
   9989     public boolean dispatchTrackballEvent(MotionEvent event) {
   9990         if (mInputEventConsistencyVerifier != null) {
   9991             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
   9992         }
   9993 
   9994         return onTrackballEvent(event);
   9995     }
   9996 
   9997     /**
   9998      * Dispatch a generic motion event.
   9999      * <p>
   10000      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   10001      * are delivered to the view under the pointer.  All other generic motion events are
   10002      * delivered to the focused view.  Hover events are handled specially and are delivered
   10003      * to {@link #onHoverEvent(MotionEvent)}.
   10004      * </p>
   10005      *
   10006      * @param event The motion event to be dispatched.
   10007      * @return True if the event was handled by the view, false otherwise.
   10008      */
   10009     public boolean dispatchGenericMotionEvent(MotionEvent event) {
   10010         if (mInputEventConsistencyVerifier != null) {
   10011             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
   10012         }
   10013 
   10014         final int source = event.getSource();
   10015         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   10016             final int action = event.getAction();
   10017             if (action == MotionEvent.ACTION_HOVER_ENTER
   10018                     || action == MotionEvent.ACTION_HOVER_MOVE
   10019                     || action == MotionEvent.ACTION_HOVER_EXIT) {
   10020                 if (dispatchHoverEvent(event)) {
   10021                     return true;
   10022                 }
   10023             } else if (dispatchGenericPointerEvent(event)) {
   10024                 return true;
   10025             }
   10026         } else if (dispatchGenericFocusedEvent(event)) {
   10027             return true;
   10028         }
   10029 
   10030         if (dispatchGenericMotionEventInternal(event)) {
   10031             return true;
   10032         }
   10033 
   10034         if (mInputEventConsistencyVerifier != null) {
   10035             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   10036         }
   10037         return false;
   10038     }
   10039 
   10040     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
   10041         //noinspection SimplifiableIfStatement
   10042         ListenerInfo li = mListenerInfo;
   10043         if (li != null && li.mOnGenericMotionListener != null
   10044                 && (mViewFlags & ENABLED_MASK) == ENABLED
   10045                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
   10046             return true;
   10047         }
   10048 
   10049         if (onGenericMotionEvent(event)) {
   10050             return true;
   10051         }
   10052 
   10053         final int actionButton = event.getActionButton();
   10054         switch (event.getActionMasked()) {
   10055             case MotionEvent.ACTION_BUTTON_PRESS:
   10056                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
   10057                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   10058                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   10059                     if (performContextClick(event.getX(), event.getY())) {
   10060                         mInContextButtonPress = true;
   10061                         setPressed(true, event.getX(), event.getY());
   10062                         removeTapCallback();
   10063                         removeLongPressCallback();
   10064                         return true;
   10065                     }
   10066                 }
   10067                 break;
   10068 
   10069             case MotionEvent.ACTION_BUTTON_RELEASE:
   10070                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   10071                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   10072                     mInContextButtonPress = false;
   10073                     mIgnoreNextUpEvent = true;
   10074                 }
   10075                 break;
   10076         }
   10077 
   10078         if (mInputEventConsistencyVerifier != null) {
   10079             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   10080         }
   10081         return false;
   10082     }
   10083 
   10084     /**
   10085      * Dispatch a hover event.
   10086      * <p>
   10087      * Do not call this method directly.
   10088      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   10089      * </p>
   10090      *
   10091      * @param event The motion event to be dispatched.
   10092      * @return True if the event was handled by the view, false otherwise.
   10093      */
   10094     protected boolean dispatchHoverEvent(MotionEvent event) {
   10095         ListenerInfo li = mListenerInfo;
   10096         //noinspection SimplifiableIfStatement
   10097         if (li != null && li.mOnHoverListener != null
   10098                 && (mViewFlags & ENABLED_MASK) == ENABLED
   10099                 && li.mOnHoverListener.onHover(this, event)) {
   10100             return true;
   10101         }
   10102 
   10103         return onHoverEvent(event);
   10104     }
   10105 
   10106     /**
   10107      * Returns true if the view has a child to which it has recently sent
   10108      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
   10109      * it does not have a hovered child, then it must be the innermost hovered view.
   10110      * @hide
   10111      */
   10112     protected boolean hasHoveredChild() {
   10113         return false;
   10114     }
   10115 
   10116     /**
   10117      * Dispatch a generic motion event to the view under the first pointer.
   10118      * <p>
   10119      * Do not call this method directly.
   10120      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   10121      * </p>
   10122      *
   10123      * @param event The motion event to be dispatched.
   10124      * @return True if the event was handled by the view, false otherwise.
   10125      */
   10126     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
   10127         return false;
   10128     }
   10129 
   10130     /**
   10131      * Dispatch a generic motion event to the currently focused view.
   10132      * <p>
   10133      * Do not call this method directly.
   10134      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   10135      * </p>
   10136      *
   10137      * @param event The motion event to be dispatched.
   10138      * @return True if the event was handled by the view, false otherwise.
   10139      */
   10140     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
   10141         return false;
   10142     }
   10143 
   10144     /**
   10145      * Dispatch a pointer event.
   10146      * <p>
   10147      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
   10148      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
   10149      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
   10150      * and should not be expected to handle other pointing device features.
   10151      * </p>
   10152      *
   10153      * @param event The motion event to be dispatched.
   10154      * @return True if the event was handled by the view, false otherwise.
   10155      * @hide
   10156      */
   10157     public final boolean dispatchPointerEvent(MotionEvent event) {
   10158         if (event.isTouchEvent()) {
   10159             return dispatchTouchEvent(event);
   10160         } else {
   10161             return dispatchGenericMotionEvent(event);
   10162         }
   10163     }
   10164 
   10165     /**
   10166      * Called when the window containing this view gains or loses window focus.
   10167      * ViewGroups should override to route to their children.
   10168      *
   10169      * @param hasFocus True if the window containing this view now has focus,
   10170      *        false otherwise.
   10171      */
   10172     public void dispatchWindowFocusChanged(boolean hasFocus) {
   10173         onWindowFocusChanged(hasFocus);
   10174     }
   10175 
   10176     /**
   10177      * Called when the window containing this view gains or loses focus.  Note
   10178      * that this is separate from view focus: to receive key events, both
   10179      * your view and its window must have focus.  If a window is displayed
   10180      * on top of yours that takes input focus, then your own window will lose
   10181      * focus but the view focus will remain unchanged.
   10182      *
   10183      * @param hasWindowFocus True if the window containing this view now has
   10184      *        focus, false otherwise.
   10185      */
   10186     public void onWindowFocusChanged(boolean hasWindowFocus) {
   10187         InputMethodManager imm = InputMethodManager.peekInstance();
   10188         if (!hasWindowFocus) {
   10189             if (isPressed()) {
   10190                 setPressed(false);
   10191             }
   10192             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
   10193                 imm.focusOut(this);
   10194             }
   10195             removeLongPressCallback();
   10196             removeTapCallback();
   10197             onFocusLost();
   10198         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
   10199             imm.focusIn(this);
   10200         }
   10201         refreshDrawableState();
   10202     }
   10203 
   10204     /**
   10205      * Returns true if this view is in a window that currently has window focus.
   10206      * Note that this is not the same as the view itself having focus.
   10207      *
   10208      * @return True if this view is in a window that currently has window focus.
   10209      */
   10210     public boolean hasWindowFocus() {
   10211         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
   10212     }
   10213 
   10214     /**
   10215      * Dispatch a view visibility change down the view hierarchy.
   10216      * ViewGroups should override to route to their children.
   10217      * @param changedView The view whose visibility changed. Could be 'this' or
   10218      * an ancestor view.
   10219      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   10220      * {@link #INVISIBLE} or {@link #GONE}.
   10221      */
   10222     protected void dispatchVisibilityChanged(@NonNull View changedView,
   10223             @Visibility int visibility) {
   10224         onVisibilityChanged(changedView, visibility);
   10225     }
   10226 
   10227     /**
   10228      * Called when the visibility of the view or an ancestor of the view has
   10229      * changed.
   10230      *
   10231      * @param changedView The view whose visibility changed. May be
   10232      *                    {@code this} or an ancestor view.
   10233      * @param visibility The new visibility, one of {@link #VISIBLE},
   10234      *                   {@link #INVISIBLE} or {@link #GONE}.
   10235      */
   10236     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
   10237     }
   10238 
   10239     /**
   10240      * Dispatch a hint about whether this view is displayed. For instance, when
   10241      * a View moves out of the screen, it might receives a display hint indicating
   10242      * the view is not displayed. Applications should not <em>rely</em> on this hint
   10243      * as there is no guarantee that they will receive one.
   10244      *
   10245      * @param hint A hint about whether or not this view is displayed:
   10246      * {@link #VISIBLE} or {@link #INVISIBLE}.
   10247      */
   10248     public void dispatchDisplayHint(@Visibility int hint) {
   10249         onDisplayHint(hint);
   10250     }
   10251 
   10252     /**
   10253      * Gives this view a hint about whether is displayed or not. For instance, when
   10254      * a View moves out of the screen, it might receives a display hint indicating
   10255      * the view is not displayed. Applications should not <em>rely</em> on this hint
   10256      * as there is no guarantee that they will receive one.
   10257      *
   10258      * @param hint A hint about whether or not this view is displayed:
   10259      * {@link #VISIBLE} or {@link #INVISIBLE}.
   10260      */
   10261     protected void onDisplayHint(@Visibility int hint) {
   10262     }
   10263 
   10264     /**
   10265      * Dispatch a window visibility change down the view hierarchy.
   10266      * ViewGroups should override to route to their children.
   10267      *
   10268      * @param visibility The new visibility of the window.
   10269      *
   10270      * @see #onWindowVisibilityChanged(int)
   10271      */
   10272     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
   10273         onWindowVisibilityChanged(visibility);
   10274     }
   10275 
   10276     /**
   10277      * Called when the window containing has change its visibility
   10278      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
   10279      * that this tells you whether or not your window is being made visible
   10280      * to the window manager; this does <em>not</em> tell you whether or not
   10281      * your window is obscured by other windows on the screen, even if it
   10282      * is itself visible.
   10283      *
   10284      * @param visibility The new visibility of the window.
   10285      */
   10286     protected void onWindowVisibilityChanged(@Visibility int visibility) {
   10287         if (visibility == VISIBLE) {
   10288             initialAwakenScrollBars();
   10289         }
   10290     }
   10291 
   10292     /**
   10293      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
   10294      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
   10295      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
   10296      *
   10297      * @param isVisible true if this view's visibility to the user is uninterrupted by its
   10298      *                  ancestors or by window visibility
   10299      * @return true if this view is visible to the user, not counting clipping or overlapping
   10300      */
   10301     @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
   10302         final boolean thisVisible = getVisibility() == VISIBLE;
   10303         // If we're not visible but something is telling us we are, ignore it.
   10304         if (thisVisible || !isVisible) {
   10305             onVisibilityAggregated(isVisible);
   10306         }
   10307         return thisVisible && isVisible;
   10308     }
   10309 
   10310     /**
   10311      * Called when the user-visibility of this View is potentially affected by a change
   10312      * to this view itself, an ancestor view or the window this view is attached to.
   10313      *
   10314      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
   10315      *                  and this view's window is also visible
   10316      */
   10317     @CallSuper
   10318     public void onVisibilityAggregated(boolean isVisible) {
   10319         if (isVisible && mAttachInfo != null) {
   10320             initialAwakenScrollBars();
   10321         }
   10322 
   10323         final Drawable dr = mBackground;
   10324         if (dr != null && isVisible != dr.isVisible()) {
   10325             dr.setVisible(isVisible, false);
   10326         }
   10327         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   10328         if (fg != null && isVisible != fg.isVisible()) {
   10329             fg.setVisible(isVisible, false);
   10330         }
   10331     }
   10332 
   10333     /**
   10334      * Returns the current visibility of the window this view is attached to
   10335      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
   10336      *
   10337      * @return Returns the current visibility of the view's window.
   10338      */
   10339     @Visibility
   10340     public int getWindowVisibility() {
   10341         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
   10342     }
   10343 
   10344     /**
   10345      * Retrieve the overall visible display size in which the window this view is
   10346      * attached to has been positioned in.  This takes into account screen
   10347      * decorations above the window, for both cases where the window itself
   10348      * is being position inside of them or the window is being placed under
   10349      * then and covered insets are used for the window to position its content
   10350      * inside.  In effect, this tells you the available area where content can
   10351      * be placed and remain visible to users.
   10352      *
   10353      * <p>This function requires an IPC back to the window manager to retrieve
   10354      * the requested information, so should not be used in performance critical
   10355      * code like drawing.
   10356      *
   10357      * @param outRect Filled in with the visible display frame.  If the view
   10358      * is not attached to a window, this is simply the raw display size.
   10359      */
   10360     public void getWindowVisibleDisplayFrame(Rect outRect) {
   10361         if (mAttachInfo != null) {
   10362             try {
   10363                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   10364             } catch (RemoteException e) {
   10365                 return;
   10366             }
   10367             // XXX This is really broken, and probably all needs to be done
   10368             // in the window manager, and we need to know more about whether
   10369             // we want the area behind or in front of the IME.
   10370             final Rect insets = mAttachInfo.mVisibleInsets;
   10371             outRect.left += insets.left;
   10372             outRect.top += insets.top;
   10373             outRect.right -= insets.right;
   10374             outRect.bottom -= insets.bottom;
   10375             return;
   10376         }
   10377         // The view is not attached to a display so we don't have a context.
   10378         // Make a best guess about the display size.
   10379         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   10380         d.getRectSize(outRect);
   10381     }
   10382 
   10383     /**
   10384      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
   10385      * is currently in without any insets.
   10386      *
   10387      * @hide
   10388      */
   10389     public void getWindowDisplayFrame(Rect outRect) {
   10390         if (mAttachInfo != null) {
   10391             try {
   10392                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   10393             } catch (RemoteException e) {
   10394                 return;
   10395             }
   10396             return;
   10397         }
   10398         // The view is not attached to a display so we don't have a context.
   10399         // Make a best guess about the display size.
   10400         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   10401         d.getRectSize(outRect);
   10402     }
   10403 
   10404     /**
   10405      * Dispatch a notification about a resource configuration change down
   10406      * the view hierarchy.
   10407      * ViewGroups should override to route to their children.
   10408      *
   10409      * @param newConfig The new resource configuration.
   10410      *
   10411      * @see #onConfigurationChanged(android.content.res.Configuration)
   10412      */
   10413     public void dispatchConfigurationChanged(Configuration newConfig) {
   10414         onConfigurationChanged(newConfig);
   10415     }
   10416 
   10417     /**
   10418      * Called when the current configuration of the resources being used
   10419      * by the application have changed.  You can use this to decide when
   10420      * to reload resources that can changed based on orientation and other
   10421      * configuration characteristics.  You only need to use this if you are
   10422      * not relying on the normal {@link android.app.Activity} mechanism of
   10423      * recreating the activity instance upon a configuration change.
   10424      *
   10425      * @param newConfig The new resource configuration.
   10426      */
   10427     protected void onConfigurationChanged(Configuration newConfig) {
   10428     }
   10429 
   10430     /**
   10431      * Private function to aggregate all per-view attributes in to the view
   10432      * root.
   10433      */
   10434     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   10435         performCollectViewAttributes(attachInfo, visibility);
   10436     }
   10437 
   10438     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   10439         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
   10440             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
   10441                 attachInfo.mKeepScreenOn = true;
   10442             }
   10443             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
   10444             ListenerInfo li = mListenerInfo;
   10445             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   10446                 attachInfo.mHasSystemUiListeners = true;
   10447             }
   10448         }
   10449     }
   10450 
   10451     void needGlobalAttributesUpdate(boolean force) {
   10452         final AttachInfo ai = mAttachInfo;
   10453         if (ai != null && !ai.mRecomputeGlobalAttributes) {
   10454             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
   10455                     || ai.mHasSystemUiListeners) {
   10456                 ai.mRecomputeGlobalAttributes = true;
   10457             }
   10458         }
   10459     }
   10460 
   10461     /**
   10462      * Returns whether the device is currently in touch mode.  Touch mode is entered
   10463      * once the user begins interacting with the device by touch, and affects various
   10464      * things like whether focus is always visible to the user.
   10465      *
   10466      * @return Whether the device is in touch mode.
   10467      */
   10468     @ViewDebug.ExportedProperty
   10469     public boolean isInTouchMode() {
   10470         if (mAttachInfo != null) {
   10471             return mAttachInfo.mInTouchMode;
   10472         } else {
   10473             return ViewRootImpl.isInTouchMode();
   10474         }
   10475     }
   10476 
   10477     /**
   10478      * Returns the context the view is running in, through which it can
   10479      * access the current theme, resources, etc.
   10480      *
   10481      * @return The view's Context.
   10482      */
   10483     @ViewDebug.CapturedViewProperty
   10484     public final Context getContext() {
   10485         return mContext;
   10486     }
   10487 
   10488     /**
   10489      * Handle a key event before it is processed by any input method
   10490      * associated with the view hierarchy.  This can be used to intercept
   10491      * key events in special situations before the IME consumes them; a
   10492      * typical example would be handling the BACK key to update the application's
   10493      * UI instead of allowing the IME to see it and close itself.
   10494      *
   10495      * @param keyCode The value in event.getKeyCode().
   10496      * @param event Description of the key event.
   10497      * @return If you handled the event, return true. If you want to allow the
   10498      *         event to be handled by the next receiver, return false.
   10499      */
   10500     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
   10501         return false;
   10502     }
   10503 
   10504     /**
   10505      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
   10506      * KeyEvent.Callback.onKeyDown()}: perform press of the view
   10507      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
   10508      * is released, if the view is enabled and clickable.
   10509      * <p>
   10510      * Key presses in software keyboards will generally NOT trigger this
   10511      * listener, although some may elect to do so in some situations. Do not
   10512      * rely on this to catch software key presses.
   10513      *
   10514      * @param keyCode a key code that represents the button pressed, from
   10515      *                {@link android.view.KeyEvent}
   10516      * @param event the KeyEvent object that defines the button action
   10517      */
   10518     public boolean onKeyDown(int keyCode, KeyEvent event) {
   10519         if (KeyEvent.isConfirmKey(keyCode)) {
   10520             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   10521                 return true;
   10522             }
   10523 
   10524             // Long clickable items don't necessarily have to be clickable.
   10525             if (((mViewFlags & CLICKABLE) == CLICKABLE
   10526                     || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   10527                     && (event.getRepeatCount() == 0)) {
   10528                 // For the purposes of menu anchoring and drawable hotspots,
   10529                 // key events are considered to be at the center of the view.
   10530                 final float x = getWidth() / 2f;
   10531                 final float y = getHeight() / 2f;
   10532                 setPressed(true, x, y);
   10533                 checkForLongClick(0, x, y);
   10534                 return true;
   10535             }
   10536         }
   10537 
   10538         return false;
   10539     }
   10540 
   10541     /**
   10542      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
   10543      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
   10544      * the event).
   10545      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   10546      * although some may elect to do so in some situations. Do not rely on this to
   10547      * catch software key presses.
   10548      */
   10549     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
   10550         return false;
   10551     }
   10552 
   10553     /**
   10554      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
   10555      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
   10556      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
   10557      * or {@link KeyEvent#KEYCODE_SPACE} is released.
   10558      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   10559      * although some may elect to do so in some situations. Do not rely on this to
   10560      * catch software key presses.
   10561      *
   10562      * @param keyCode A key code that represents the button pressed, from
   10563      *                {@link android.view.KeyEvent}.
   10564      * @param event   The KeyEvent object that defines the button action.
   10565      */
   10566     public boolean onKeyUp(int keyCode, KeyEvent event) {
   10567         if (KeyEvent.isConfirmKey(keyCode)) {
   10568             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   10569                 return true;
   10570             }
   10571             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
   10572                 setPressed(false);
   10573 
   10574                 if (!mHasPerformedLongPress) {
   10575                     // This is a tap, so remove the longpress check
   10576                     removeLongPressCallback();
   10577                     return performClick();
   10578                 }
   10579             }
   10580         }
   10581         return false;
   10582     }
   10583 
   10584     /**
   10585      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   10586      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
   10587      * the event).
   10588      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   10589      * although some may elect to do so in some situations. Do not rely on this to
   10590      * catch software key presses.
   10591      *
   10592      * @param keyCode     A key code that represents the button pressed, from
   10593      *                    {@link android.view.KeyEvent}.
   10594      * @param repeatCount The number of times the action was made.
   10595      * @param event       The KeyEvent object that defines the button action.
   10596      */
   10597     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
   10598         return false;
   10599     }
   10600 
   10601     /**
   10602      * Called on the focused view when a key shortcut event is not handled.
   10603      * Override this method to implement local key shortcuts for the View.
   10604      * Key shortcuts can also be implemented by setting the
   10605      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
   10606      *
   10607      * @param keyCode The value in event.getKeyCode().
   10608      * @param event Description of the key event.
   10609      * @return If you handled the event, return true. If you want to allow the
   10610      *         event to be handled by the next receiver, return false.
   10611      */
   10612     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
   10613         return false;
   10614     }
   10615 
   10616     /**
   10617      * Check whether the called view is a text editor, in which case it
   10618      * would make sense to automatically display a soft input window for
   10619      * it.  Subclasses should override this if they implement
   10620      * {@link #onCreateInputConnection(EditorInfo)} to return true if
   10621      * a call on that method would return a non-null InputConnection, and
   10622      * they are really a first-class editor that the user would normally
   10623      * start typing on when the go into a window containing your view.
   10624      *
   10625      * <p>The default implementation always returns false.  This does
   10626      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
   10627      * will not be called or the user can not otherwise perform edits on your
   10628      * view; it is just a hint to the system that this is not the primary
   10629      * purpose of this view.
   10630      *
   10631      * @return Returns true if this view is a text editor, else false.
   10632      */
   10633     public boolean onCheckIsTextEditor() {
   10634         return false;
   10635     }
   10636 
   10637     /**
   10638      * Create a new InputConnection for an InputMethod to interact
   10639      * with the view.  The default implementation returns null, since it doesn't
   10640      * support input methods.  You can override this to implement such support.
   10641      * This is only needed for views that take focus and text input.
   10642      *
   10643      * <p>When implementing this, you probably also want to implement
   10644      * {@link #onCheckIsTextEditor()} to indicate you will return a
   10645      * non-null InputConnection.</p>
   10646      *
   10647      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
   10648      * object correctly and in its entirety, so that the connected IME can rely
   10649      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
   10650      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
   10651      * must be filled in with the correct cursor position for IMEs to work correctly
   10652      * with your application.</p>
   10653      *
   10654      * @param outAttrs Fill in with attribute information about the connection.
   10655      */
   10656     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   10657         return null;
   10658     }
   10659 
   10660     /**
   10661      * Called by the {@link android.view.inputmethod.InputMethodManager}
   10662      * when a view who is not the current
   10663      * input connection target is trying to make a call on the manager.  The
   10664      * default implementation returns false; you can override this to return
   10665      * true for certain views if you are performing InputConnection proxying
   10666      * to them.
   10667      * @param view The View that is making the InputMethodManager call.
   10668      * @return Return true to allow the call, false to reject.
   10669      */
   10670     public boolean checkInputConnectionProxy(View view) {
   10671         return false;
   10672     }
   10673 
   10674     /**
   10675      * Show the context menu for this view. It is not safe to hold on to the
   10676      * menu after returning from this method.
   10677      *
   10678      * You should normally not overload this method. Overload
   10679      * {@link #onCreateContextMenu(ContextMenu)} or define an
   10680      * {@link OnCreateContextMenuListener} to add items to the context menu.
   10681      *
   10682      * @param menu The context menu to populate
   10683      */
   10684     public void createContextMenu(ContextMenu menu) {
   10685         ContextMenuInfo menuInfo = getContextMenuInfo();
   10686 
   10687         // Sets the current menu info so all items added to menu will have
   10688         // my extra info set.
   10689         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
   10690 
   10691         onCreateContextMenu(menu);
   10692         ListenerInfo li = mListenerInfo;
   10693         if (li != null && li.mOnCreateContextMenuListener != null) {
   10694             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
   10695         }
   10696 
   10697         // Clear the extra information so subsequent items that aren't mine don't
   10698         // have my extra info.
   10699         ((MenuBuilder)menu).setCurrentMenuInfo(null);
   10700 
   10701         if (mParent != null) {
   10702             mParent.createContextMenu(menu);
   10703         }
   10704     }
   10705 
   10706     /**
   10707      * Views should implement this if they have extra information to associate
   10708      * with the context menu. The return result is supplied as a parameter to
   10709      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
   10710      * callback.
   10711      *
   10712      * @return Extra information about the item for which the context menu
   10713      *         should be shown. This information will vary across different
   10714      *         subclasses of View.
   10715      */
   10716     protected ContextMenuInfo getContextMenuInfo() {
   10717         return null;
   10718     }
   10719 
   10720     /**
   10721      * Views should implement this if the view itself is going to add items to
   10722      * the context menu.
   10723      *
   10724      * @param menu the context menu to populate
   10725      */
   10726     protected void onCreateContextMenu(ContextMenu menu) {
   10727     }
   10728 
   10729     /**
   10730      * Implement this method to handle trackball motion events.  The
   10731      * <em>relative</em> movement of the trackball since the last event
   10732      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
   10733      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
   10734      * that a movement of 1 corresponds to the user pressing one DPAD key (so
   10735      * they will often be fractional values, representing the more fine-grained
   10736      * movement information available from a trackball).
   10737      *
   10738      * @param event The motion event.
   10739      * @return True if the event was handled, false otherwise.
   10740      */
   10741     public boolean onTrackballEvent(MotionEvent event) {
   10742         return false;
   10743     }
   10744 
   10745     /**
   10746      * Implement this method to handle generic motion events.
   10747      * <p>
   10748      * Generic motion events describe joystick movements, mouse hovers, track pad
   10749      * touches, scroll wheel movements and other input events.  The
   10750      * {@link MotionEvent#getSource() source} of the motion event specifies
   10751      * the class of input that was received.  Implementations of this method
   10752      * must examine the bits in the source before processing the event.
   10753      * The following code example shows how this is done.
   10754      * </p><p>
   10755      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   10756      * are delivered to the view under the pointer.  All other generic motion events are
   10757      * delivered to the focused view.
   10758      * </p>
   10759      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
   10760      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
   10761      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
   10762      *             // process the joystick movement...
   10763      *             return true;
   10764      *         }
   10765      *     }
   10766      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
   10767      *         switch (event.getAction()) {
   10768      *             case MotionEvent.ACTION_HOVER_MOVE:
   10769      *                 // process the mouse hover movement...
   10770      *                 return true;
   10771      *             case MotionEvent.ACTION_SCROLL:
   10772      *                 // process the scroll wheel movement...
   10773      *                 return true;
   10774      *         }
   10775      *     }
   10776      *     return super.onGenericMotionEvent(event);
   10777      * }</pre>
   10778      *
   10779      * @param event The generic motion event being processed.
   10780      * @return True if the event was handled, false otherwise.
   10781      */
   10782     public boolean onGenericMotionEvent(MotionEvent event) {
   10783         return false;
   10784     }
   10785 
   10786     /**
   10787      * Implement this method to handle hover events.
   10788      * <p>
   10789      * This method is called whenever a pointer is hovering into, over, or out of the
   10790      * bounds of a view and the view is not currently being touched.
   10791      * Hover events are represented as pointer events with action
   10792      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
   10793      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
   10794      * </p>
   10795      * <ul>
   10796      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
   10797      * when the pointer enters the bounds of the view.</li>
   10798      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
   10799      * when the pointer has already entered the bounds of the view and has moved.</li>
   10800      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
   10801      * when the pointer has exited the bounds of the view or when the pointer is
   10802      * about to go down due to a button click, tap, or similar user action that
   10803      * causes the view to be touched.</li>
   10804      * </ul>
   10805      * <p>
   10806      * The view should implement this method to return true to indicate that it is
   10807      * handling the hover event, such as by changing its drawable state.
   10808      * </p><p>
   10809      * The default implementation calls {@link #setHovered} to update the hovered state
   10810      * of the view when a hover enter or hover exit event is received, if the view
   10811      * is enabled and is clickable.  The default implementation also sends hover
   10812      * accessibility events.
   10813      * </p>
   10814      *
   10815      * @param event The motion event that describes the hover.
   10816      * @return True if the view handled the hover event.
   10817      *
   10818      * @see #isHovered
   10819      * @see #setHovered
   10820      * @see #onHoverChanged
   10821      */
   10822     public boolean onHoverEvent(MotionEvent event) {
   10823         // The root view may receive hover (or touch) events that are outside the bounds of
   10824         // the window.  This code ensures that we only send accessibility events for
   10825         // hovers that are actually within the bounds of the root view.
   10826         final int action = event.getActionMasked();
   10827         if (!mSendingHoverAccessibilityEvents) {
   10828             if ((action == MotionEvent.ACTION_HOVER_ENTER
   10829                     || action == MotionEvent.ACTION_HOVER_MOVE)
   10830                     && !hasHoveredChild()
   10831                     && pointInView(event.getX(), event.getY())) {
   10832                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
   10833                 mSendingHoverAccessibilityEvents = true;
   10834             }
   10835         } else {
   10836             if (action == MotionEvent.ACTION_HOVER_EXIT
   10837                     || (action == MotionEvent.ACTION_MOVE
   10838                             && !pointInView(event.getX(), event.getY()))) {
   10839                 mSendingHoverAccessibilityEvents = false;
   10840                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
   10841             }
   10842         }
   10843 
   10844         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
   10845                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
   10846                 && isOnScrollbar(event.getX(), event.getY())) {
   10847             awakenScrollBars();
   10848         }
   10849         if (isHoverable()) {
   10850             switch (action) {
   10851                 case MotionEvent.ACTION_HOVER_ENTER:
   10852                     setHovered(true);
   10853                     break;
   10854                 case MotionEvent.ACTION_HOVER_EXIT:
   10855                     setHovered(false);
   10856                     break;
   10857             }
   10858 
   10859             // Dispatch the event to onGenericMotionEvent before returning true.
   10860             // This is to provide compatibility with existing applications that
   10861             // handled HOVER_MOVE events in onGenericMotionEvent and that would
   10862             // break because of the new default handling for hoverable views
   10863             // in onHoverEvent.
   10864             // Note that onGenericMotionEvent will be called by default when
   10865             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
   10866             dispatchGenericMotionEventInternal(event);
   10867             // The event was already handled by calling setHovered(), so always
   10868             // return true.
   10869             return true;
   10870         }
   10871 
   10872         return false;
   10873     }
   10874 
   10875     /**
   10876      * Returns true if the view should handle {@link #onHoverEvent}
   10877      * by calling {@link #setHovered} to change its hovered state.
   10878      *
   10879      * @return True if the view is hoverable.
   10880      */
   10881     private boolean isHoverable() {
   10882         final int viewFlags = mViewFlags;
   10883         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   10884             return false;
   10885         }
   10886 
   10887         return (viewFlags & CLICKABLE) == CLICKABLE
   10888                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   10889                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   10890     }
   10891 
   10892     /**
   10893      * Returns true if the view is currently hovered.
   10894      *
   10895      * @return True if the view is currently hovered.
   10896      *
   10897      * @see #setHovered
   10898      * @see #onHoverChanged
   10899      */
   10900     @ViewDebug.ExportedProperty
   10901     public boolean isHovered() {
   10902         return (mPrivateFlags & PFLAG_HOVERED) != 0;
   10903     }
   10904 
   10905     /**
   10906      * Sets whether the view is currently hovered.
   10907      * <p>
   10908      * Calling this method also changes the drawable state of the view.  This
   10909      * enables the view to react to hover by using different drawable resources
   10910      * to change its appearance.
   10911      * </p><p>
   10912      * The {@link #onHoverChanged} method is called when the hovered state changes.
   10913      * </p>
   10914      *
   10915      * @param hovered True if the view is hovered.
   10916      *
   10917      * @see #isHovered
   10918      * @see #onHoverChanged
   10919      */
   10920     public void setHovered(boolean hovered) {
   10921         if (hovered) {
   10922             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
   10923                 mPrivateFlags |= PFLAG_HOVERED;
   10924                 refreshDrawableState();
   10925                 onHoverChanged(true);
   10926             }
   10927         } else {
   10928             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
   10929                 mPrivateFlags &= ~PFLAG_HOVERED;
   10930                 refreshDrawableState();
   10931                 onHoverChanged(false);
   10932             }
   10933         }
   10934     }
   10935 
   10936     /**
   10937      * Implement this method to handle hover state changes.
   10938      * <p>
   10939      * This method is called whenever the hover state changes as a result of a
   10940      * call to {@link #setHovered}.
   10941      * </p>
   10942      *
   10943      * @param hovered The current hover state, as returned by {@link #isHovered}.
   10944      *
   10945      * @see #isHovered
   10946      * @see #setHovered
   10947      */
   10948     public void onHoverChanged(boolean hovered) {
   10949     }
   10950 
   10951     /**
   10952      * Handles scroll bar dragging by mouse input.
   10953      *
   10954      * @hide
   10955      * @param event The motion event.
   10956      *
   10957      * @return true if the event was handled as a scroll bar dragging, false otherwise.
   10958      */
   10959     protected boolean handleScrollBarDragging(MotionEvent event) {
   10960         if (mScrollCache == null) {
   10961             return false;
   10962         }
   10963         final float x = event.getX();
   10964         final float y = event.getY();
   10965         final int action = event.getAction();
   10966         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
   10967                 && action != MotionEvent.ACTION_DOWN)
   10968                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
   10969                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
   10970             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
   10971             return false;
   10972         }
   10973 
   10974         switch (action) {
   10975             case MotionEvent.ACTION_MOVE:
   10976                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
   10977                     return false;
   10978                 }
   10979                 if (mScrollCache.mScrollBarDraggingState
   10980                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
   10981                     final Rect bounds = mScrollCache.mScrollBarBounds;
   10982                     getVerticalScrollBarBounds(bounds);
   10983                     final int range = computeVerticalScrollRange();
   10984                     final int offset = computeVerticalScrollOffset();
   10985                     final int extent = computeVerticalScrollExtent();
   10986 
   10987                     final int thumbLength = ScrollBarUtils.getThumbLength(
   10988                             bounds.height(), bounds.width(), extent, range);
   10989                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
   10990                             bounds.height(), thumbLength, extent, range, offset);
   10991 
   10992                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
   10993                     final float maxThumbOffset = bounds.height() - thumbLength;
   10994                     final float newThumbOffset =
   10995                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
   10996                     final int height = getHeight();
   10997                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
   10998                             && height > 0 && extent > 0) {
   10999                         final int newY = Math.round((range - extent)
   11000                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
   11001                         if (newY != getScrollY()) {
   11002                             mScrollCache.mScrollBarDraggingPos = y;
   11003                             setScrollY(newY);
   11004                         }
   11005                     }
   11006                     return true;
   11007                 }
   11008                 if (mScrollCache.mScrollBarDraggingState
   11009                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
   11010                     final Rect bounds = mScrollCache.mScrollBarBounds;
   11011                     getHorizontalScrollBarBounds(bounds);
   11012                     final int range = computeHorizontalScrollRange();
   11013                     final int offset = computeHorizontalScrollOffset();
   11014                     final int extent = computeHorizontalScrollExtent();
   11015 
   11016                     final int thumbLength = ScrollBarUtils.getThumbLength(
   11017                             bounds.width(), bounds.height(), extent, range);
   11018                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
   11019                             bounds.width(), thumbLength, extent, range, offset);
   11020 
   11021                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
   11022                     final float maxThumbOffset = bounds.width() - thumbLength;
   11023                     final float newThumbOffset =
   11024                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
   11025                     final int width = getWidth();
   11026                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
   11027                             && width > 0 && extent > 0) {
   11028                         final int newX = Math.round((range - extent)
   11029                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
   11030                         if (newX != getScrollX()) {
   11031                             mScrollCache.mScrollBarDraggingPos = x;
   11032                             setScrollX(newX);
   11033                         }
   11034                     }
   11035                     return true;
   11036                 }
   11037             case MotionEvent.ACTION_DOWN:
   11038                 if (mScrollCache.state == ScrollabilityCache.OFF) {
   11039                     return false;
   11040                 }
   11041                 if (isOnVerticalScrollbarThumb(x, y)) {
   11042                     mScrollCache.mScrollBarDraggingState =
   11043                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
   11044                     mScrollCache.mScrollBarDraggingPos = y;
   11045                     return true;
   11046                 }
   11047                 if (isOnHorizontalScrollbarThumb(x, y)) {
   11048                     mScrollCache.mScrollBarDraggingState =
   11049                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
   11050                     mScrollCache.mScrollBarDraggingPos = x;
   11051                     return true;
   11052                 }
   11053         }
   11054         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
   11055         return false;
   11056     }
   11057 
   11058     /**
   11059      * Implement this method to handle touch screen motion events.
   11060      * <p>
   11061      * If this method is used to detect click actions, it is recommended that
   11062      * the actions be performed by implementing and calling
   11063      * {@link #performClick()}. This will ensure consistent system behavior,
   11064      * including:
   11065      * <ul>
   11066      * <li>obeying click sound preferences
   11067      * <li>dispatching OnClickListener calls
   11068      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
   11069      * accessibility features are enabled
   11070      * </ul>
   11071      *
   11072      * @param event The motion event.
   11073      * @return True if the event was handled, false otherwise.
   11074      */
   11075     public boolean onTouchEvent(MotionEvent event) {
   11076         final float x = event.getX();
   11077         final float y = event.getY();
   11078         final int viewFlags = mViewFlags;
   11079         final int action = event.getAction();
   11080 
   11081         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   11082             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
   11083                 setPressed(false);
   11084             }
   11085             // A disabled view that is clickable still consumes the touch
   11086             // events, it just doesn't respond to them.
   11087             return (((viewFlags & CLICKABLE) == CLICKABLE
   11088                     || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   11089                     || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
   11090         }
   11091         if (mTouchDelegate != null) {
   11092             if (mTouchDelegate.onTouchEvent(event)) {
   11093                 return true;
   11094             }
   11095         }
   11096 
   11097         if (((viewFlags & CLICKABLE) == CLICKABLE ||
   11098                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
   11099                 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
   11100             switch (action) {
   11101                 case MotionEvent.ACTION_UP:
   11102                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
   11103                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
   11104                         // take focus if we don't have it already and we should in
   11105                         // touch mode.
   11106                         boolean focusTaken = false;
   11107                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
   11108                             focusTaken = requestFocus();
   11109                         }
   11110 
   11111                         if (prepressed) {
   11112                             // The button is being released before we actually
   11113                             // showed it as pressed.  Make it show the pressed
   11114                             // state now (before scheduling the click) to ensure
   11115                             // the user sees it.
   11116                             setPressed(true, x, y);
   11117                        }
   11118 
   11119                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
   11120                             // This is a tap, so remove the longpress check
   11121                             removeLongPressCallback();
   11122 
   11123                             // Only perform take click actions if we were in the pressed state
   11124                             if (!focusTaken) {
   11125                                 // Use a Runnable and post this rather than calling
   11126                                 // performClick directly. This lets other visual state
   11127                                 // of the view update before click actions start.
   11128                                 if (mPerformClick == null) {
   11129                                     mPerformClick = new PerformClick();
   11130                                 }
   11131                                 if (!post(mPerformClick)) {
   11132                                     performClick();
   11133                                 }
   11134                             }
   11135                         }
   11136 
   11137                         if (mUnsetPressedState == null) {
   11138                             mUnsetPressedState = new UnsetPressedState();
   11139                         }
   11140 
   11141                         if (prepressed) {
   11142                             postDelayed(mUnsetPressedState,
   11143                                     ViewConfiguration.getPressedStateDuration());
   11144                         } else if (!post(mUnsetPressedState)) {
   11145                             // If the post failed, unpress right now
   11146                             mUnsetPressedState.run();
   11147                         }
   11148 
   11149                         removeTapCallback();
   11150                     }
   11151                     mIgnoreNextUpEvent = false;
   11152                     break;
   11153 
   11154                 case MotionEvent.ACTION_DOWN:
   11155                     mHasPerformedLongPress = false;
   11156 
   11157                     if (performButtonActionOnTouchDown(event)) {
   11158                         break;
   11159                     }
   11160 
   11161                     // Walk up the hierarchy to determine if we're inside a scrolling container.
   11162                     boolean isInScrollingContainer = isInScrollingContainer();
   11163 
   11164                     // For views inside a scrolling container, delay the pressed feedback for
   11165                     // a short period in case this is a scroll.
   11166                     if (isInScrollingContainer) {
   11167                         mPrivateFlags |= PFLAG_PREPRESSED;
   11168                         if (mPendingCheckForTap == null) {
   11169                             mPendingCheckForTap = new CheckForTap();
   11170                         }
   11171                         mPendingCheckForTap.x = event.getX();
   11172                         mPendingCheckForTap.y = event.getY();
   11173                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
   11174                     } else {
   11175                         // Not inside a scrolling container, so show the feedback right away
   11176                         setPressed(true, x, y);
   11177                         checkForLongClick(0, x, y);
   11178                     }
   11179                     break;
   11180 
   11181                 case MotionEvent.ACTION_CANCEL:
   11182                     setPressed(false);
   11183                     removeTapCallback();
   11184                     removeLongPressCallback();
   11185                     mInContextButtonPress = false;
   11186                     mHasPerformedLongPress = false;
   11187                     mIgnoreNextUpEvent = false;
   11188                     break;
   11189 
   11190                 case MotionEvent.ACTION_MOVE:
   11191                     drawableHotspotChanged(x, y);
   11192 
   11193                     // Be lenient about moving outside of buttons
   11194                     if (!pointInView(x, y, mTouchSlop)) {
   11195                         // Outside button
   11196                         removeTapCallback();
   11197                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
   11198                             // Remove any future long press/tap checks
   11199                             removeLongPressCallback();
   11200 
   11201                             setPressed(false);
   11202                         }
   11203                     }
   11204                     break;
   11205             }
   11206 
   11207             return true;
   11208         }
   11209 
   11210         return false;
   11211     }
   11212 
   11213     /**
   11214      * @hide
   11215      */
   11216     public boolean isInScrollingContainer() {
   11217         ViewParent p = getParent();
   11218         while (p != null && p instanceof ViewGroup) {
   11219             if (((ViewGroup) p).shouldDelayChildPressedState()) {
   11220                 return true;
   11221             }
   11222             p = p.getParent();
   11223         }
   11224         return false;
   11225     }
   11226 
   11227     /**
   11228      * Remove the longpress detection timer.
   11229      */
   11230     private void removeLongPressCallback() {
   11231         if (mPendingCheckForLongPress != null) {
   11232           removeCallbacks(mPendingCheckForLongPress);
   11233         }
   11234     }
   11235 
   11236     /**
   11237      * Remove the pending click action
   11238      */
   11239     private void removePerformClickCallback() {
   11240         if (mPerformClick != null) {
   11241             removeCallbacks(mPerformClick);
   11242         }
   11243     }
   11244 
   11245     /**
   11246      * Remove the prepress detection timer.
   11247      */
   11248     private void removeUnsetPressCallback() {
   11249         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
   11250             setPressed(false);
   11251             removeCallbacks(mUnsetPressedState);
   11252         }
   11253     }
   11254 
   11255     /**
   11256      * Remove the tap detection timer.
   11257      */
   11258     private void removeTapCallback() {
   11259         if (mPendingCheckForTap != null) {
   11260             mPrivateFlags &= ~PFLAG_PREPRESSED;
   11261             removeCallbacks(mPendingCheckForTap);
   11262         }
   11263     }
   11264 
   11265     /**
   11266      * Cancels a pending long press.  Your subclass can use this if you
   11267      * want the context menu to come up if the user presses and holds
   11268      * at the same place, but you don't want it to come up if they press
   11269      * and then move around enough to cause scrolling.
   11270      */
   11271     public void cancelLongPress() {
   11272         removeLongPressCallback();
   11273 
   11274         /*
   11275          * The prepressed state handled by the tap callback is a display
   11276          * construct, but the tap callback will post a long press callback
   11277          * less its own timeout. Remove it here.
   11278          */
   11279         removeTapCallback();
   11280     }
   11281 
   11282     /**
   11283      * Remove the pending callback for sending a
   11284      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   11285      */
   11286     private void removeSendViewScrolledAccessibilityEventCallback() {
   11287         if (mSendViewScrolledAccessibilityEvent != null) {
   11288             removeCallbacks(mSendViewScrolledAccessibilityEvent);
   11289             mSendViewScrolledAccessibilityEvent.mIsPending = false;
   11290         }
   11291     }
   11292 
   11293     /**
   11294      * Sets the TouchDelegate for this View.
   11295      */
   11296     public void setTouchDelegate(TouchDelegate delegate) {
   11297         mTouchDelegate = delegate;
   11298     }
   11299 
   11300     /**
   11301      * Gets the TouchDelegate for this View.
   11302      */
   11303     public TouchDelegate getTouchDelegate() {
   11304         return mTouchDelegate;
   11305     }
   11306 
   11307     /**
   11308      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
   11309      *
   11310      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
   11311      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
   11312      * available. This method should only be called for touch events.
   11313      *
   11314      * <p class="note">This api is not intended for most applications. Buffered dispatch
   11315      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
   11316      * streams will not improve your input latency. Side effects include: increased latency,
   11317      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
   11318      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
   11319      * you.</p>
   11320      */
   11321     public final void requestUnbufferedDispatch(MotionEvent event) {
   11322         final int action = event.getAction();
   11323         if (mAttachInfo == null
   11324                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
   11325                 || !event.isTouchEvent()) {
   11326             return;
   11327         }
   11328         mAttachInfo.mUnbufferedDispatchRequested = true;
   11329     }
   11330 
   11331     /**
   11332      * Set flags controlling behavior of this view.
   11333      *
   11334      * @param flags Constant indicating the value which should be set
   11335      * @param mask Constant indicating the bit range that should be changed
   11336      */
   11337     void setFlags(int flags, int mask) {
   11338         final boolean accessibilityEnabled =
   11339                 AccessibilityManager.getInstance(mContext).isEnabled();
   11340         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
   11341 
   11342         int old = mViewFlags;
   11343         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
   11344 
   11345         int changed = mViewFlags ^ old;
   11346         if (changed == 0) {
   11347             return;
   11348         }
   11349         int privateFlags = mPrivateFlags;
   11350 
   11351         /* Check if the FOCUSABLE bit has changed */
   11352         if (((changed & FOCUSABLE_MASK) != 0) &&
   11353                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
   11354             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
   11355                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
   11356                 /* Give up focus if we are no longer focusable */
   11357                 clearFocus();
   11358             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
   11359                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
   11360                 /*
   11361                  * Tell the view system that we are now available to take focus
   11362                  * if no one else already has it.
   11363                  */
   11364                 if (mParent != null) mParent.focusableViewAvailable(this);
   11365             }
   11366         }
   11367 
   11368         final int newVisibility = flags & VISIBILITY_MASK;
   11369         if (newVisibility == VISIBLE) {
   11370             if ((changed & VISIBILITY_MASK) != 0) {
   11371                 /*
   11372                  * If this view is becoming visible, invalidate it in case it changed while
   11373                  * it was not visible. Marking it drawn ensures that the invalidation will
   11374                  * go through.
   11375                  */
   11376                 mPrivateFlags |= PFLAG_DRAWN;
   11377                 invalidate(true);
   11378 
   11379                 needGlobalAttributesUpdate(true);
   11380 
   11381                 // a view becoming visible is worth notifying the parent
   11382                 // about in case nothing has focus.  even if this specific view
   11383                 // isn't focusable, it may contain something that is, so let
   11384                 // the root view try to give this focus if nothing else does.
   11385                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
   11386                     mParent.focusableViewAvailable(this);
   11387                 }
   11388             }
   11389         }
   11390 
   11391         /* Check if the GONE bit has changed */
   11392         if ((changed & GONE) != 0) {
   11393             needGlobalAttributesUpdate(false);
   11394             requestLayout();
   11395 
   11396             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
   11397                 if (hasFocus()) clearFocus();
   11398                 clearAccessibilityFocus();
   11399                 destroyDrawingCache();
   11400                 if (mParent instanceof View) {
   11401                     // GONE views noop invalidation, so invalidate the parent
   11402                     ((View) mParent).invalidate(true);
   11403                 }
   11404                 // Mark the view drawn to ensure that it gets invalidated properly the next
   11405                 // time it is visible and gets invalidated
   11406                 mPrivateFlags |= PFLAG_DRAWN;
   11407             }
   11408             if (mAttachInfo != null) {
   11409                 mAttachInfo.mViewVisibilityChanged = true;
   11410             }
   11411         }
   11412 
   11413         /* Check if the VISIBLE bit has changed */
   11414         if ((changed & INVISIBLE) != 0) {
   11415             needGlobalAttributesUpdate(false);
   11416             /*
   11417              * If this view is becoming invisible, set the DRAWN flag so that
   11418              * the next invalidate() will not be skipped.
   11419              */
   11420             mPrivateFlags |= PFLAG_DRAWN;
   11421 
   11422             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
   11423                 // root view becoming invisible shouldn't clear focus and accessibility focus
   11424                 if (getRootView() != this) {
   11425                     if (hasFocus()) clearFocus();
   11426                     clearAccessibilityFocus();
   11427                 }
   11428             }
   11429             if (mAttachInfo != null) {
   11430                 mAttachInfo.mViewVisibilityChanged = true;
   11431             }
   11432         }
   11433 
   11434         if ((changed & VISIBILITY_MASK) != 0) {
   11435             // If the view is invisible, cleanup its display list to free up resources
   11436             if (newVisibility != VISIBLE && mAttachInfo != null) {
   11437                 cleanupDraw();
   11438             }
   11439 
   11440             if (mParent instanceof ViewGroup) {
   11441                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
   11442                         (changed & VISIBILITY_MASK), newVisibility);
   11443                 ((View) mParent).invalidate(true);
   11444             } else if (mParent != null) {
   11445                 mParent.invalidateChild(this, null);
   11446             }
   11447 
   11448             if (mAttachInfo != null) {
   11449                 dispatchVisibilityChanged(this, newVisibility);
   11450 
   11451                 // Aggregated visibility changes are dispatched to attached views
   11452                 // in visible windows where the parent is currently shown/drawn
   11453                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
   11454                 // discounting clipping or overlapping. This makes it a good place
   11455                 // to change animation states.
   11456                 if (mParent != null && getWindowVisibility() == VISIBLE &&
   11457                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
   11458                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
   11459                 }
   11460                 notifySubtreeAccessibilityStateChangedIfNeeded();
   11461             }
   11462         }
   11463 
   11464         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
   11465             destroyDrawingCache();
   11466         }
   11467 
   11468         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
   11469             destroyDrawingCache();
   11470             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   11471             invalidateParentCaches();
   11472         }
   11473 
   11474         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
   11475             destroyDrawingCache();
   11476             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   11477         }
   11478 
   11479         if ((changed & DRAW_MASK) != 0) {
   11480             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
   11481                 if (mBackground != null
   11482                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
   11483                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   11484                 } else {
   11485                     mPrivateFlags |= PFLAG_SKIP_DRAW;
   11486                 }
   11487             } else {
   11488                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   11489             }
   11490             requestLayout();
   11491             invalidate(true);
   11492         }
   11493 
   11494         if ((changed & KEEP_SCREEN_ON) != 0) {
   11495             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   11496                 mParent.recomputeViewAttributes(this);
   11497             }
   11498         }
   11499 
   11500         if (accessibilityEnabled) {
   11501             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
   11502                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
   11503                     || (changed & CONTEXT_CLICKABLE) != 0) {
   11504                 if (oldIncludeForAccessibility != includeForAccessibility()) {
   11505                     notifySubtreeAccessibilityStateChangedIfNeeded();
   11506                 } else {
   11507                     notifyViewAccessibilityStateChangedIfNeeded(
   11508                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   11509                 }
   11510             } else if ((changed & ENABLED_MASK) != 0) {
   11511                 notifyViewAccessibilityStateChangedIfNeeded(
   11512                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   11513             }
   11514         }
   11515     }
   11516 
   11517     /**
   11518      * Change the view's z order in the tree, so it's on top of other sibling
   11519      * views. This ordering change may affect layout, if the parent container
   11520      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
   11521      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
   11522      * method should be followed by calls to {@link #requestLayout()} and
   11523      * {@link View#invalidate()} on the view's parent to force the parent to redraw
   11524      * with the new child ordering.
   11525      *
   11526      * @see ViewGroup#bringChildToFront(View)
   11527      */
   11528     public void bringToFront() {
   11529         if (mParent != null) {
   11530             mParent.bringChildToFront(this);
   11531         }
   11532     }
   11533 
   11534     /**
   11535      * This is called in response to an internal scroll in this view (i.e., the
   11536      * view scrolled its own contents). This is typically as a result of
   11537      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
   11538      * called.
   11539      *
   11540      * @param l Current horizontal scroll origin.
   11541      * @param t Current vertical scroll origin.
   11542      * @param oldl Previous horizontal scroll origin.
   11543      * @param oldt Previous vertical scroll origin.
   11544      */
   11545     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   11546         notifySubtreeAccessibilityStateChangedIfNeeded();
   11547 
   11548         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   11549             postSendViewScrolledAccessibilityEventCallback();
   11550         }
   11551 
   11552         mBackgroundSizeChanged = true;
   11553         if (mForegroundInfo != null) {
   11554             mForegroundInfo.mBoundsChanged = true;
   11555         }
   11556 
   11557         final AttachInfo ai = mAttachInfo;
   11558         if (ai != null) {
   11559             ai.mViewScrollChanged = true;
   11560         }
   11561 
   11562         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
   11563             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
   11564         }
   11565     }
   11566 
   11567     /**
   11568      * Interface definition for a callback to be invoked when the scroll
   11569      * X or Y positions of a view change.
   11570      * <p>
   11571      * <b>Note:</b> Some views handle scrolling independently from View and may
   11572      * have their own separate listeners for scroll-type events. For example,
   11573      * {@link android.widget.ListView ListView} allows clients to register an
   11574      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   11575      * to listen for changes in list scroll position.
   11576      *
   11577      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
   11578      */
   11579     public interface OnScrollChangeListener {
   11580         /**
   11581          * Called when the scroll position of a view changes.
   11582          *
   11583          * @param v The view whose scroll position has changed.
   11584          * @param scrollX Current horizontal scroll origin.
   11585          * @param scrollY Current vertical scroll origin.
   11586          * @param oldScrollX Previous horizontal scroll origin.
   11587          * @param oldScrollY Previous vertical scroll origin.
   11588          */
   11589         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
   11590     }
   11591 
   11592     /**
   11593      * Interface definition for a callback to be invoked when the layout bounds of a view
   11594      * changes due to layout processing.
   11595      */
   11596     public interface OnLayoutChangeListener {
   11597         /**
   11598          * Called when the layout bounds of a view changes due to layout processing.
   11599          *
   11600          * @param v The view whose bounds have changed.
   11601          * @param left The new value of the view's left property.
   11602          * @param top The new value of the view's top property.
   11603          * @param right The new value of the view's right property.
   11604          * @param bottom The new value of the view's bottom property.
   11605          * @param oldLeft The previous value of the view's left property.
   11606          * @param oldTop The previous value of the view's top property.
   11607          * @param oldRight The previous value of the view's right property.
   11608          * @param oldBottom The previous value of the view's bottom property.
   11609          */
   11610         void onLayoutChange(View v, int left, int top, int right, int bottom,
   11611             int oldLeft, int oldTop, int oldRight, int oldBottom);
   11612     }
   11613 
   11614     /**
   11615      * This is called during layout when the size of this view has changed. If
   11616      * you were just added to the view hierarchy, you're called with the old
   11617      * values of 0.
   11618      *
   11619      * @param w Current width of this view.
   11620      * @param h Current height of this view.
   11621      * @param oldw Old width of this view.
   11622      * @param oldh Old height of this view.
   11623      */
   11624     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   11625     }
   11626 
   11627     /**
   11628      * Called by draw to draw the child views. This may be overridden
   11629      * by derived classes to gain control just before its children are drawn
   11630      * (but after its own view has been drawn).
   11631      * @param canvas the canvas on which to draw the view
   11632      */
   11633     protected void dispatchDraw(Canvas canvas) {
   11634 
   11635     }
   11636 
   11637     /**
   11638      * Gets the parent of this view. Note that the parent is a
   11639      * ViewParent and not necessarily a View.
   11640      *
   11641      * @return Parent of this view.
   11642      */
   11643     public final ViewParent getParent() {
   11644         return mParent;
   11645     }
   11646 
   11647     /**
   11648      * Set the horizontal scrolled position of your view. This will cause a call to
   11649      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   11650      * invalidated.
   11651      * @param value the x position to scroll to
   11652      */
   11653     public void setScrollX(int value) {
   11654         scrollTo(value, mScrollY);
   11655     }
   11656 
   11657     /**
   11658      * Set the vertical scrolled position of your view. This will cause a call to
   11659      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   11660      * invalidated.
   11661      * @param value the y position to scroll to
   11662      */
   11663     public void setScrollY(int value) {
   11664         scrollTo(mScrollX, value);
   11665     }
   11666 
   11667     /**
   11668      * Return the scrolled left position of this view. This is the left edge of
   11669      * the displayed part of your view. You do not need to draw any pixels
   11670      * farther left, since those are outside of the frame of your view on
   11671      * screen.
   11672      *
   11673      * @return The left edge of the displayed part of your view, in pixels.
   11674      */
   11675     public final int getScrollX() {
   11676         return mScrollX;
   11677     }
   11678 
   11679     /**
   11680      * Return the scrolled top position of this view. This is the top edge of
   11681      * the displayed part of your view. You do not need to draw any pixels above
   11682      * it, since those are outside of the frame of your view on screen.
   11683      *
   11684      * @return The top edge of the displayed part of your view, in pixels.
   11685      */
   11686     public final int getScrollY() {
   11687         return mScrollY;
   11688     }
   11689 
   11690     /**
   11691      * Return the width of the your view.
   11692      *
   11693      * @return The width of your view, in pixels.
   11694      */
   11695     @ViewDebug.ExportedProperty(category = "layout")
   11696     public final int getWidth() {
   11697         return mRight - mLeft;
   11698     }
   11699 
   11700     /**
   11701      * Return the height of your view.
   11702      *
   11703      * @return The height of your view, in pixels.
   11704      */
   11705     @ViewDebug.ExportedProperty(category = "layout")
   11706     public final int getHeight() {
   11707         return mBottom - mTop;
   11708     }
   11709 
   11710     /**
   11711      * Return the visible drawing bounds of your view. Fills in the output
   11712      * rectangle with the values from getScrollX(), getScrollY(),
   11713      * getWidth(), and getHeight(). These bounds do not account for any
   11714      * transformation properties currently set on the view, such as
   11715      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
   11716      *
   11717      * @param outRect The (scrolled) drawing bounds of the view.
   11718      */
   11719     public void getDrawingRect(Rect outRect) {
   11720         outRect.left = mScrollX;
   11721         outRect.top = mScrollY;
   11722         outRect.right = mScrollX + (mRight - mLeft);
   11723         outRect.bottom = mScrollY + (mBottom - mTop);
   11724     }
   11725 
   11726     /**
   11727      * Like {@link #getMeasuredWidthAndState()}, but only returns the
   11728      * raw width component (that is the result is masked by
   11729      * {@link #MEASURED_SIZE_MASK}).
   11730      *
   11731      * @return The raw measured width of this view.
   11732      */
   11733     public final int getMeasuredWidth() {
   11734         return mMeasuredWidth & MEASURED_SIZE_MASK;
   11735     }
   11736 
   11737     /**
   11738      * Return the full width measurement information for this view as computed
   11739      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   11740      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   11741      * This should be used during measurement and layout calculations only. Use
   11742      * {@link #getWidth()} to see how wide a view is after layout.
   11743      *
   11744      * @return The measured width of this view as a bit mask.
   11745      */
   11746     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   11747             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   11748                     name = "MEASURED_STATE_TOO_SMALL"),
   11749     })
   11750     public final int getMeasuredWidthAndState() {
   11751         return mMeasuredWidth;
   11752     }
   11753 
   11754     /**
   11755      * Like {@link #getMeasuredHeightAndState()}, but only returns the
   11756      * raw width component (that is the result is masked by
   11757      * {@link #MEASURED_SIZE_MASK}).
   11758      *
   11759      * @return The raw measured height of this view.
   11760      */
   11761     public final int getMeasuredHeight() {
   11762         return mMeasuredHeight & MEASURED_SIZE_MASK;
   11763     }
   11764 
   11765     /**
   11766      * Return the full height measurement information for this view as computed
   11767      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   11768      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   11769      * This should be used during measurement and layout calculations only. Use
   11770      * {@link #getHeight()} to see how wide a view is after layout.
   11771      *
   11772      * @return The measured width of this view as a bit mask.
   11773      */
   11774     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   11775             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   11776                     name = "MEASURED_STATE_TOO_SMALL"),
   11777     })
   11778     public final int getMeasuredHeightAndState() {
   11779         return mMeasuredHeight;
   11780     }
   11781 
   11782     /**
   11783      * Return only the state bits of {@link #getMeasuredWidthAndState()}
   11784      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
   11785      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
   11786      * and the height component is at the shifted bits
   11787      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
   11788      */
   11789     public final int getMeasuredState() {
   11790         return (mMeasuredWidth&MEASURED_STATE_MASK)
   11791                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
   11792                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
   11793     }
   11794 
   11795     /**
   11796      * The transform matrix of this view, which is calculated based on the current
   11797      * rotation, scale, and pivot properties.
   11798      *
   11799      * @see #getRotation()
   11800      * @see #getScaleX()
   11801      * @see #getScaleY()
   11802      * @see #getPivotX()
   11803      * @see #getPivotY()
   11804      * @return The current transform matrix for the view
   11805      */
   11806     public Matrix getMatrix() {
   11807         ensureTransformationInfo();
   11808         final Matrix matrix = mTransformationInfo.mMatrix;
   11809         mRenderNode.getMatrix(matrix);
   11810         return matrix;
   11811     }
   11812 
   11813     /**
   11814      * Returns true if the transform matrix is the identity matrix.
   11815      * Recomputes the matrix if necessary.
   11816      *
   11817      * @return True if the transform matrix is the identity matrix, false otherwise.
   11818      */
   11819     final boolean hasIdentityMatrix() {
   11820         return mRenderNode.hasIdentityMatrix();
   11821     }
   11822 
   11823     void ensureTransformationInfo() {
   11824         if (mTransformationInfo == null) {
   11825             mTransformationInfo = new TransformationInfo();
   11826         }
   11827     }
   11828 
   11829     /**
   11830      * Utility method to retrieve the inverse of the current mMatrix property.
   11831      * We cache the matrix to avoid recalculating it when transform properties
   11832      * have not changed.
   11833      *
   11834      * @return The inverse of the current matrix of this view.
   11835      * @hide
   11836      */
   11837     public final Matrix getInverseMatrix() {
   11838         ensureTransformationInfo();
   11839         if (mTransformationInfo.mInverseMatrix == null) {
   11840             mTransformationInfo.mInverseMatrix = new Matrix();
   11841         }
   11842         final Matrix matrix = mTransformationInfo.mInverseMatrix;
   11843         mRenderNode.getInverseMatrix(matrix);
   11844         return matrix;
   11845     }
   11846 
   11847     /**
   11848      * Gets the distance along the Z axis from the camera to this view.
   11849      *
   11850      * @see #setCameraDistance(float)
   11851      *
   11852      * @return The distance along the Z axis.
   11853      */
   11854     public float getCameraDistance() {
   11855         final float dpi = mResources.getDisplayMetrics().densityDpi;
   11856         return -(mRenderNode.getCameraDistance() * dpi);
   11857     }
   11858 
   11859     /**
   11860      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
   11861      * views are drawn) from the camera to this view. The camera's distance
   11862      * affects 3D transformations, for instance rotations around the X and Y
   11863      * axis. If the rotationX or rotationY properties are changed and this view is
   11864      * large (more than half the size of the screen), it is recommended to always
   11865      * use a camera distance that's greater than the height (X axis rotation) or
   11866      * the width (Y axis rotation) of this view.</p>
   11867      *
   11868      * <p>The distance of the camera from the view plane can have an affect on the
   11869      * perspective distortion of the view when it is rotated around the x or y axis.
   11870      * For example, a large distance will result in a large viewing angle, and there
   11871      * will not be much perspective distortion of the view as it rotates. A short
   11872      * distance may cause much more perspective distortion upon rotation, and can
   11873      * also result in some drawing artifacts if the rotated view ends up partially
   11874      * behind the camera (which is why the recommendation is to use a distance at
   11875      * least as far as the size of the view, if the view is to be rotated.)</p>
   11876      *
   11877      * <p>The distance is expressed in "depth pixels." The default distance depends
   11878      * on the screen density. For instance, on a medium density display, the
   11879      * default distance is 1280. On a high density display, the default distance
   11880      * is 1920.</p>
   11881      *
   11882      * <p>If you want to specify a distance that leads to visually consistent
   11883      * results across various densities, use the following formula:</p>
   11884      * <pre>
   11885      * float scale = context.getResources().getDisplayMetrics().density;
   11886      * view.setCameraDistance(distance * scale);
   11887      * </pre>
   11888      *
   11889      * <p>The density scale factor of a high density display is 1.5,
   11890      * and 1920 = 1280 * 1.5.</p>
   11891      *
   11892      * @param distance The distance in "depth pixels", if negative the opposite
   11893      *        value is used
   11894      *
   11895      * @see #setRotationX(float)
   11896      * @see #setRotationY(float)
   11897      */
   11898     public void setCameraDistance(float distance) {
   11899         final float dpi = mResources.getDisplayMetrics().densityDpi;
   11900 
   11901         invalidateViewProperty(true, false);
   11902         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
   11903         invalidateViewProperty(false, false);
   11904 
   11905         invalidateParentIfNeededAndWasQuickRejected();
   11906     }
   11907 
   11908     /**
   11909      * The degrees that the view is rotated around the pivot point.
   11910      *
   11911      * @see #setRotation(float)
   11912      * @see #getPivotX()
   11913      * @see #getPivotY()
   11914      *
   11915      * @return The degrees of rotation.
   11916      */
   11917     @ViewDebug.ExportedProperty(category = "drawing")
   11918     public float getRotation() {
   11919         return mRenderNode.getRotation();
   11920     }
   11921 
   11922     /**
   11923      * Sets the degrees that the view is rotated around the pivot point. Increasing values
   11924      * result in clockwise rotation.
   11925      *
   11926      * @param rotation The degrees of rotation.
   11927      *
   11928      * @see #getRotation()
   11929      * @see #getPivotX()
   11930      * @see #getPivotY()
   11931      * @see #setRotationX(float)
   11932      * @see #setRotationY(float)
   11933      *
   11934      * @attr ref android.R.styleable#View_rotation
   11935      */
   11936     public void setRotation(float rotation) {
   11937         if (rotation != getRotation()) {
   11938             // Double-invalidation is necessary to capture view's old and new areas
   11939             invalidateViewProperty(true, false);
   11940             mRenderNode.setRotation(rotation);
   11941             invalidateViewProperty(false, true);
   11942 
   11943             invalidateParentIfNeededAndWasQuickRejected();
   11944             notifySubtreeAccessibilityStateChangedIfNeeded();
   11945         }
   11946     }
   11947 
   11948     /**
   11949      * The degrees that the view is rotated around the vertical axis through the pivot point.
   11950      *
   11951      * @see #getPivotX()
   11952      * @see #getPivotY()
   11953      * @see #setRotationY(float)
   11954      *
   11955      * @return The degrees of Y rotation.
   11956      */
   11957     @ViewDebug.ExportedProperty(category = "drawing")
   11958     public float getRotationY() {
   11959         return mRenderNode.getRotationY();
   11960     }
   11961 
   11962     /**
   11963      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
   11964      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
   11965      * down the y axis.
   11966      *
   11967      * When rotating large views, it is recommended to adjust the camera distance
   11968      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   11969      *
   11970      * @param rotationY The degrees of Y rotation.
   11971      *
   11972      * @see #getRotationY()
   11973      * @see #getPivotX()
   11974      * @see #getPivotY()
   11975      * @see #setRotation(float)
   11976      * @see #setRotationX(float)
   11977      * @see #setCameraDistance(float)
   11978      *
   11979      * @attr ref android.R.styleable#View_rotationY
   11980      */
   11981     public void setRotationY(float rotationY) {
   11982         if (rotationY != getRotationY()) {
   11983             invalidateViewProperty(true, false);
   11984             mRenderNode.setRotationY(rotationY);
   11985             invalidateViewProperty(false, true);
   11986 
   11987             invalidateParentIfNeededAndWasQuickRejected();
   11988             notifySubtreeAccessibilityStateChangedIfNeeded();
   11989         }
   11990     }
   11991 
   11992     /**
   11993      * The degrees that the view is rotated around the horizontal axis through the pivot point.
   11994      *
   11995      * @see #getPivotX()
   11996      * @see #getPivotY()
   11997      * @see #setRotationX(float)
   11998      *
   11999      * @return The degrees of X rotation.
   12000      */
   12001     @ViewDebug.ExportedProperty(category = "drawing")
   12002     public float getRotationX() {
   12003         return mRenderNode.getRotationX();
   12004     }
   12005 
   12006     /**
   12007      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
   12008      * Increasing values result in clockwise rotation from the viewpoint of looking down the
   12009      * x axis.
   12010      *
   12011      * When rotating large views, it is recommended to adjust the camera distance
   12012      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   12013      *
   12014      * @param rotationX The degrees of X rotation.
   12015      *
   12016      * @see #getRotationX()
   12017      * @see #getPivotX()
   12018      * @see #getPivotY()
   12019      * @see #setRotation(float)
   12020      * @see #setRotationY(float)
   12021      * @see #setCameraDistance(float)
   12022      *
   12023      * @attr ref android.R.styleable#View_rotationX
   12024      */
   12025     public void setRotationX(float rotationX) {
   12026         if (rotationX != getRotationX()) {
   12027             invalidateViewProperty(true, false);
   12028             mRenderNode.setRotationX(rotationX);
   12029             invalidateViewProperty(false, true);
   12030 
   12031             invalidateParentIfNeededAndWasQuickRejected();
   12032             notifySubtreeAccessibilityStateChangedIfNeeded();
   12033         }
   12034     }
   12035 
   12036     /**
   12037      * The amount that the view is scaled in x around the pivot point, as a proportion of
   12038      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
   12039      *
   12040      * <p>By default, this is 1.0f.
   12041      *
   12042      * @see #getPivotX()
   12043      * @see #getPivotY()
   12044      * @return The scaling factor.
   12045      */
   12046     @ViewDebug.ExportedProperty(category = "drawing")
   12047     public float getScaleX() {
   12048         return mRenderNode.getScaleX();
   12049     }
   12050 
   12051     /**
   12052      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
   12053      * the view's unscaled width. A value of 1 means that no scaling is applied.
   12054      *
   12055      * @param scaleX The scaling factor.
   12056      * @see #getPivotX()
   12057      * @see #getPivotY()
   12058      *
   12059      * @attr ref android.R.styleable#View_scaleX
   12060      */
   12061     public void setScaleX(float scaleX) {
   12062         if (scaleX != getScaleX()) {
   12063             invalidateViewProperty(true, false);
   12064             mRenderNode.setScaleX(scaleX);
   12065             invalidateViewProperty(false, true);
   12066 
   12067             invalidateParentIfNeededAndWasQuickRejected();
   12068             notifySubtreeAccessibilityStateChangedIfNeeded();
   12069         }
   12070     }
   12071 
   12072     /**
   12073      * The amount that the view is scaled in y around the pivot point, as a proportion of
   12074      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
   12075      *
   12076      * <p>By default, this is 1.0f.
   12077      *
   12078      * @see #getPivotX()
   12079      * @see #getPivotY()
   12080      * @return The scaling factor.
   12081      */
   12082     @ViewDebug.ExportedProperty(category = "drawing")
   12083     public float getScaleY() {
   12084         return mRenderNode.getScaleY();
   12085     }
   12086 
   12087     /**
   12088      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
   12089      * the view's unscaled width. A value of 1 means that no scaling is applied.
   12090      *
   12091      * @param scaleY The scaling factor.
   12092      * @see #getPivotX()
   12093      * @see #getPivotY()
   12094      *
   12095      * @attr ref android.R.styleable#View_scaleY
   12096      */
   12097     public void setScaleY(float scaleY) {
   12098         if (scaleY != getScaleY()) {
   12099             invalidateViewProperty(true, false);
   12100             mRenderNode.setScaleY(scaleY);
   12101             invalidateViewProperty(false, true);
   12102 
   12103             invalidateParentIfNeededAndWasQuickRejected();
   12104             notifySubtreeAccessibilityStateChangedIfNeeded();
   12105         }
   12106     }
   12107 
   12108     /**
   12109      * The x location of the point around which the view is {@link #setRotation(float) rotated}
   12110      * and {@link #setScaleX(float) scaled}.
   12111      *
   12112      * @see #getRotation()
   12113      * @see #getScaleX()
   12114      * @see #getScaleY()
   12115      * @see #getPivotY()
   12116      * @return The x location of the pivot point.
   12117      *
   12118      * @attr ref android.R.styleable#View_transformPivotX
   12119      */
   12120     @ViewDebug.ExportedProperty(category = "drawing")
   12121     public float getPivotX() {
   12122         return mRenderNode.getPivotX();
   12123     }
   12124 
   12125     /**
   12126      * Sets the x location of the point around which the view is
   12127      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
   12128      * By default, the pivot point is centered on the object.
   12129      * Setting this property disables this behavior and causes the view to use only the
   12130      * explicitly set pivotX and pivotY values.
   12131      *
   12132      * @param pivotX The x location of the pivot point.
   12133      * @see #getRotation()
   12134      * @see #getScaleX()
   12135      * @see #getScaleY()
   12136      * @see #getPivotY()
   12137      *
   12138      * @attr ref android.R.styleable#View_transformPivotX
   12139      */
   12140     public void setPivotX(float pivotX) {
   12141         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
   12142             invalidateViewProperty(true, false);
   12143             mRenderNode.setPivotX(pivotX);
   12144             invalidateViewProperty(false, true);
   12145 
   12146             invalidateParentIfNeededAndWasQuickRejected();
   12147         }
   12148     }
   12149 
   12150     /**
   12151      * The y location of the point around which the view is {@link #setRotation(float) rotated}
   12152      * and {@link #setScaleY(float) scaled}.
   12153      *
   12154      * @see #getRotation()
   12155      * @see #getScaleX()
   12156      * @see #getScaleY()
   12157      * @see #getPivotY()
   12158      * @return The y location of the pivot point.
   12159      *
   12160      * @attr ref android.R.styleable#View_transformPivotY
   12161      */
   12162     @ViewDebug.ExportedProperty(category = "drawing")
   12163     public float getPivotY() {
   12164         return mRenderNode.getPivotY();
   12165     }
   12166 
   12167     /**
   12168      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
   12169      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
   12170      * Setting this property disables this behavior and causes the view to use only the
   12171      * explicitly set pivotX and pivotY values.
   12172      *
   12173      * @param pivotY The y location of the pivot point.
   12174      * @see #getRotation()
   12175      * @see #getScaleX()
   12176      * @see #getScaleY()
   12177      * @see #getPivotY()
   12178      *
   12179      * @attr ref android.R.styleable#View_transformPivotY
   12180      */
   12181     public void setPivotY(float pivotY) {
   12182         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
   12183             invalidateViewProperty(true, false);
   12184             mRenderNode.setPivotY(pivotY);
   12185             invalidateViewProperty(false, true);
   12186 
   12187             invalidateParentIfNeededAndWasQuickRejected();
   12188         }
   12189     }
   12190 
   12191     /**
   12192      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
   12193      * completely transparent and 1 means the view is completely opaque.
   12194      *
   12195      * <p>By default this is 1.0f.
   12196      * @return The opacity of the view.
   12197      */
   12198     @ViewDebug.ExportedProperty(category = "drawing")
   12199     public float getAlpha() {
   12200         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
   12201     }
   12202 
   12203     /**
   12204      * Sets the behavior for overlapping rendering for this view (see {@link
   12205      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
   12206      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
   12207      * providing the value which is then used internally. That is, when {@link
   12208      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
   12209      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
   12210      * instead.
   12211      *
   12212      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
   12213      * instead of that returned by {@link #hasOverlappingRendering()}.
   12214      *
   12215      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
   12216      */
   12217     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
   12218         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
   12219         if (hasOverlappingRendering) {
   12220             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
   12221         } else {
   12222             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
   12223         }
   12224     }
   12225 
   12226     /**
   12227      * Returns the value for overlapping rendering that is used internally. This is either
   12228      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
   12229      * the return value of {@link #hasOverlappingRendering()}, otherwise.
   12230      *
   12231      * @return The value for overlapping rendering being used internally.
   12232      */
   12233     public final boolean getHasOverlappingRendering() {
   12234         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
   12235                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
   12236                 hasOverlappingRendering();
   12237     }
   12238 
   12239     /**
   12240      * Returns whether this View has content which overlaps.
   12241      *
   12242      * <p>This function, intended to be overridden by specific View types, is an optimization when
   12243      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
   12244      * an offscreen buffer and then composited into place, which can be expensive. If the view has
   12245      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
   12246      * directly. An example of overlapping rendering is a TextView with a background image, such as
   12247      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
   12248      * ImageView with only the foreground image. The default implementation returns true; subclasses
   12249      * should override if they have cases which can be optimized.</p>
   12250      *
   12251      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
   12252      * necessitates that a View return true if it uses the methods internally without passing the
   12253      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
   12254      *
   12255      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
   12256      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
   12257      *
   12258      * @return true if the content in this view might overlap, false otherwise.
   12259      */
   12260     @ViewDebug.ExportedProperty(category = "drawing")
   12261     public boolean hasOverlappingRendering() {
   12262         return true;
   12263     }
   12264 
   12265     /**
   12266      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
   12267      * completely transparent and 1 means the view is completely opaque.
   12268      *
   12269      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
   12270      * can have significant performance implications, especially for large views. It is best to use
   12271      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
   12272      *
   12273      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
   12274      * strongly recommended for performance reasons to either override
   12275      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
   12276      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
   12277      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
   12278      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
   12279      * of rendering cost, even for simple or small views. Starting with
   12280      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
   12281      * applied to the view at the rendering level.</p>
   12282      *
   12283      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
   12284      * responsible for applying the opacity itself.</p>
   12285      *
   12286      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
   12287      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
   12288      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
   12289      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
   12290      *
   12291      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
   12292      * value will clip a View to its bounds, unless the View returns <code>false</code> from
   12293      * {@link #hasOverlappingRendering}.</p>
   12294      *
   12295      * @param alpha The opacity of the view.
   12296      *
   12297      * @see #hasOverlappingRendering()
   12298      * @see #setLayerType(int, android.graphics.Paint)
   12299      *
   12300      * @attr ref android.R.styleable#View_alpha
   12301      */
   12302     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
   12303         ensureTransformationInfo();
   12304         if (mTransformationInfo.mAlpha != alpha) {
   12305             mTransformationInfo.mAlpha = alpha;
   12306             if (onSetAlpha((int) (alpha * 255))) {
   12307                 mPrivateFlags |= PFLAG_ALPHA_SET;
   12308                 // subclass is handling alpha - don't optimize rendering cache invalidation
   12309                 invalidateParentCaches();
   12310                 invalidate(true);
   12311             } else {
   12312                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   12313                 invalidateViewProperty(true, false);
   12314                 mRenderNode.setAlpha(getFinalAlpha());
   12315                 notifyViewAccessibilityStateChangedIfNeeded(
   12316                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   12317             }
   12318         }
   12319     }
   12320 
   12321     /**
   12322      * Faster version of setAlpha() which performs the same steps except there are
   12323      * no calls to invalidate(). The caller of this function should perform proper invalidation
   12324      * on the parent and this object. The return value indicates whether the subclass handles
   12325      * alpha (the return value for onSetAlpha()).
   12326      *
   12327      * @param alpha The new value for the alpha property
   12328      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
   12329      *         the new value for the alpha property is different from the old value
   12330      */
   12331     boolean setAlphaNoInvalidation(float alpha) {
   12332         ensureTransformationInfo();
   12333         if (mTransformationInfo.mAlpha != alpha) {
   12334             mTransformationInfo.mAlpha = alpha;
   12335             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
   12336             if (subclassHandlesAlpha) {
   12337                 mPrivateFlags |= PFLAG_ALPHA_SET;
   12338                 return true;
   12339             } else {
   12340                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   12341                 mRenderNode.setAlpha(getFinalAlpha());
   12342             }
   12343         }
   12344         return false;
   12345     }
   12346 
   12347     /**
   12348      * This property is hidden and intended only for use by the Fade transition, which
   12349      * animates it to produce a visual translucency that does not side-effect (or get
   12350      * affected by) the real alpha property. This value is composited with the other
   12351      * alpha value (and the AlphaAnimation value, when that is present) to produce
   12352      * a final visual translucency result, which is what is passed into the DisplayList.
   12353      *
   12354      * @hide
   12355      */
   12356     public void setTransitionAlpha(float alpha) {
   12357         ensureTransformationInfo();
   12358         if (mTransformationInfo.mTransitionAlpha != alpha) {
   12359             mTransformationInfo.mTransitionAlpha = alpha;
   12360             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   12361             invalidateViewProperty(true, false);
   12362             mRenderNode.setAlpha(getFinalAlpha());
   12363         }
   12364     }
   12365 
   12366     /**
   12367      * Calculates the visual alpha of this view, which is a combination of the actual
   12368      * alpha value and the transitionAlpha value (if set).
   12369      */
   12370     private float getFinalAlpha() {
   12371         if (mTransformationInfo != null) {
   12372             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
   12373         }
   12374         return 1;
   12375     }
   12376 
   12377     /**
   12378      * This property is hidden and intended only for use by the Fade transition, which
   12379      * animates it to produce a visual translucency that does not side-effect (or get
   12380      * affected by) the real alpha property. This value is composited with the other
   12381      * alpha value (and the AlphaAnimation value, when that is present) to produce
   12382      * a final visual translucency result, which is what is passed into the DisplayList.
   12383      *
   12384      * @hide
   12385      */
   12386     @ViewDebug.ExportedProperty(category = "drawing")
   12387     public float getTransitionAlpha() {
   12388         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
   12389     }
   12390 
   12391     /**
   12392      * Top position of this view relative to its parent.
   12393      *
   12394      * @return The top of this view, in pixels.
   12395      */
   12396     @ViewDebug.CapturedViewProperty
   12397     public final int getTop() {
   12398         return mTop;
   12399     }
   12400 
   12401     /**
   12402      * Sets the top position of this view relative to its parent. This method is meant to be called
   12403      * by the layout system and should not generally be called otherwise, because the property
   12404      * may be changed at any time by the layout.
   12405      *
   12406      * @param top The top of this view, in pixels.
   12407      */
   12408     public final void setTop(int top) {
   12409         if (top != mTop) {
   12410             final boolean matrixIsIdentity = hasIdentityMatrix();
   12411             if (matrixIsIdentity) {
   12412                 if (mAttachInfo != null) {
   12413                     int minTop;
   12414                     int yLoc;
   12415                     if (top < mTop) {
   12416                         minTop = top;
   12417                         yLoc = top - mTop;
   12418                     } else {
   12419                         minTop = mTop;
   12420                         yLoc = 0;
   12421                     }
   12422                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
   12423                 }
   12424             } else {
   12425                 // Double-invalidation is necessary to capture view's old and new areas
   12426                 invalidate(true);
   12427             }
   12428 
   12429             int width = mRight - mLeft;
   12430             int oldHeight = mBottom - mTop;
   12431 
   12432             mTop = top;
   12433             mRenderNode.setTop(mTop);
   12434 
   12435             sizeChange(width, mBottom - mTop, width, oldHeight);
   12436 
   12437             if (!matrixIsIdentity) {
   12438                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12439                 invalidate(true);
   12440             }
   12441             mBackgroundSizeChanged = true;
   12442             if (mForegroundInfo != null) {
   12443                 mForegroundInfo.mBoundsChanged = true;
   12444             }
   12445             invalidateParentIfNeeded();
   12446             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   12447                 // View was rejected last time it was drawn by its parent; this may have changed
   12448                 invalidateParentIfNeeded();
   12449             }
   12450         }
   12451     }
   12452 
   12453     /**
   12454      * Bottom position of this view relative to its parent.
   12455      *
   12456      * @return The bottom of this view, in pixels.
   12457      */
   12458     @ViewDebug.CapturedViewProperty
   12459     public final int getBottom() {
   12460         return mBottom;
   12461     }
   12462 
   12463     /**
   12464      * True if this view has changed since the last time being drawn.
   12465      *
   12466      * @return The dirty state of this view.
   12467      */
   12468     public boolean isDirty() {
   12469         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
   12470     }
   12471 
   12472     /**
   12473      * Sets the bottom position of this view relative to its parent. This method is meant to be
   12474      * called by the layout system and should not generally be called otherwise, because the
   12475      * property may be changed at any time by the layout.
   12476      *
   12477      * @param bottom The bottom of this view, in pixels.
   12478      */
   12479     public final void setBottom(int bottom) {
   12480         if (bottom != mBottom) {
   12481             final boolean matrixIsIdentity = hasIdentityMatrix();
   12482             if (matrixIsIdentity) {
   12483                 if (mAttachInfo != null) {
   12484                     int maxBottom;
   12485                     if (bottom < mBottom) {
   12486                         maxBottom = mBottom;
   12487                     } else {
   12488                         maxBottom = bottom;
   12489                     }
   12490                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
   12491                 }
   12492             } else {
   12493                 // Double-invalidation is necessary to capture view's old and new areas
   12494                 invalidate(true);
   12495             }
   12496 
   12497             int width = mRight - mLeft;
   12498             int oldHeight = mBottom - mTop;
   12499 
   12500             mBottom = bottom;
   12501             mRenderNode.setBottom(mBottom);
   12502 
   12503             sizeChange(width, mBottom - mTop, width, oldHeight);
   12504 
   12505             if (!matrixIsIdentity) {
   12506                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12507                 invalidate(true);
   12508             }
   12509             mBackgroundSizeChanged = true;
   12510             if (mForegroundInfo != null) {
   12511                 mForegroundInfo.mBoundsChanged = true;
   12512             }
   12513             invalidateParentIfNeeded();
   12514             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   12515                 // View was rejected last time it was drawn by its parent; this may have changed
   12516                 invalidateParentIfNeeded();
   12517             }
   12518         }
   12519     }
   12520 
   12521     /**
   12522      * Left position of this view relative to its parent.
   12523      *
   12524      * @return The left edge of this view, in pixels.
   12525      */
   12526     @ViewDebug.CapturedViewProperty
   12527     public final int getLeft() {
   12528         return mLeft;
   12529     }
   12530 
   12531     /**
   12532      * Sets the left position of this view relative to its parent. This method is meant to be called
   12533      * by the layout system and should not generally be called otherwise, because the property
   12534      * may be changed at any time by the layout.
   12535      *
   12536      * @param left The left of this view, in pixels.
   12537      */
   12538     public final void setLeft(int left) {
   12539         if (left != mLeft) {
   12540             final boolean matrixIsIdentity = hasIdentityMatrix();
   12541             if (matrixIsIdentity) {
   12542                 if (mAttachInfo != null) {
   12543                     int minLeft;
   12544                     int xLoc;
   12545                     if (left < mLeft) {
   12546                         minLeft = left;
   12547                         xLoc = left - mLeft;
   12548                     } else {
   12549                         minLeft = mLeft;
   12550                         xLoc = 0;
   12551                     }
   12552                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
   12553                 }
   12554             } else {
   12555                 // Double-invalidation is necessary to capture view's old and new areas
   12556                 invalidate(true);
   12557             }
   12558 
   12559             int oldWidth = mRight - mLeft;
   12560             int height = mBottom - mTop;
   12561 
   12562             mLeft = left;
   12563             mRenderNode.setLeft(left);
   12564 
   12565             sizeChange(mRight - mLeft, height, oldWidth, height);
   12566 
   12567             if (!matrixIsIdentity) {
   12568                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12569                 invalidate(true);
   12570             }
   12571             mBackgroundSizeChanged = true;
   12572             if (mForegroundInfo != null) {
   12573                 mForegroundInfo.mBoundsChanged = true;
   12574             }
   12575             invalidateParentIfNeeded();
   12576             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   12577                 // View was rejected last time it was drawn by its parent; this may have changed
   12578                 invalidateParentIfNeeded();
   12579             }
   12580         }
   12581     }
   12582 
   12583     /**
   12584      * Right position of this view relative to its parent.
   12585      *
   12586      * @return The right edge of this view, in pixels.
   12587      */
   12588     @ViewDebug.CapturedViewProperty
   12589     public final int getRight() {
   12590         return mRight;
   12591     }
   12592 
   12593     /**
   12594      * Sets the right position of this view relative to its parent. This method is meant to be called
   12595      * by the layout system and should not generally be called otherwise, because the property
   12596      * may be changed at any time by the layout.
   12597      *
   12598      * @param right The right of this view, in pixels.
   12599      */
   12600     public final void setRight(int right) {
   12601         if (right != mRight) {
   12602             final boolean matrixIsIdentity = hasIdentityMatrix();
   12603             if (matrixIsIdentity) {
   12604                 if (mAttachInfo != null) {
   12605                     int maxRight;
   12606                     if (right < mRight) {
   12607                         maxRight = mRight;
   12608                     } else {
   12609                         maxRight = right;
   12610                     }
   12611                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
   12612                 }
   12613             } else {
   12614                 // Double-invalidation is necessary to capture view's old and new areas
   12615                 invalidate(true);
   12616             }
   12617 
   12618             int oldWidth = mRight - mLeft;
   12619             int height = mBottom - mTop;
   12620 
   12621             mRight = right;
   12622             mRenderNode.setRight(mRight);
   12623 
   12624             sizeChange(mRight - mLeft, height, oldWidth, height);
   12625 
   12626             if (!matrixIsIdentity) {
   12627                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12628                 invalidate(true);
   12629             }
   12630             mBackgroundSizeChanged = true;
   12631             if (mForegroundInfo != null) {
   12632                 mForegroundInfo.mBoundsChanged = true;
   12633             }
   12634             invalidateParentIfNeeded();
   12635             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   12636                 // View was rejected last time it was drawn by its parent; this may have changed
   12637                 invalidateParentIfNeeded();
   12638             }
   12639         }
   12640     }
   12641 
   12642     /**
   12643      * The visual x position of this view, in pixels. This is equivalent to the
   12644      * {@link #setTranslationX(float) translationX} property plus the current
   12645      * {@link #getLeft() left} property.
   12646      *
   12647      * @return The visual x position of this view, in pixels.
   12648      */
   12649     @ViewDebug.ExportedProperty(category = "drawing")
   12650     public float getX() {
   12651         return mLeft + getTranslationX();
   12652     }
   12653 
   12654     /**
   12655      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
   12656      * {@link #setTranslationX(float) translationX} property to be the difference between
   12657      * the x value passed in and the current {@link #getLeft() left} property.
   12658      *
   12659      * @param x The visual x position of this view, in pixels.
   12660      */
   12661     public void setX(float x) {
   12662         setTranslationX(x - mLeft);
   12663     }
   12664 
   12665     /**
   12666      * The visual y position of this view, in pixels. This is equivalent to the
   12667      * {@link #setTranslationY(float) translationY} property plus the current
   12668      * {@link #getTop() top} property.
   12669      *
   12670      * @return The visual y position of this view, in pixels.
   12671      */
   12672     @ViewDebug.ExportedProperty(category = "drawing")
   12673     public float getY() {
   12674         return mTop + getTranslationY();
   12675     }
   12676 
   12677     /**
   12678      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
   12679      * {@link #setTranslationY(float) translationY} property to be the difference between
   12680      * the y value passed in and the current {@link #getTop() top} property.
   12681      *
   12682      * @param y The visual y position of this view, in pixels.
   12683      */
   12684     public void setY(float y) {
   12685         setTranslationY(y - mTop);
   12686     }
   12687 
   12688     /**
   12689      * The visual z position of this view, in pixels. This is equivalent to the
   12690      * {@link #setTranslationZ(float) translationZ} property plus the current
   12691      * {@link #getElevation() elevation} property.
   12692      *
   12693      * @return The visual z position of this view, in pixels.
   12694      */
   12695     @ViewDebug.ExportedProperty(category = "drawing")
   12696     public float getZ() {
   12697         return getElevation() + getTranslationZ();
   12698     }
   12699 
   12700     /**
   12701      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
   12702      * {@link #setTranslationZ(float) translationZ} property to be the difference between
   12703      * the x value passed in and the current {@link #getElevation() elevation} property.
   12704      *
   12705      * @param z The visual z position of this view, in pixels.
   12706      */
   12707     public void setZ(float z) {
   12708         setTranslationZ(z - getElevation());
   12709     }
   12710 
   12711     /**
   12712      * The base elevation of this view relative to its parent, in pixels.
   12713      *
   12714      * @return The base depth position of the view, in pixels.
   12715      */
   12716     @ViewDebug.ExportedProperty(category = "drawing")
   12717     public float getElevation() {
   12718         return mRenderNode.getElevation();
   12719     }
   12720 
   12721     /**
   12722      * Sets the base elevation of this view, in pixels.
   12723      *
   12724      * @attr ref android.R.styleable#View_elevation
   12725      */
   12726     public void setElevation(float elevation) {
   12727         if (elevation != getElevation()) {
   12728             invalidateViewProperty(true, false);
   12729             mRenderNode.setElevation(elevation);
   12730             invalidateViewProperty(false, true);
   12731 
   12732             invalidateParentIfNeededAndWasQuickRejected();
   12733         }
   12734     }
   12735 
   12736     /**
   12737      * The horizontal location of this view relative to its {@link #getLeft() left} position.
   12738      * This position is post-layout, in addition to wherever the object's
   12739      * layout placed it.
   12740      *
   12741      * @return The horizontal position of this view relative to its left position, in pixels.
   12742      */
   12743     @ViewDebug.ExportedProperty(category = "drawing")
   12744     public float getTranslationX() {
   12745         return mRenderNode.getTranslationX();
   12746     }
   12747 
   12748     /**
   12749      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
   12750      * This effectively positions the object post-layout, in addition to wherever the object's
   12751      * layout placed it.
   12752      *
   12753      * @param translationX The horizontal position of this view relative to its left position,
   12754      * in pixels.
   12755      *
   12756      * @attr ref android.R.styleable#View_translationX
   12757      */
   12758     public void setTranslationX(float translationX) {
   12759         if (translationX != getTranslationX()) {
   12760             invalidateViewProperty(true, false);
   12761             mRenderNode.setTranslationX(translationX);
   12762             invalidateViewProperty(false, true);
   12763 
   12764             invalidateParentIfNeededAndWasQuickRejected();
   12765             notifySubtreeAccessibilityStateChangedIfNeeded();
   12766         }
   12767     }
   12768 
   12769     /**
   12770      * The vertical location of this view relative to its {@link #getTop() top} position.
   12771      * This position is post-layout, in addition to wherever the object's
   12772      * layout placed it.
   12773      *
   12774      * @return The vertical position of this view relative to its top position,
   12775      * in pixels.
   12776      */
   12777     @ViewDebug.ExportedProperty(category = "drawing")
   12778     public float getTranslationY() {
   12779         return mRenderNode.getTranslationY();
   12780     }
   12781 
   12782     /**
   12783      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
   12784      * This effectively positions the object post-layout, in addition to wherever the object's
   12785      * layout placed it.
   12786      *
   12787      * @param translationY The vertical position of this view relative to its top position,
   12788      * in pixels.
   12789      *
   12790      * @attr ref android.R.styleable#View_translationY
   12791      */
   12792     public void setTranslationY(float translationY) {
   12793         if (translationY != getTranslationY()) {
   12794             invalidateViewProperty(true, false);
   12795             mRenderNode.setTranslationY(translationY);
   12796             invalidateViewProperty(false, true);
   12797 
   12798             invalidateParentIfNeededAndWasQuickRejected();
   12799             notifySubtreeAccessibilityStateChangedIfNeeded();
   12800         }
   12801     }
   12802 
   12803     /**
   12804      * The depth location of this view relative to its {@link #getElevation() elevation}.
   12805      *
   12806      * @return The depth of this view relative to its elevation.
   12807      */
   12808     @ViewDebug.ExportedProperty(category = "drawing")
   12809     public float getTranslationZ() {
   12810         return mRenderNode.getTranslationZ();
   12811     }
   12812 
   12813     /**
   12814      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
   12815      *
   12816      * @attr ref android.R.styleable#View_translationZ
   12817      */
   12818     public void setTranslationZ(float translationZ) {
   12819         if (translationZ != getTranslationZ()) {
   12820             invalidateViewProperty(true, false);
   12821             mRenderNode.setTranslationZ(translationZ);
   12822             invalidateViewProperty(false, true);
   12823 
   12824             invalidateParentIfNeededAndWasQuickRejected();
   12825         }
   12826     }
   12827 
   12828     /** @hide */
   12829     public void setAnimationMatrix(Matrix matrix) {
   12830         invalidateViewProperty(true, false);
   12831         mRenderNode.setAnimationMatrix(matrix);
   12832         invalidateViewProperty(false, true);
   12833 
   12834         invalidateParentIfNeededAndWasQuickRejected();
   12835     }
   12836 
   12837     /**
   12838      * Returns the current StateListAnimator if exists.
   12839      *
   12840      * @return StateListAnimator or null if it does not exists
   12841      * @see    #setStateListAnimator(android.animation.StateListAnimator)
   12842      */
   12843     public StateListAnimator getStateListAnimator() {
   12844         return mStateListAnimator;
   12845     }
   12846 
   12847     /**
   12848      * Attaches the provided StateListAnimator to this View.
   12849      * <p>
   12850      * Any previously attached StateListAnimator will be detached.
   12851      *
   12852      * @param stateListAnimator The StateListAnimator to update the view
   12853      * @see {@link android.animation.StateListAnimator}
   12854      */
   12855     public void setStateListAnimator(StateListAnimator stateListAnimator) {
   12856         if (mStateListAnimator == stateListAnimator) {
   12857             return;
   12858         }
   12859         if (mStateListAnimator != null) {
   12860             mStateListAnimator.setTarget(null);
   12861         }
   12862         mStateListAnimator = stateListAnimator;
   12863         if (stateListAnimator != null) {
   12864             stateListAnimator.setTarget(this);
   12865             if (isAttachedToWindow()) {
   12866                 stateListAnimator.setState(getDrawableState());
   12867             }
   12868         }
   12869     }
   12870 
   12871     /**
   12872      * Returns whether the Outline should be used to clip the contents of the View.
   12873      * <p>
   12874      * Note that this flag will only be respected if the View's Outline returns true from
   12875      * {@link Outline#canClip()}.
   12876      *
   12877      * @see #setOutlineProvider(ViewOutlineProvider)
   12878      * @see #setClipToOutline(boolean)
   12879      */
   12880     public final boolean getClipToOutline() {
   12881         return mRenderNode.getClipToOutline();
   12882     }
   12883 
   12884     /**
   12885      * Sets whether the View's Outline should be used to clip the contents of the View.
   12886      * <p>
   12887      * Only a single non-rectangular clip can be applied on a View at any time.
   12888      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
   12889      * circular reveal} animation take priority over Outline clipping, and
   12890      * child Outline clipping takes priority over Outline clipping done by a
   12891      * parent.
   12892      * <p>
   12893      * Note that this flag will only be respected if the View's Outline returns true from
   12894      * {@link Outline#canClip()}.
   12895      *
   12896      * @see #setOutlineProvider(ViewOutlineProvider)
   12897      * @see #getClipToOutline()
   12898      */
   12899     public void setClipToOutline(boolean clipToOutline) {
   12900         damageInParent();
   12901         if (getClipToOutline() != clipToOutline) {
   12902             mRenderNode.setClipToOutline(clipToOutline);
   12903         }
   12904     }
   12905 
   12906     // correspond to the enum values of View_outlineProvider
   12907     private static final int PROVIDER_BACKGROUND = 0;
   12908     private static final int PROVIDER_NONE = 1;
   12909     private static final int PROVIDER_BOUNDS = 2;
   12910     private static final int PROVIDER_PADDED_BOUNDS = 3;
   12911     private void setOutlineProviderFromAttribute(int providerInt) {
   12912         switch (providerInt) {
   12913             case PROVIDER_BACKGROUND:
   12914                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
   12915                 break;
   12916             case PROVIDER_NONE:
   12917                 setOutlineProvider(null);
   12918                 break;
   12919             case PROVIDER_BOUNDS:
   12920                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
   12921                 break;
   12922             case PROVIDER_PADDED_BOUNDS:
   12923                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
   12924                 break;
   12925         }
   12926     }
   12927 
   12928     /**
   12929      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
   12930      * the shape of the shadow it casts, and enables outline clipping.
   12931      * <p>
   12932      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
   12933      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
   12934      * outline provider with this method allows this behavior to be overridden.
   12935      * <p>
   12936      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
   12937      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
   12938      * <p>
   12939      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
   12940      *
   12941      * @see #setClipToOutline(boolean)
   12942      * @see #getClipToOutline()
   12943      * @see #getOutlineProvider()
   12944      */
   12945     public void setOutlineProvider(ViewOutlineProvider provider) {
   12946         mOutlineProvider = provider;
   12947         invalidateOutline();
   12948     }
   12949 
   12950     /**
   12951      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
   12952      * that defines the shape of the shadow it casts, and enables outline clipping.
   12953      *
   12954      * @see #setOutlineProvider(ViewOutlineProvider)
   12955      */
   12956     public ViewOutlineProvider getOutlineProvider() {
   12957         return mOutlineProvider;
   12958     }
   12959 
   12960     /**
   12961      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
   12962      *
   12963      * @see #setOutlineProvider(ViewOutlineProvider)
   12964      */
   12965     public void invalidateOutline() {
   12966         rebuildOutline();
   12967 
   12968         notifySubtreeAccessibilityStateChangedIfNeeded();
   12969         invalidateViewProperty(false, false);
   12970     }
   12971 
   12972     /**
   12973      * Internal version of {@link #invalidateOutline()} which invalidates the
   12974      * outline without invalidating the view itself. This is intended to be called from
   12975      * within methods in the View class itself which are the result of the view being
   12976      * invalidated already. For example, when we are drawing the background of a View,
   12977      * we invalidate the outline in case it changed in the meantime, but we do not
   12978      * need to invalidate the view because we're already drawing the background as part
   12979      * of drawing the view in response to an earlier invalidation of the view.
   12980      */
   12981     private void rebuildOutline() {
   12982         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
   12983         if (mAttachInfo == null) return;
   12984 
   12985         if (mOutlineProvider == null) {
   12986             // no provider, remove outline
   12987             mRenderNode.setOutline(null);
   12988         } else {
   12989             final Outline outline = mAttachInfo.mTmpOutline;
   12990             outline.setEmpty();
   12991             outline.setAlpha(1.0f);
   12992 
   12993             mOutlineProvider.getOutline(this, outline);
   12994             mRenderNode.setOutline(outline);
   12995         }
   12996     }
   12997 
   12998     /**
   12999      * HierarchyViewer only
   13000      *
   13001      * @hide
   13002      */
   13003     @ViewDebug.ExportedProperty(category = "drawing")
   13004     public boolean hasShadow() {
   13005         return mRenderNode.hasShadow();
   13006     }
   13007 
   13008 
   13009     /** @hide */
   13010     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
   13011         mRenderNode.setRevealClip(shouldClip, x, y, radius);
   13012         invalidateViewProperty(false, false);
   13013     }
   13014 
   13015     /**
   13016      * Hit rectangle in parent's coordinates
   13017      *
   13018      * @param outRect The hit rectangle of the view.
   13019      */
   13020     public void getHitRect(Rect outRect) {
   13021         if (hasIdentityMatrix() || mAttachInfo == null) {
   13022             outRect.set(mLeft, mTop, mRight, mBottom);
   13023         } else {
   13024             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
   13025             tmpRect.set(0, 0, getWidth(), getHeight());
   13026             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
   13027             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
   13028                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
   13029         }
   13030     }
   13031 
   13032     /**
   13033      * Determines whether the given point, in local coordinates is inside the view.
   13034      */
   13035     /*package*/ final boolean pointInView(float localX, float localY) {
   13036         return pointInView(localX, localY, 0);
   13037     }
   13038 
   13039     /**
   13040      * Utility method to determine whether the given point, in local coordinates,
   13041      * is inside the view, where the area of the view is expanded by the slop factor.
   13042      * This method is called while processing touch-move events to determine if the event
   13043      * is still within the view.
   13044      *
   13045      * @hide
   13046      */
   13047     public boolean pointInView(float localX, float localY, float slop) {
   13048         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
   13049                 localY < ((mBottom - mTop) + slop);
   13050     }
   13051 
   13052     /**
   13053      * When a view has focus and the user navigates away from it, the next view is searched for
   13054      * starting from the rectangle filled in by this method.
   13055      *
   13056      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
   13057      * of the view.  However, if your view maintains some idea of internal selection,
   13058      * such as a cursor, or a selected row or column, you should override this method and
   13059      * fill in a more specific rectangle.
   13060      *
   13061      * @param r The rectangle to fill in, in this view's coordinates.
   13062      */
   13063     public void getFocusedRect(Rect r) {
   13064         getDrawingRect(r);
   13065     }
   13066 
   13067     /**
   13068      * If some part of this view is not clipped by any of its parents, then
   13069      * return that area in r in global (root) coordinates. To convert r to local
   13070      * coordinates (without taking possible View rotations into account), offset
   13071      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
   13072      * If the view is completely clipped or translated out, return false.
   13073      *
   13074      * @param r If true is returned, r holds the global coordinates of the
   13075      *        visible portion of this view.
   13076      * @param globalOffset If true is returned, globalOffset holds the dx,dy
   13077      *        between this view and its root. globalOffet may be null.
   13078      * @return true if r is non-empty (i.e. part of the view is visible at the
   13079      *         root level.
   13080      */
   13081     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
   13082         int width = mRight - mLeft;
   13083         int height = mBottom - mTop;
   13084         if (width > 0 && height > 0) {
   13085             r.set(0, 0, width, height);
   13086             if (globalOffset != null) {
   13087                 globalOffset.set(-mScrollX, -mScrollY);
   13088             }
   13089             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
   13090         }
   13091         return false;
   13092     }
   13093 
   13094     public final boolean getGlobalVisibleRect(Rect r) {
   13095         return getGlobalVisibleRect(r, null);
   13096     }
   13097 
   13098     public final boolean getLocalVisibleRect(Rect r) {
   13099         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
   13100         if (getGlobalVisibleRect(r, offset)) {
   13101             r.offset(-offset.x, -offset.y); // make r local
   13102             return true;
   13103         }
   13104         return false;
   13105     }
   13106 
   13107     /**
   13108      * Offset this view's vertical location by the specified number of pixels.
   13109      *
   13110      * @param offset the number of pixels to offset the view by
   13111      */
   13112     public void offsetTopAndBottom(int offset) {
   13113         if (offset != 0) {
   13114             final boolean matrixIsIdentity = hasIdentityMatrix();
   13115             if (matrixIsIdentity) {
   13116                 if (isHardwareAccelerated()) {
   13117                     invalidateViewProperty(false, false);
   13118                 } else {
   13119                     final ViewParent p = mParent;
   13120                     if (p != null && mAttachInfo != null) {
   13121                         final Rect r = mAttachInfo.mTmpInvalRect;
   13122                         int minTop;
   13123                         int maxBottom;
   13124                         int yLoc;
   13125                         if (offset < 0) {
   13126                             minTop = mTop + offset;
   13127                             maxBottom = mBottom;
   13128                             yLoc = offset;
   13129                         } else {
   13130                             minTop = mTop;
   13131                             maxBottom = mBottom + offset;
   13132                             yLoc = 0;
   13133                         }
   13134                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
   13135                         p.invalidateChild(this, r);
   13136                     }
   13137                 }
   13138             } else {
   13139                 invalidateViewProperty(false, false);
   13140             }
   13141 
   13142             mTop += offset;
   13143             mBottom += offset;
   13144             mRenderNode.offsetTopAndBottom(offset);
   13145             if (isHardwareAccelerated()) {
   13146                 invalidateViewProperty(false, false);
   13147                 invalidateParentIfNeededAndWasQuickRejected();
   13148             } else {
   13149                 if (!matrixIsIdentity) {
   13150                     invalidateViewProperty(false, true);
   13151                 }
   13152                 invalidateParentIfNeeded();
   13153             }
   13154             notifySubtreeAccessibilityStateChangedIfNeeded();
   13155         }
   13156     }
   13157 
   13158     /**
   13159      * Offset this view's horizontal location by the specified amount of pixels.
   13160      *
   13161      * @param offset the number of pixels to offset the view by
   13162      */
   13163     public void offsetLeftAndRight(int offset) {
   13164         if (offset != 0) {
   13165             final boolean matrixIsIdentity = hasIdentityMatrix();
   13166             if (matrixIsIdentity) {
   13167                 if (isHardwareAccelerated()) {
   13168                     invalidateViewProperty(false, false);
   13169                 } else {
   13170                     final ViewParent p = mParent;
   13171                     if (p != null && mAttachInfo != null) {
   13172                         final Rect r = mAttachInfo.mTmpInvalRect;
   13173                         int minLeft;
   13174                         int maxRight;
   13175                         if (offset < 0) {
   13176                             minLeft = mLeft + offset;
   13177                             maxRight = mRight;
   13178                         } else {
   13179                             minLeft = mLeft;
   13180                             maxRight = mRight + offset;
   13181                         }
   13182                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
   13183                         p.invalidateChild(this, r);
   13184                     }
   13185                 }
   13186             } else {
   13187                 invalidateViewProperty(false, false);
   13188             }
   13189 
   13190             mLeft += offset;
   13191             mRight += offset;
   13192             mRenderNode.offsetLeftAndRight(offset);
   13193             if (isHardwareAccelerated()) {
   13194                 invalidateViewProperty(false, false);
   13195                 invalidateParentIfNeededAndWasQuickRejected();
   13196             } else {
   13197                 if (!matrixIsIdentity) {
   13198                     invalidateViewProperty(false, true);
   13199                 }
   13200                 invalidateParentIfNeeded();
   13201             }
   13202             notifySubtreeAccessibilityStateChangedIfNeeded();
   13203         }
   13204     }
   13205 
   13206     /**
   13207      * Get the LayoutParams associated with this view. All views should have
   13208      * layout parameters. These supply parameters to the <i>parent</i> of this
   13209      * view specifying how it should be arranged. There are many subclasses of
   13210      * ViewGroup.LayoutParams, and these correspond to the different subclasses
   13211      * of ViewGroup that are responsible for arranging their children.
   13212      *
   13213      * This method may return null if this View is not attached to a parent
   13214      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
   13215      * was not invoked successfully. When a View is attached to a parent
   13216      * ViewGroup, this method must not return null.
   13217      *
   13218      * @return The LayoutParams associated with this view, or null if no
   13219      *         parameters have been set yet
   13220      */
   13221     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
   13222     public ViewGroup.LayoutParams getLayoutParams() {
   13223         return mLayoutParams;
   13224     }
   13225 
   13226     /**
   13227      * Set the layout parameters associated with this view. These supply
   13228      * parameters to the <i>parent</i> of this view specifying how it should be
   13229      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
   13230      * correspond to the different subclasses of ViewGroup that are responsible
   13231      * for arranging their children.
   13232      *
   13233      * @param params The layout parameters for this view, cannot be null
   13234      */
   13235     public void setLayoutParams(ViewGroup.LayoutParams params) {
   13236         if (params == null) {
   13237             throw new NullPointerException("Layout parameters cannot be null");
   13238         }
   13239         mLayoutParams = params;
   13240         resolveLayoutParams();
   13241         if (mParent instanceof ViewGroup) {
   13242             ((ViewGroup) mParent).onSetLayoutParams(this, params);
   13243         }
   13244         requestLayout();
   13245     }
   13246 
   13247     /**
   13248      * Resolve the layout parameters depending on the resolved layout direction
   13249      *
   13250      * @hide
   13251      */
   13252     public void resolveLayoutParams() {
   13253         if (mLayoutParams != null) {
   13254             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
   13255         }
   13256     }
   13257 
   13258     /**
   13259      * Set the scrolled position of your view. This will cause a call to
   13260      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   13261      * invalidated.
   13262      * @param x the x position to scroll to
   13263      * @param y the y position to scroll to
   13264      */
   13265     public void scrollTo(int x, int y) {
   13266         if (mScrollX != x || mScrollY != y) {
   13267             int oldX = mScrollX;
   13268             int oldY = mScrollY;
   13269             mScrollX = x;
   13270             mScrollY = y;
   13271             invalidateParentCaches();
   13272             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
   13273             if (!awakenScrollBars()) {
   13274                 postInvalidateOnAnimation();
   13275             }
   13276         }
   13277     }
   13278 
   13279     /**
   13280      * Move the scrolled position of your view. This will cause a call to
   13281      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   13282      * invalidated.
   13283      * @param x the amount of pixels to scroll by horizontally
   13284      * @param y the amount of pixels to scroll by vertically
   13285      */
   13286     public void scrollBy(int x, int y) {
   13287         scrollTo(mScrollX + x, mScrollY + y);
   13288     }
   13289 
   13290     /**
   13291      * <p>Trigger the scrollbars to draw. When invoked this method starts an
   13292      * animation to fade the scrollbars out after a default delay. If a subclass
   13293      * provides animated scrolling, the start delay should equal the duration
   13294      * of the scrolling animation.</p>
   13295      *
   13296      * <p>The animation starts only if at least one of the scrollbars is
   13297      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
   13298      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   13299      * this method returns true, and false otherwise. If the animation is
   13300      * started, this method calls {@link #invalidate()}; in that case the
   13301      * caller should not call {@link #invalidate()}.</p>
   13302      *
   13303      * <p>This method should be invoked every time a subclass directly updates
   13304      * the scroll parameters.</p>
   13305      *
   13306      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
   13307      * and {@link #scrollTo(int, int)}.</p>
   13308      *
   13309      * @return true if the animation is played, false otherwise
   13310      *
   13311      * @see #awakenScrollBars(int)
   13312      * @see #scrollBy(int, int)
   13313      * @see #scrollTo(int, int)
   13314      * @see #isHorizontalScrollBarEnabled()
   13315      * @see #isVerticalScrollBarEnabled()
   13316      * @see #setHorizontalScrollBarEnabled(boolean)
   13317      * @see #setVerticalScrollBarEnabled(boolean)
   13318      */
   13319     protected boolean awakenScrollBars() {
   13320         return mScrollCache != null &&
   13321                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
   13322     }
   13323 
   13324     /**
   13325      * Trigger the scrollbars to draw.
   13326      * This method differs from awakenScrollBars() only in its default duration.
   13327      * initialAwakenScrollBars() will show the scroll bars for longer than
   13328      * usual to give the user more of a chance to notice them.
   13329      *
   13330      * @return true if the animation is played, false otherwise.
   13331      */
   13332     private boolean initialAwakenScrollBars() {
   13333         return mScrollCache != null &&
   13334                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
   13335     }
   13336 
   13337     /**
   13338      * <p>
   13339      * Trigger the scrollbars to draw. When invoked this method starts an
   13340      * animation to fade the scrollbars out after a fixed delay. If a subclass
   13341      * provides animated scrolling, the start delay should equal the duration of
   13342      * the scrolling animation.
   13343      * </p>
   13344      *
   13345      * <p>
   13346      * The animation starts only if at least one of the scrollbars is enabled,
   13347      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   13348      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   13349      * this method returns true, and false otherwise. If the animation is
   13350      * started, this method calls {@link #invalidate()}; in that case the caller
   13351      * should not call {@link #invalidate()}.
   13352      * </p>
   13353      *
   13354      * <p>
   13355      * This method should be invoked every time a subclass directly updates the
   13356      * scroll parameters.
   13357      * </p>
   13358      *
   13359      * @param startDelay the delay, in milliseconds, after which the animation
   13360      *        should start; when the delay is 0, the animation starts
   13361      *        immediately
   13362      * @return true if the animation is played, false otherwise
   13363      *
   13364      * @see #scrollBy(int, int)
   13365      * @see #scrollTo(int, int)
   13366      * @see #isHorizontalScrollBarEnabled()
   13367      * @see #isVerticalScrollBarEnabled()
   13368      * @see #setHorizontalScrollBarEnabled(boolean)
   13369      * @see #setVerticalScrollBarEnabled(boolean)
   13370      */
   13371     protected boolean awakenScrollBars(int startDelay) {
   13372         return awakenScrollBars(startDelay, true);
   13373     }
   13374 
   13375     /**
   13376      * <p>
   13377      * Trigger the scrollbars to draw. When invoked this method starts an
   13378      * animation to fade the scrollbars out after a fixed delay. If a subclass
   13379      * provides animated scrolling, the start delay should equal the duration of
   13380      * the scrolling animation.
   13381      * </p>
   13382      *
   13383      * <p>
   13384      * The animation starts only if at least one of the scrollbars is enabled,
   13385      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   13386      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   13387      * this method returns true, and false otherwise. If the animation is
   13388      * started, this method calls {@link #invalidate()} if the invalidate parameter
   13389      * is set to true; in that case the caller
   13390      * should not call {@link #invalidate()}.
   13391      * </p>
   13392      *
   13393      * <p>
   13394      * This method should be invoked every time a subclass directly updates the
   13395      * scroll parameters.
   13396      * </p>
   13397      *
   13398      * @param startDelay the delay, in milliseconds, after which the animation
   13399      *        should start; when the delay is 0, the animation starts
   13400      *        immediately
   13401      *
   13402      * @param invalidate Whether this method should call invalidate
   13403      *
   13404      * @return true if the animation is played, false otherwise
   13405      *
   13406      * @see #scrollBy(int, int)
   13407      * @see #scrollTo(int, int)
   13408      * @see #isHorizontalScrollBarEnabled()
   13409      * @see #isVerticalScrollBarEnabled()
   13410      * @see #setHorizontalScrollBarEnabled(boolean)
   13411      * @see #setVerticalScrollBarEnabled(boolean)
   13412      */
   13413     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
   13414         final ScrollabilityCache scrollCache = mScrollCache;
   13415 
   13416         if (scrollCache == null || !scrollCache.fadeScrollBars) {
   13417             return false;
   13418         }
   13419 
   13420         if (scrollCache.scrollBar == null) {
   13421             scrollCache.scrollBar = new ScrollBarDrawable();
   13422             scrollCache.scrollBar.setState(getDrawableState());
   13423             scrollCache.scrollBar.setCallback(this);
   13424         }
   13425 
   13426         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
   13427 
   13428             if (invalidate) {
   13429                 // Invalidate to show the scrollbars
   13430                 postInvalidateOnAnimation();
   13431             }
   13432 
   13433             if (scrollCache.state == ScrollabilityCache.OFF) {
   13434                 // FIXME: this is copied from WindowManagerService.
   13435                 // We should get this value from the system when it
   13436                 // is possible to do so.
   13437                 final int KEY_REPEAT_FIRST_DELAY = 750;
   13438                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
   13439             }
   13440 
   13441             // Tell mScrollCache when we should start fading. This may
   13442             // extend the fade start time if one was already scheduled
   13443             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
   13444             scrollCache.fadeStartTime = fadeStartTime;
   13445             scrollCache.state = ScrollabilityCache.ON;
   13446 
   13447             // Schedule our fader to run, unscheduling any old ones first
   13448             if (mAttachInfo != null) {
   13449                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
   13450                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
   13451             }
   13452 
   13453             return true;
   13454         }
   13455 
   13456         return false;
   13457     }
   13458 
   13459     /**
   13460      * Do not invalidate views which are not visible and which are not running an animation. They
   13461      * will not get drawn and they should not set dirty flags as if they will be drawn
   13462      */
   13463     private boolean skipInvalidate() {
   13464         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
   13465                 (!(mParent instanceof ViewGroup) ||
   13466                         !((ViewGroup) mParent).isViewTransitioning(this));
   13467     }
   13468 
   13469     /**
   13470      * Mark the area defined by dirty as needing to be drawn. If the view is
   13471      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   13472      * point in the future.
   13473      * <p>
   13474      * This must be called from a UI thread. To call from a non-UI thread, call
   13475      * {@link #postInvalidate()}.
   13476      * <p>
   13477      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
   13478      * {@code dirty}.
   13479      *
   13480      * @param dirty the rectangle representing the bounds of the dirty region
   13481      */
   13482     public void invalidate(Rect dirty) {
   13483         final int scrollX = mScrollX;
   13484         final int scrollY = mScrollY;
   13485         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
   13486                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
   13487     }
   13488 
   13489     /**
   13490      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
   13491      * coordinates of the dirty rect are relative to the view. If the view is
   13492      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   13493      * point in the future.
   13494      * <p>
   13495      * This must be called from a UI thread. To call from a non-UI thread, call
   13496      * {@link #postInvalidate()}.
   13497      *
   13498      * @param l the left position of the dirty region
   13499      * @param t the top position of the dirty region
   13500      * @param r the right position of the dirty region
   13501      * @param b the bottom position of the dirty region
   13502      */
   13503     public void invalidate(int l, int t, int r, int b) {
   13504         final int scrollX = mScrollX;
   13505         final int scrollY = mScrollY;
   13506         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
   13507     }
   13508 
   13509     /**
   13510      * Invalidate the whole view. If the view is visible,
   13511      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
   13512      * the future.
   13513      * <p>
   13514      * This must be called from a UI thread. To call from a non-UI thread, call
   13515      * {@link #postInvalidate()}.
   13516      */
   13517     public void invalidate() {
   13518         invalidate(true);
   13519     }
   13520 
   13521     /**
   13522      * This is where the invalidate() work actually happens. A full invalidate()
   13523      * causes the drawing cache to be invalidated, but this function can be
   13524      * called with invalidateCache set to false to skip that invalidation step
   13525      * for cases that do not need it (for example, a component that remains at
   13526      * the same dimensions with the same content).
   13527      *
   13528      * @param invalidateCache Whether the drawing cache for this view should be
   13529      *            invalidated as well. This is usually true for a full
   13530      *            invalidate, but may be set to false if the View's contents or
   13531      *            dimensions have not changed.
   13532      */
   13533     void invalidate(boolean invalidateCache) {
   13534         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
   13535     }
   13536 
   13537     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
   13538             boolean fullInvalidate) {
   13539         if (mGhostView != null) {
   13540             mGhostView.invalidate(true);
   13541             return;
   13542         }
   13543 
   13544         if (skipInvalidate()) {
   13545             return;
   13546         }
   13547 
   13548         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
   13549                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
   13550                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
   13551                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
   13552             if (fullInvalidate) {
   13553                 mLastIsOpaque = isOpaque();
   13554                 mPrivateFlags &= ~PFLAG_DRAWN;
   13555             }
   13556 
   13557             mPrivateFlags |= PFLAG_DIRTY;
   13558 
   13559             if (invalidateCache) {
   13560                 mPrivateFlags |= PFLAG_INVALIDATED;
   13561                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   13562             }
   13563 
   13564             // Propagate the damage rectangle to the parent view.
   13565             final AttachInfo ai = mAttachInfo;
   13566             final ViewParent p = mParent;
   13567             if (p != null && ai != null && l < r && t < b) {
   13568                 final Rect damage = ai.mTmpInvalRect;
   13569                 damage.set(l, t, r, b);
   13570                 p.invalidateChild(this, damage);
   13571             }
   13572 
   13573             // Damage the entire projection receiver, if necessary.
   13574             if (mBackground != null && mBackground.isProjected()) {
   13575                 final View receiver = getProjectionReceiver();
   13576                 if (receiver != null) {
   13577                     receiver.damageInParent();
   13578                 }
   13579             }
   13580 
   13581             // Damage the entire IsolatedZVolume receiving this view's shadow.
   13582             if (isHardwareAccelerated() && getZ() != 0) {
   13583                 damageShadowReceiver();
   13584             }
   13585         }
   13586     }
   13587 
   13588     /**
   13589      * @return this view's projection receiver, or {@code null} if none exists
   13590      */
   13591     private View getProjectionReceiver() {
   13592         ViewParent p = getParent();
   13593         while (p != null && p instanceof View) {
   13594             final View v = (View) p;
   13595             if (v.isProjectionReceiver()) {
   13596                 return v;
   13597             }
   13598             p = p.getParent();
   13599         }
   13600 
   13601         return null;
   13602     }
   13603 
   13604     /**
   13605      * @return whether the view is a projection receiver
   13606      */
   13607     private boolean isProjectionReceiver() {
   13608         return mBackground != null;
   13609     }
   13610 
   13611     /**
   13612      * Damage area of the screen that can be covered by this View's shadow.
   13613      *
   13614      * This method will guarantee that any changes to shadows cast by a View
   13615      * are damaged on the screen for future redraw.
   13616      */
   13617     private void damageShadowReceiver() {
   13618         final AttachInfo ai = mAttachInfo;
   13619         if (ai != null) {
   13620             ViewParent p = getParent();
   13621             if (p != null && p instanceof ViewGroup) {
   13622                 final ViewGroup vg = (ViewGroup) p;
   13623                 vg.damageInParent();
   13624             }
   13625         }
   13626     }
   13627 
   13628     /**
   13629      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
   13630      * set any flags or handle all of the cases handled by the default invalidation methods.
   13631      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
   13632      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
   13633      * walk up the hierarchy, transforming the dirty rect as necessary.
   13634      *
   13635      * The method also handles normal invalidation logic if display list properties are not
   13636      * being used in this view. The invalidateParent and forceRedraw flags are used by that
   13637      * backup approach, to handle these cases used in the various property-setting methods.
   13638      *
   13639      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
   13640      * are not being used in this view
   13641      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
   13642      * list properties are not being used in this view
   13643      */
   13644     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
   13645         if (!isHardwareAccelerated()
   13646                 || !mRenderNode.isValid()
   13647                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
   13648             if (invalidateParent) {
   13649                 invalidateParentCaches();
   13650             }
   13651             if (forceRedraw) {
   13652                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   13653             }
   13654             invalidate(false);
   13655         } else {
   13656             damageInParent();
   13657         }
   13658         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
   13659             damageShadowReceiver();
   13660         }
   13661     }
   13662 
   13663     /**
   13664      * Tells the parent view to damage this view's bounds.
   13665      *
   13666      * @hide
   13667      */
   13668     protected void damageInParent() {
   13669         final AttachInfo ai = mAttachInfo;
   13670         final ViewParent p = mParent;
   13671         if (p != null && ai != null) {
   13672             final Rect r = ai.mTmpInvalRect;
   13673             r.set(0, 0, mRight - mLeft, mBottom - mTop);
   13674             if (mParent instanceof ViewGroup) {
   13675                 ((ViewGroup) mParent).damageChild(this, r);
   13676             } else {
   13677                 mParent.invalidateChild(this, r);
   13678             }
   13679         }
   13680     }
   13681 
   13682     /**
   13683      * Utility method to transform a given Rect by the current matrix of this view.
   13684      */
   13685     void transformRect(final Rect rect) {
   13686         if (!getMatrix().isIdentity()) {
   13687             RectF boundingRect = mAttachInfo.mTmpTransformRect;
   13688             boundingRect.set(rect);
   13689             getMatrix().mapRect(boundingRect);
   13690             rect.set((int) Math.floor(boundingRect.left),
   13691                     (int) Math.floor(boundingRect.top),
   13692                     (int) Math.ceil(boundingRect.right),
   13693                     (int) Math.ceil(boundingRect.bottom));
   13694         }
   13695     }
   13696 
   13697     /**
   13698      * Used to indicate that the parent of this view should clear its caches. This functionality
   13699      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   13700      * which is necessary when various parent-managed properties of the view change, such as
   13701      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
   13702      * clears the parent caches and does not causes an invalidate event.
   13703      *
   13704      * @hide
   13705      */
   13706     protected void invalidateParentCaches() {
   13707         if (mParent instanceof View) {
   13708             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
   13709         }
   13710     }
   13711 
   13712     /**
   13713      * Used to indicate that the parent of this view should be invalidated. This functionality
   13714      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   13715      * which is necessary when various parent-managed properties of the view change, such as
   13716      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
   13717      * an invalidation event to the parent.
   13718      *
   13719      * @hide
   13720      */
   13721     protected void invalidateParentIfNeeded() {
   13722         if (isHardwareAccelerated() && mParent instanceof View) {
   13723             ((View) mParent).invalidate(true);
   13724         }
   13725     }
   13726 
   13727     /**
   13728      * @hide
   13729      */
   13730     protected void invalidateParentIfNeededAndWasQuickRejected() {
   13731         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
   13732             // View was rejected last time it was drawn by its parent; this may have changed
   13733             invalidateParentIfNeeded();
   13734         }
   13735     }
   13736 
   13737     /**
   13738      * Indicates whether this View is opaque. An opaque View guarantees that it will
   13739      * draw all the pixels overlapping its bounds using a fully opaque color.
   13740      *
   13741      * Subclasses of View should override this method whenever possible to indicate
   13742      * whether an instance is opaque. Opaque Views are treated in a special way by
   13743      * the View hierarchy, possibly allowing it to perform optimizations during
   13744      * invalidate/draw passes.
   13745      *
   13746      * @return True if this View is guaranteed to be fully opaque, false otherwise.
   13747      */
   13748     @ViewDebug.ExportedProperty(category = "drawing")
   13749     public boolean isOpaque() {
   13750         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
   13751                 getFinalAlpha() >= 1.0f;
   13752     }
   13753 
   13754     /**
   13755      * @hide
   13756      */
   13757     protected void computeOpaqueFlags() {
   13758         // Opaque if:
   13759         //   - Has a background
   13760         //   - Background is opaque
   13761         //   - Doesn't have scrollbars or scrollbars overlay
   13762 
   13763         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
   13764             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
   13765         } else {
   13766             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
   13767         }
   13768 
   13769         final int flags = mViewFlags;
   13770         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
   13771                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
   13772                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
   13773             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
   13774         } else {
   13775             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
   13776         }
   13777     }
   13778 
   13779     /**
   13780      * @hide
   13781      */
   13782     protected boolean hasOpaqueScrollbars() {
   13783         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
   13784     }
   13785 
   13786     /**
   13787      * @return A handler associated with the thread running the View. This
   13788      * handler can be used to pump events in the UI events queue.
   13789      */
   13790     public Handler getHandler() {
   13791         final AttachInfo attachInfo = mAttachInfo;
   13792         if (attachInfo != null) {
   13793             return attachInfo.mHandler;
   13794         }
   13795         return null;
   13796     }
   13797 
   13798     /**
   13799      * Returns the queue of runnable for this view.
   13800      *
   13801      * @return the queue of runnables for this view
   13802      */
   13803     private HandlerActionQueue getRunQueue() {
   13804         if (mRunQueue == null) {
   13805             mRunQueue = new HandlerActionQueue();
   13806         }
   13807         return mRunQueue;
   13808     }
   13809 
   13810     /**
   13811      * Gets the view root associated with the View.
   13812      * @return The view root, or null if none.
   13813      * @hide
   13814      */
   13815     public ViewRootImpl getViewRootImpl() {
   13816         if (mAttachInfo != null) {
   13817             return mAttachInfo.mViewRootImpl;
   13818         }
   13819         return null;
   13820     }
   13821 
   13822     /**
   13823      * @hide
   13824      */
   13825     public ThreadedRenderer getHardwareRenderer() {
   13826         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
   13827     }
   13828 
   13829     /**
   13830      * <p>Causes the Runnable to be added to the message queue.
   13831      * The runnable will be run on the user interface thread.</p>
   13832      *
   13833      * @param action The Runnable that will be executed.
   13834      *
   13835      * @return Returns true if the Runnable was successfully placed in to the
   13836      *         message queue.  Returns false on failure, usually because the
   13837      *         looper processing the message queue is exiting.
   13838      *
   13839      * @see #postDelayed
   13840      * @see #removeCallbacks
   13841      */
   13842     public boolean post(Runnable action) {
   13843         final AttachInfo attachInfo = mAttachInfo;
   13844         if (attachInfo != null) {
   13845             return attachInfo.mHandler.post(action);
   13846         }
   13847 
   13848         // Postpone the runnable until we know on which thread it needs to run.
   13849         // Assume that the runnable will be successfully placed after attach.
   13850         getRunQueue().post(action);
   13851         return true;
   13852     }
   13853 
   13854     /**
   13855      * <p>Causes the Runnable to be added to the message queue, to be run
   13856      * after the specified amount of time elapses.
   13857      * The runnable will be run on the user interface thread.</p>
   13858      *
   13859      * @param action The Runnable that will be executed.
   13860      * @param delayMillis The delay (in milliseconds) until the Runnable
   13861      *        will be executed.
   13862      *
   13863      * @return true if the Runnable was successfully placed in to the
   13864      *         message queue.  Returns false on failure, usually because the
   13865      *         looper processing the message queue is exiting.  Note that a
   13866      *         result of true does not mean the Runnable will be processed --
   13867      *         if the looper is quit before the delivery time of the message
   13868      *         occurs then the message will be dropped.
   13869      *
   13870      * @see #post
   13871      * @see #removeCallbacks
   13872      */
   13873     public boolean postDelayed(Runnable action, long delayMillis) {
   13874         final AttachInfo attachInfo = mAttachInfo;
   13875         if (attachInfo != null) {
   13876             return attachInfo.mHandler.postDelayed(action, delayMillis);
   13877         }
   13878 
   13879         // Postpone the runnable until we know on which thread it needs to run.
   13880         // Assume that the runnable will be successfully placed after attach.
   13881         getRunQueue().postDelayed(action, delayMillis);
   13882         return true;
   13883     }
   13884 
   13885     /**
   13886      * <p>Causes the Runnable to execute on the next animation time step.
   13887      * The runnable will be run on the user interface thread.</p>
   13888      *
   13889      * @param action The Runnable that will be executed.
   13890      *
   13891      * @see #postOnAnimationDelayed
   13892      * @see #removeCallbacks
   13893      */
   13894     public void postOnAnimation(Runnable action) {
   13895         final AttachInfo attachInfo = mAttachInfo;
   13896         if (attachInfo != null) {
   13897             attachInfo.mViewRootImpl.mChoreographer.postCallback(
   13898                     Choreographer.CALLBACK_ANIMATION, action, null);
   13899         } else {
   13900             // Postpone the runnable until we know
   13901             // on which thread it needs to run.
   13902             getRunQueue().post(action);
   13903         }
   13904     }
   13905 
   13906     /**
   13907      * <p>Causes the Runnable to execute on the next animation time step,
   13908      * after the specified amount of time elapses.
   13909      * The runnable will be run on the user interface thread.</p>
   13910      *
   13911      * @param action The Runnable that will be executed.
   13912      * @param delayMillis The delay (in milliseconds) until the Runnable
   13913      *        will be executed.
   13914      *
   13915      * @see #postOnAnimation
   13916      * @see #removeCallbacks
   13917      */
   13918     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
   13919         final AttachInfo attachInfo = mAttachInfo;
   13920         if (attachInfo != null) {
   13921             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   13922                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
   13923         } else {
   13924             // Postpone the runnable until we know
   13925             // on which thread it needs to run.
   13926             getRunQueue().postDelayed(action, delayMillis);
   13927         }
   13928     }
   13929 
   13930     /**
   13931      * <p>Removes the specified Runnable from the message queue.</p>
   13932      *
   13933      * @param action The Runnable to remove from the message handling queue
   13934      *
   13935      * @return true if this view could ask the Handler to remove the Runnable,
   13936      *         false otherwise. When the returned value is true, the Runnable
   13937      *         may or may not have been actually removed from the message queue
   13938      *         (for instance, if the Runnable was not in the queue already.)
   13939      *
   13940      * @see #post
   13941      * @see #postDelayed
   13942      * @see #postOnAnimation
   13943      * @see #postOnAnimationDelayed
   13944      */
   13945     public boolean removeCallbacks(Runnable action) {
   13946         if (action != null) {
   13947             final AttachInfo attachInfo = mAttachInfo;
   13948             if (attachInfo != null) {
   13949                 attachInfo.mHandler.removeCallbacks(action);
   13950                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   13951                         Choreographer.CALLBACK_ANIMATION, action, null);
   13952             }
   13953             getRunQueue().removeCallbacks(action);
   13954         }
   13955         return true;
   13956     }
   13957 
   13958     /**
   13959      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
   13960      * Use this to invalidate the View from a non-UI thread.</p>
   13961      *
   13962      * <p>This method can be invoked from outside of the UI thread
   13963      * only when this View is attached to a window.</p>
   13964      *
   13965      * @see #invalidate()
   13966      * @see #postInvalidateDelayed(long)
   13967      */
   13968     public void postInvalidate() {
   13969         postInvalidateDelayed(0);
   13970     }
   13971 
   13972     /**
   13973      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   13974      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
   13975      *
   13976      * <p>This method can be invoked from outside of the UI thread
   13977      * only when this View is attached to a window.</p>
   13978      *
   13979      * @param left The left coordinate of the rectangle to invalidate.
   13980      * @param top The top coordinate of the rectangle to invalidate.
   13981      * @param right The right coordinate of the rectangle to invalidate.
   13982      * @param bottom The bottom coordinate of the rectangle to invalidate.
   13983      *
   13984      * @see #invalidate(int, int, int, int)
   13985      * @see #invalidate(Rect)
   13986      * @see #postInvalidateDelayed(long, int, int, int, int)
   13987      */
   13988     public void postInvalidate(int left, int top, int right, int bottom) {
   13989         postInvalidateDelayed(0, left, top, right, bottom);
   13990     }
   13991 
   13992     /**
   13993      * <p>Cause an invalidate to happen on a subsequent cycle through the event
   13994      * loop. Waits for the specified amount of time.</p>
   13995      *
   13996      * <p>This method can be invoked from outside of the UI thread
   13997      * only when this View is attached to a window.</p>
   13998      *
   13999      * @param delayMilliseconds the duration in milliseconds to delay the
   14000      *         invalidation by
   14001      *
   14002      * @see #invalidate()
   14003      * @see #postInvalidate()
   14004      */
   14005     public void postInvalidateDelayed(long delayMilliseconds) {
   14006         // We try only with the AttachInfo because there's no point in invalidating
   14007         // if we are not attached to our window
   14008         final AttachInfo attachInfo = mAttachInfo;
   14009         if (attachInfo != null) {
   14010             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
   14011         }
   14012     }
   14013 
   14014     /**
   14015      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   14016      * through the event loop. Waits for the specified amount of time.</p>
   14017      *
   14018      * <p>This method can be invoked from outside of the UI thread
   14019      * only when this View is attached to a window.</p>
   14020      *
   14021      * @param delayMilliseconds the duration in milliseconds to delay the
   14022      *         invalidation by
   14023      * @param left The left coordinate of the rectangle to invalidate.
   14024      * @param top The top coordinate of the rectangle to invalidate.
   14025      * @param right The right coordinate of the rectangle to invalidate.
   14026      * @param bottom The bottom coordinate of the rectangle to invalidate.
   14027      *
   14028      * @see #invalidate(int, int, int, int)
   14029      * @see #invalidate(Rect)
   14030      * @see #postInvalidate(int, int, int, int)
   14031      */
   14032     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
   14033             int right, int bottom) {
   14034 
   14035         // We try only with the AttachInfo because there's no point in invalidating
   14036         // if we are not attached to our window
   14037         final AttachInfo attachInfo = mAttachInfo;
   14038         if (attachInfo != null) {
   14039             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   14040             info.target = this;
   14041             info.left = left;
   14042             info.top = top;
   14043             info.right = right;
   14044             info.bottom = bottom;
   14045 
   14046             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
   14047         }
   14048     }
   14049 
   14050     /**
   14051      * <p>Cause an invalidate to happen on the next animation time step, typically the
   14052      * next display frame.</p>
   14053      *
   14054      * <p>This method can be invoked from outside of the UI thread
   14055      * only when this View is attached to a window.</p>
   14056      *
   14057      * @see #invalidate()
   14058      */
   14059     public void postInvalidateOnAnimation() {
   14060         // We try only with the AttachInfo because there's no point in invalidating
   14061         // if we are not attached to our window
   14062         final AttachInfo attachInfo = mAttachInfo;
   14063         if (attachInfo != null) {
   14064             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
   14065         }
   14066     }
   14067 
   14068     /**
   14069      * <p>Cause an invalidate of the specified area to happen on the next animation
   14070      * time step, typically the next display frame.</p>
   14071      *
   14072      * <p>This method can be invoked from outside of the UI thread
   14073      * only when this View is attached to a window.</p>
   14074      *
   14075      * @param left The left coordinate of the rectangle to invalidate.
   14076      * @param top The top coordinate of the rectangle to invalidate.
   14077      * @param right The right coordinate of the rectangle to invalidate.
   14078      * @param bottom The bottom coordinate of the rectangle to invalidate.
   14079      *
   14080      * @see #invalidate(int, int, int, int)
   14081      * @see #invalidate(Rect)
   14082      */
   14083     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
   14084         // We try only with the AttachInfo because there's no point in invalidating
   14085         // if we are not attached to our window
   14086         final AttachInfo attachInfo = mAttachInfo;
   14087         if (attachInfo != null) {
   14088             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   14089             info.target = this;
   14090             info.left = left;
   14091             info.top = top;
   14092             info.right = right;
   14093             info.bottom = bottom;
   14094 
   14095             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
   14096         }
   14097     }
   14098 
   14099     /**
   14100      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
   14101      * This event is sent at most once every
   14102      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
   14103      */
   14104     private void postSendViewScrolledAccessibilityEventCallback() {
   14105         if (mSendViewScrolledAccessibilityEvent == null) {
   14106             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
   14107         }
   14108         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
   14109             mSendViewScrolledAccessibilityEvent.mIsPending = true;
   14110             postDelayed(mSendViewScrolledAccessibilityEvent,
   14111                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
   14112         }
   14113     }
   14114 
   14115     /**
   14116      * Called by a parent to request that a child update its values for mScrollX
   14117      * and mScrollY if necessary. This will typically be done if the child is
   14118      * animating a scroll using a {@link android.widget.Scroller Scroller}
   14119      * object.
   14120      */
   14121     public void computeScroll() {
   14122     }
   14123 
   14124     /**
   14125      * <p>Indicate whether the horizontal edges are faded when the view is
   14126      * scrolled horizontally.</p>
   14127      *
   14128      * @return true if the horizontal edges should are faded on scroll, false
   14129      *         otherwise
   14130      *
   14131      * @see #setHorizontalFadingEdgeEnabled(boolean)
   14132      *
   14133      * @attr ref android.R.styleable#View_requiresFadingEdge
   14134      */
   14135     public boolean isHorizontalFadingEdgeEnabled() {
   14136         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
   14137     }
   14138 
   14139     /**
   14140      * <p>Define whether the horizontal edges should be faded when this view
   14141      * is scrolled horizontally.</p>
   14142      *
   14143      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
   14144      *                                    be faded when the view is scrolled
   14145      *                                    horizontally
   14146      *
   14147      * @see #isHorizontalFadingEdgeEnabled()
   14148      *
   14149      * @attr ref android.R.styleable#View_requiresFadingEdge
   14150      */
   14151     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
   14152         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
   14153             if (horizontalFadingEdgeEnabled) {
   14154                 initScrollCache();
   14155             }
   14156 
   14157             mViewFlags ^= FADING_EDGE_HORIZONTAL;
   14158         }
   14159     }
   14160 
   14161     /**
   14162      * <p>Indicate whether the vertical edges are faded when the view is
   14163      * scrolled horizontally.</p>
   14164      *
   14165      * @return true if the vertical edges should are faded on scroll, false
   14166      *         otherwise
   14167      *
   14168      * @see #setVerticalFadingEdgeEnabled(boolean)
   14169      *
   14170      * @attr ref android.R.styleable#View_requiresFadingEdge
   14171      */
   14172     public boolean isVerticalFadingEdgeEnabled() {
   14173         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
   14174     }
   14175 
   14176     /**
   14177      * <p>Define whether the vertical edges should be faded when this view
   14178      * is scrolled vertically.</p>
   14179      *
   14180      * @param verticalFadingEdgeEnabled true if the vertical edges should
   14181      *                                  be faded when the view is scrolled
   14182      *                                  vertically
   14183      *
   14184      * @see #isVerticalFadingEdgeEnabled()
   14185      *
   14186      * @attr ref android.R.styleable#View_requiresFadingEdge
   14187      */
   14188     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
   14189         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
   14190             if (verticalFadingEdgeEnabled) {
   14191                 initScrollCache();
   14192             }
   14193 
   14194             mViewFlags ^= FADING_EDGE_VERTICAL;
   14195         }
   14196     }
   14197 
   14198     /**
   14199      * Returns the strength, or intensity, of the top faded edge. The strength is
   14200      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   14201      * returns 0.0 or 1.0 but no value in between.
   14202      *
   14203      * Subclasses should override this method to provide a smoother fade transition
   14204      * when scrolling occurs.
   14205      *
   14206      * @return the intensity of the top fade as a float between 0.0f and 1.0f
   14207      */
   14208     protected float getTopFadingEdgeStrength() {
   14209         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
   14210     }
   14211 
   14212     /**
   14213      * Returns the strength, or intensity, of the bottom faded edge. The strength is
   14214      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   14215      * returns 0.0 or 1.0 but no value in between.
   14216      *
   14217      * Subclasses should override this method to provide a smoother fade transition
   14218      * when scrolling occurs.
   14219      *
   14220      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
   14221      */
   14222     protected float getBottomFadingEdgeStrength() {
   14223         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
   14224                 computeVerticalScrollRange() ? 1.0f : 0.0f;
   14225     }
   14226 
   14227     /**
   14228      * Returns the strength, or intensity, of the left faded edge. The strength is
   14229      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   14230      * returns 0.0 or 1.0 but no value in between.
   14231      *
   14232      * Subclasses should override this method to provide a smoother fade transition
   14233      * when scrolling occurs.
   14234      *
   14235      * @return the intensity of the left fade as a float between 0.0f and 1.0f
   14236      */
   14237     protected float getLeftFadingEdgeStrength() {
   14238         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
   14239     }
   14240 
   14241     /**
   14242      * Returns the strength, or intensity, of the right faded edge. The strength is
   14243      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   14244      * returns 0.0 or 1.0 but no value in between.
   14245      *
   14246      * Subclasses should override this method to provide a smoother fade transition
   14247      * when scrolling occurs.
   14248      *
   14249      * @return the intensity of the right fade as a float between 0.0f and 1.0f
   14250      */
   14251     protected float getRightFadingEdgeStrength() {
   14252         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
   14253                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
   14254     }
   14255 
   14256     /**
   14257      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
   14258      * scrollbar is not drawn by default.</p>
   14259      *
   14260      * @return true if the horizontal scrollbar should be painted, false
   14261      *         otherwise
   14262      *
   14263      * @see #setHorizontalScrollBarEnabled(boolean)
   14264      */
   14265     public boolean isHorizontalScrollBarEnabled() {
   14266         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   14267     }
   14268 
   14269     /**
   14270      * <p>Define whether the horizontal scrollbar should be drawn or not. The
   14271      * scrollbar is not drawn by default.</p>
   14272      *
   14273      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
   14274      *                                   be painted
   14275      *
   14276      * @see #isHorizontalScrollBarEnabled()
   14277      */
   14278     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
   14279         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
   14280             mViewFlags ^= SCROLLBARS_HORIZONTAL;
   14281             computeOpaqueFlags();
   14282             resolvePadding();
   14283         }
   14284     }
   14285 
   14286     /**
   14287      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
   14288      * scrollbar is not drawn by default.</p>
   14289      *
   14290      * @return true if the vertical scrollbar should be painted, false
   14291      *         otherwise
   14292      *
   14293      * @see #setVerticalScrollBarEnabled(boolean)
   14294      */
   14295     public boolean isVerticalScrollBarEnabled() {
   14296         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
   14297     }
   14298 
   14299     /**
   14300      * <p>Define whether the vertical scrollbar should be drawn or not. The
   14301      * scrollbar is not drawn by default.</p>
   14302      *
   14303      * @param verticalScrollBarEnabled true if the vertical scrollbar should
   14304      *                                 be painted
   14305      *
   14306      * @see #isVerticalScrollBarEnabled()
   14307      */
   14308     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
   14309         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
   14310             mViewFlags ^= SCROLLBARS_VERTICAL;
   14311             computeOpaqueFlags();
   14312             resolvePadding();
   14313         }
   14314     }
   14315 
   14316     /**
   14317      * @hide
   14318      */
   14319     protected void recomputePadding() {
   14320         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   14321     }
   14322 
   14323     /**
   14324      * Define whether scrollbars will fade when the view is not scrolling.
   14325      *
   14326      * @param fadeScrollbars whether to enable fading
   14327      *
   14328      * @attr ref android.R.styleable#View_fadeScrollbars
   14329      */
   14330     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
   14331         initScrollCache();
   14332         final ScrollabilityCache scrollabilityCache = mScrollCache;
   14333         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   14334         if (fadeScrollbars) {
   14335             scrollabilityCache.state = ScrollabilityCache.OFF;
   14336         } else {
   14337             scrollabilityCache.state = ScrollabilityCache.ON;
   14338         }
   14339     }
   14340 
   14341     /**
   14342      *
   14343      * Returns true if scrollbars will fade when this view is not scrolling
   14344      *
   14345      * @return true if scrollbar fading is enabled
   14346      *
   14347      * @attr ref android.R.styleable#View_fadeScrollbars
   14348      */
   14349     public boolean isScrollbarFadingEnabled() {
   14350         return mScrollCache != null && mScrollCache.fadeScrollBars;
   14351     }
   14352 
   14353     /**
   14354      *
   14355      * Returns the delay before scrollbars fade.
   14356      *
   14357      * @return the delay before scrollbars fade
   14358      *
   14359      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   14360      */
   14361     public int getScrollBarDefaultDelayBeforeFade() {
   14362         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
   14363                 mScrollCache.scrollBarDefaultDelayBeforeFade;
   14364     }
   14365 
   14366     /**
   14367      * Define the delay before scrollbars fade.
   14368      *
   14369      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
   14370      *
   14371      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   14372      */
   14373     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
   14374         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
   14375     }
   14376 
   14377     /**
   14378      *
   14379      * Returns the scrollbar fade duration.
   14380      *
   14381      * @return the scrollbar fade duration
   14382      *
   14383      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   14384      */
   14385     public int getScrollBarFadeDuration() {
   14386         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
   14387                 mScrollCache.scrollBarFadeDuration;
   14388     }
   14389 
   14390     /**
   14391      * Define the scrollbar fade duration.
   14392      *
   14393      * @param scrollBarFadeDuration - the scrollbar fade duration
   14394      *
   14395      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   14396      */
   14397     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
   14398         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
   14399     }
   14400 
   14401     /**
   14402      *
   14403      * Returns the scrollbar size.
   14404      *
   14405      * @return the scrollbar size
   14406      *
   14407      * @attr ref android.R.styleable#View_scrollbarSize
   14408      */
   14409     public int getScrollBarSize() {
   14410         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
   14411                 mScrollCache.scrollBarSize;
   14412     }
   14413 
   14414     /**
   14415      * Define the scrollbar size.
   14416      *
   14417      * @param scrollBarSize - the scrollbar size
   14418      *
   14419      * @attr ref android.R.styleable#View_scrollbarSize
   14420      */
   14421     public void setScrollBarSize(int scrollBarSize) {
   14422         getScrollCache().scrollBarSize = scrollBarSize;
   14423     }
   14424 
   14425     /**
   14426      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
   14427      * inset. When inset, they add to the padding of the view. And the scrollbars
   14428      * can be drawn inside the padding area or on the edge of the view. For example,
   14429      * if a view has a background drawable and you want to draw the scrollbars
   14430      * inside the padding specified by the drawable, you can use
   14431      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
   14432      * appear at the edge of the view, ignoring the padding, then you can use
   14433      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
   14434      * @param style the style of the scrollbars. Should be one of
   14435      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
   14436      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
   14437      * @see #SCROLLBARS_INSIDE_OVERLAY
   14438      * @see #SCROLLBARS_INSIDE_INSET
   14439      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   14440      * @see #SCROLLBARS_OUTSIDE_INSET
   14441      *
   14442      * @attr ref android.R.styleable#View_scrollbarStyle
   14443      */
   14444     public void setScrollBarStyle(@ScrollBarStyle int style) {
   14445         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
   14446             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
   14447             computeOpaqueFlags();
   14448             resolvePadding();
   14449         }
   14450     }
   14451 
   14452     /**
   14453      * <p>Returns the current scrollbar style.</p>
   14454      * @return the current scrollbar style
   14455      * @see #SCROLLBARS_INSIDE_OVERLAY
   14456      * @see #SCROLLBARS_INSIDE_INSET
   14457      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   14458      * @see #SCROLLBARS_OUTSIDE_INSET
   14459      *
   14460      * @attr ref android.R.styleable#View_scrollbarStyle
   14461      */
   14462     @ViewDebug.ExportedProperty(mapping = {
   14463             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
   14464             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
   14465             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
   14466             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
   14467     })
   14468     @ScrollBarStyle
   14469     public int getScrollBarStyle() {
   14470         return mViewFlags & SCROLLBARS_STYLE_MASK;
   14471     }
   14472 
   14473     /**
   14474      * <p>Compute the horizontal range that the horizontal scrollbar
   14475      * represents.</p>
   14476      *
   14477      * <p>The range is expressed in arbitrary units that must be the same as the
   14478      * units used by {@link #computeHorizontalScrollExtent()} and
   14479      * {@link #computeHorizontalScrollOffset()}.</p>
   14480      *
   14481      * <p>The default range is the drawing width of this view.</p>
   14482      *
   14483      * @return the total horizontal range represented by the horizontal
   14484      *         scrollbar
   14485      *
   14486      * @see #computeHorizontalScrollExtent()
   14487      * @see #computeHorizontalScrollOffset()
   14488      * @see android.widget.ScrollBarDrawable
   14489      */
   14490     protected int computeHorizontalScrollRange() {
   14491         return getWidth();
   14492     }
   14493 
   14494     /**
   14495      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
   14496      * within the horizontal range. This value is used to compute the position
   14497      * of the thumb within the scrollbar's track.</p>
   14498      *
   14499      * <p>The range is expressed in arbitrary units that must be the same as the
   14500      * units used by {@link #computeHorizontalScrollRange()} and
   14501      * {@link #computeHorizontalScrollExtent()}.</p>
   14502      *
   14503      * <p>The default offset is the scroll offset of this view.</p>
   14504      *
   14505      * @return the horizontal offset of the scrollbar's thumb
   14506      *
   14507      * @see #computeHorizontalScrollRange()
   14508      * @see #computeHorizontalScrollExtent()
   14509      * @see android.widget.ScrollBarDrawable
   14510      */
   14511     protected int computeHorizontalScrollOffset() {
   14512         return mScrollX;
   14513     }
   14514 
   14515     /**
   14516      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
   14517      * within the horizontal range. This value is used to compute the length
   14518      * of the thumb within the scrollbar's track.</p>
   14519      *
   14520      * <p>The range is expressed in arbitrary units that must be the same as the
   14521      * units used by {@link #computeHorizontalScrollRange()} and
   14522      * {@link #computeHorizontalScrollOffset()}.</p>
   14523      *
   14524      * <p>The default extent is the drawing width of this view.</p>
   14525      *
   14526      * @return the horizontal extent of the scrollbar's thumb
   14527      *
   14528      * @see #computeHorizontalScrollRange()
   14529      * @see #computeHorizontalScrollOffset()
   14530      * @see android.widget.ScrollBarDrawable
   14531      */
   14532     protected int computeHorizontalScrollExtent() {
   14533         return getWidth();
   14534     }
   14535 
   14536     /**
   14537      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
   14538      *
   14539      * <p>The range is expressed in arbitrary units that must be the same as the
   14540      * units used by {@link #computeVerticalScrollExtent()} and
   14541      * {@link #computeVerticalScrollOffset()}.</p>
   14542      *
   14543      * @return the total vertical range represented by the vertical scrollbar
   14544      *
   14545      * <p>The default range is the drawing height of this view.</p>
   14546      *
   14547      * @see #computeVerticalScrollExtent()
   14548      * @see #computeVerticalScrollOffset()
   14549      * @see android.widget.ScrollBarDrawable
   14550      */
   14551     protected int computeVerticalScrollRange() {
   14552         return getHeight();
   14553     }
   14554 
   14555     /**
   14556      * <p>Compute the vertical offset of the vertical scrollbar's thumb
   14557      * within the horizontal range. This value is used to compute the position
   14558      * of the thumb within the scrollbar's track.</p>
   14559      *
   14560      * <p>The range is expressed in arbitrary units that must be the same as the
   14561      * units used by {@link #computeVerticalScrollRange()} and
   14562      * {@link #computeVerticalScrollExtent()}.</p>
   14563      *
   14564      * <p>The default offset is the scroll offset of this view.</p>
   14565      *
   14566      * @return the vertical offset of the scrollbar's thumb
   14567      *
   14568      * @see #computeVerticalScrollRange()
   14569      * @see #computeVerticalScrollExtent()
   14570      * @see android.widget.ScrollBarDrawable
   14571      */
   14572     protected int computeVerticalScrollOffset() {
   14573         return mScrollY;
   14574     }
   14575 
   14576     /**
   14577      * <p>Compute the vertical extent of the vertical scrollbar's thumb
   14578      * within the vertical range. This value is used to compute the length
   14579      * of the thumb within the scrollbar's track.</p>
   14580      *
   14581      * <p>The range is expressed in arbitrary units that must be the same as the
   14582      * units used by {@link #computeVerticalScrollRange()} and
   14583      * {@link #computeVerticalScrollOffset()}.</p>
   14584      *
   14585      * <p>The default extent is the drawing height of this view.</p>
   14586      *
   14587      * @return the vertical extent of the scrollbar's thumb
   14588      *
   14589      * @see #computeVerticalScrollRange()
   14590      * @see #computeVerticalScrollOffset()
   14591      * @see android.widget.ScrollBarDrawable
   14592      */
   14593     protected int computeVerticalScrollExtent() {
   14594         return getHeight();
   14595     }
   14596 
   14597     /**
   14598      * Check if this view can be scrolled horizontally in a certain direction.
   14599      *
   14600      * @param direction Negative to check scrolling left, positive to check scrolling right.
   14601      * @return true if this view can be scrolled in the specified direction, false otherwise.
   14602      */
   14603     public boolean canScrollHorizontally(int direction) {
   14604         final int offset = computeHorizontalScrollOffset();
   14605         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
   14606         if (range == 0) return false;
   14607         if (direction < 0) {
   14608             return offset > 0;
   14609         } else {
   14610             return offset < range - 1;
   14611         }
   14612     }
   14613 
   14614     /**
   14615      * Check if this view can be scrolled vertically in a certain direction.
   14616      *
   14617      * @param direction Negative to check scrolling up, positive to check scrolling down.
   14618      * @return true if this view can be scrolled in the specified direction, false otherwise.
   14619      */
   14620     public boolean canScrollVertically(int direction) {
   14621         final int offset = computeVerticalScrollOffset();
   14622         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
   14623         if (range == 0) return false;
   14624         if (direction < 0) {
   14625             return offset > 0;
   14626         } else {
   14627             return offset < range - 1;
   14628         }
   14629     }
   14630 
   14631     void getScrollIndicatorBounds(@NonNull Rect out) {
   14632         out.left = mScrollX;
   14633         out.right = mScrollX + mRight - mLeft;
   14634         out.top = mScrollY;
   14635         out.bottom = mScrollY + mBottom - mTop;
   14636     }
   14637 
   14638     private void onDrawScrollIndicators(Canvas c) {
   14639         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
   14640             // No scroll indicators enabled.
   14641             return;
   14642         }
   14643 
   14644         final Drawable dr = mScrollIndicatorDrawable;
   14645         if (dr == null) {
   14646             // Scroll indicators aren't supported here.
   14647             return;
   14648         }
   14649 
   14650         final int h = dr.getIntrinsicHeight();
   14651         final int w = dr.getIntrinsicWidth();
   14652         final Rect rect = mAttachInfo.mTmpInvalRect;
   14653         getScrollIndicatorBounds(rect);
   14654 
   14655         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
   14656             final boolean canScrollUp = canScrollVertically(-1);
   14657             if (canScrollUp) {
   14658                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
   14659                 dr.draw(c);
   14660             }
   14661         }
   14662 
   14663         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
   14664             final boolean canScrollDown = canScrollVertically(1);
   14665             if (canScrollDown) {
   14666                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
   14667                 dr.draw(c);
   14668             }
   14669         }
   14670 
   14671         final int leftRtl;
   14672         final int rightRtl;
   14673         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   14674             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
   14675             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
   14676         } else {
   14677             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
   14678             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
   14679         }
   14680 
   14681         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
   14682         if ((mPrivateFlags3 & leftMask) != 0) {
   14683             final boolean canScrollLeft = canScrollHorizontally(-1);
   14684             if (canScrollLeft) {
   14685                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
   14686                 dr.draw(c);
   14687             }
   14688         }
   14689 
   14690         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
   14691         if ((mPrivateFlags3 & rightMask) != 0) {
   14692             final boolean canScrollRight = canScrollHorizontally(1);
   14693             if (canScrollRight) {
   14694                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
   14695                 dr.draw(c);
   14696             }
   14697         }
   14698     }
   14699 
   14700     private void getHorizontalScrollBarBounds(Rect bounds) {
   14701         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   14702         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
   14703                 && !isVerticalScrollBarHidden();
   14704         final int size = getHorizontalScrollbarHeight();
   14705         final int verticalScrollBarGap = drawVerticalScrollBar ?
   14706                 getVerticalScrollbarWidth() : 0;
   14707         final int width = mRight - mLeft;
   14708         final int height = mBottom - mTop;
   14709         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
   14710         bounds.left = mScrollX + (mPaddingLeft & inside);
   14711         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
   14712         bounds.bottom = bounds.top + size;
   14713     }
   14714 
   14715     private void getVerticalScrollBarBounds(Rect bounds) {
   14716         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   14717         final int size = getVerticalScrollbarWidth();
   14718         int verticalScrollbarPosition = mVerticalScrollbarPosition;
   14719         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
   14720             verticalScrollbarPosition = isLayoutRtl() ?
   14721                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
   14722         }
   14723         final int width = mRight - mLeft;
   14724         final int height = mBottom - mTop;
   14725         switch (verticalScrollbarPosition) {
   14726             default:
   14727             case SCROLLBAR_POSITION_RIGHT:
   14728                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
   14729                 break;
   14730             case SCROLLBAR_POSITION_LEFT:
   14731                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
   14732                 break;
   14733         }
   14734         bounds.top = mScrollY + (mPaddingTop & inside);
   14735         bounds.right = bounds.left + size;
   14736         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
   14737     }
   14738 
   14739     /**
   14740      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
   14741      * scrollbars are painted only if they have been awakened first.</p>
   14742      *
   14743      * @param canvas the canvas on which to draw the scrollbars
   14744      *
   14745      * @see #awakenScrollBars(int)
   14746      */
   14747     protected final void onDrawScrollBars(Canvas canvas) {
   14748         // scrollbars are drawn only when the animation is running
   14749         final ScrollabilityCache cache = mScrollCache;
   14750         if (cache != null) {
   14751 
   14752             int state = cache.state;
   14753 
   14754             if (state == ScrollabilityCache.OFF) {
   14755                 return;
   14756             }
   14757 
   14758             boolean invalidate = false;
   14759 
   14760             if (state == ScrollabilityCache.FADING) {
   14761                 // We're fading -- get our fade interpolation
   14762                 if (cache.interpolatorValues == null) {
   14763                     cache.interpolatorValues = new float[1];
   14764                 }
   14765 
   14766                 float[] values = cache.interpolatorValues;
   14767 
   14768                 // Stops the animation if we're done
   14769                 if (cache.scrollBarInterpolator.timeToValues(values) ==
   14770                         Interpolator.Result.FREEZE_END) {
   14771                     cache.state = ScrollabilityCache.OFF;
   14772                 } else {
   14773                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
   14774                 }
   14775 
   14776                 // This will make the scroll bars inval themselves after
   14777                 // drawing. We only want this when we're fading so that
   14778                 // we prevent excessive redraws
   14779                 invalidate = true;
   14780             } else {
   14781                 // We're just on -- but we may have been fading before so
   14782                 // reset alpha
   14783                 cache.scrollBar.mutate().setAlpha(255);
   14784             }
   14785 
   14786             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
   14787             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
   14788                     && !isVerticalScrollBarHidden();
   14789 
   14790             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
   14791                 final ScrollBarDrawable scrollBar = cache.scrollBar;
   14792 
   14793                 if (drawHorizontalScrollBar) {
   14794                     scrollBar.setParameters(computeHorizontalScrollRange(),
   14795                                             computeHorizontalScrollOffset(),
   14796                                             computeHorizontalScrollExtent(), false);
   14797                     final Rect bounds = cache.mScrollBarBounds;
   14798                     getHorizontalScrollBarBounds(bounds);
   14799                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
   14800                             bounds.right, bounds.bottom);
   14801                     if (invalidate) {
   14802                         invalidate(bounds);
   14803                     }
   14804                 }
   14805 
   14806                 if (drawVerticalScrollBar) {
   14807                     scrollBar.setParameters(computeVerticalScrollRange(),
   14808                                             computeVerticalScrollOffset(),
   14809                                             computeVerticalScrollExtent(), true);
   14810                     final Rect bounds = cache.mScrollBarBounds;
   14811                     getVerticalScrollBarBounds(bounds);
   14812                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
   14813                             bounds.right, bounds.bottom);
   14814                     if (invalidate) {
   14815                         invalidate(bounds);
   14816                     }
   14817                 }
   14818             }
   14819         }
   14820     }
   14821 
   14822     /**
   14823      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
   14824      * FastScroller is visible.
   14825      * @return whether to temporarily hide the vertical scrollbar
   14826      * @hide
   14827      */
   14828     protected boolean isVerticalScrollBarHidden() {
   14829         return false;
   14830     }
   14831 
   14832     /**
   14833      * <p>Draw the horizontal scrollbar if
   14834      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
   14835      *
   14836      * @param canvas the canvas on which to draw the scrollbar
   14837      * @param scrollBar the scrollbar's drawable
   14838      *
   14839      * @see #isHorizontalScrollBarEnabled()
   14840      * @see #computeHorizontalScrollRange()
   14841      * @see #computeHorizontalScrollExtent()
   14842      * @see #computeHorizontalScrollOffset()
   14843      * @see android.widget.ScrollBarDrawable
   14844      * @hide
   14845      */
   14846     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
   14847             int l, int t, int r, int b) {
   14848         scrollBar.setBounds(l, t, r, b);
   14849         scrollBar.draw(canvas);
   14850     }
   14851 
   14852     /**
   14853      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
   14854      * returns true.</p>
   14855      *
   14856      * @param canvas the canvas on which to draw the scrollbar
   14857      * @param scrollBar the scrollbar's drawable
   14858      *
   14859      * @see #isVerticalScrollBarEnabled()
   14860      * @see #computeVerticalScrollRange()
   14861      * @see #computeVerticalScrollExtent()
   14862      * @see #computeVerticalScrollOffset()
   14863      * @see android.widget.ScrollBarDrawable
   14864      * @hide
   14865      */
   14866     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
   14867             int l, int t, int r, int b) {
   14868         scrollBar.setBounds(l, t, r, b);
   14869         scrollBar.draw(canvas);
   14870     }
   14871 
   14872     /**
   14873      * Implement this to do your drawing.
   14874      *
   14875      * @param canvas the canvas on which the background will be drawn
   14876      */
   14877     protected void onDraw(Canvas canvas) {
   14878     }
   14879 
   14880     /*
   14881      * Caller is responsible for calling requestLayout if necessary.
   14882      * (This allows addViewInLayout to not request a new layout.)
   14883      */
   14884     void assignParent(ViewParent parent) {
   14885         if (mParent == null) {
   14886             mParent = parent;
   14887         } else if (parent == null) {
   14888             mParent = null;
   14889         } else {
   14890             throw new RuntimeException("view " + this + " being added, but"
   14891                     + " it already has a parent");
   14892         }
   14893     }
   14894 
   14895     /**
   14896      * This is called when the view is attached to a window.  At this point it
   14897      * has a Surface and will start drawing.  Note that this function is
   14898      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
   14899      * however it may be called any time before the first onDraw -- including
   14900      * before or after {@link #onMeasure(int, int)}.
   14901      *
   14902      * @see #onDetachedFromWindow()
   14903      */
   14904     @CallSuper
   14905     protected void onAttachedToWindow() {
   14906         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
   14907             mParent.requestTransparentRegion(this);
   14908         }
   14909 
   14910         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   14911 
   14912         jumpDrawablesToCurrentState();
   14913 
   14914         resetSubtreeAccessibilityStateChanged();
   14915 
   14916         // rebuild, since Outline not maintained while View is detached
   14917         rebuildOutline();
   14918 
   14919         if (isFocused()) {
   14920             InputMethodManager imm = InputMethodManager.peekInstance();
   14921             if (imm != null) {
   14922                 imm.focusIn(this);
   14923             }
   14924         }
   14925     }
   14926 
   14927     /**
   14928      * Resolve all RTL related properties.
   14929      *
   14930      * @return true if resolution of RTL properties has been done
   14931      *
   14932      * @hide
   14933      */
   14934     public boolean resolveRtlPropertiesIfNeeded() {
   14935         if (!needRtlPropertiesResolution()) return false;
   14936 
   14937         // Order is important here: LayoutDirection MUST be resolved first
   14938         if (!isLayoutDirectionResolved()) {
   14939             resolveLayoutDirection();
   14940             resolveLayoutParams();
   14941         }
   14942         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
   14943         if (!isTextDirectionResolved()) {
   14944             resolveTextDirection();
   14945         }
   14946         if (!isTextAlignmentResolved()) {
   14947             resolveTextAlignment();
   14948         }
   14949         // Should resolve Drawables before Padding because we need the layout direction of the
   14950         // Drawable to correctly resolve Padding.
   14951         if (!areDrawablesResolved()) {
   14952             resolveDrawables();
   14953         }
   14954         if (!isPaddingResolved()) {
   14955             resolvePadding();
   14956         }
   14957         onRtlPropertiesChanged(getLayoutDirection());
   14958         return true;
   14959     }
   14960 
   14961     /**
   14962      * Reset resolution of all RTL related properties.
   14963      *
   14964      * @hide
   14965      */
   14966     public void resetRtlProperties() {
   14967         resetResolvedLayoutDirection();
   14968         resetResolvedTextDirection();
   14969         resetResolvedTextAlignment();
   14970         resetResolvedPadding();
   14971         resetResolvedDrawables();
   14972     }
   14973 
   14974     /**
   14975      * @see #onScreenStateChanged(int)
   14976      */
   14977     void dispatchScreenStateChanged(int screenState) {
   14978         onScreenStateChanged(screenState);
   14979     }
   14980 
   14981     /**
   14982      * This method is called whenever the state of the screen this view is
   14983      * attached to changes. A state change will usually occurs when the screen
   14984      * turns on or off (whether it happens automatically or the user does it
   14985      * manually.)
   14986      *
   14987      * @param screenState The new state of the screen. Can be either
   14988      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
   14989      */
   14990     public void onScreenStateChanged(int screenState) {
   14991     }
   14992 
   14993     /**
   14994      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
   14995      */
   14996     private boolean hasRtlSupport() {
   14997         return mContext.getApplicationInfo().hasRtlSupport();
   14998     }
   14999 
   15000     /**
   15001      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
   15002      * RTL not supported)
   15003      */
   15004     private boolean isRtlCompatibilityMode() {
   15005         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   15006         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
   15007     }
   15008 
   15009     /**
   15010      * @return true if RTL properties need resolution.
   15011      *
   15012      */
   15013     private boolean needRtlPropertiesResolution() {
   15014         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
   15015     }
   15016 
   15017     /**
   15018      * Called when any RTL property (layout direction or text direction or text alignment) has
   15019      * been changed.
   15020      *
   15021      * Subclasses need to override this method to take care of cached information that depends on the
   15022      * resolved layout direction, or to inform child views that inherit their layout direction.
   15023      *
   15024      * The default implementation does nothing.
   15025      *
   15026      * @param layoutDirection the direction of the layout
   15027      *
   15028      * @see #LAYOUT_DIRECTION_LTR
   15029      * @see #LAYOUT_DIRECTION_RTL
   15030      */
   15031     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
   15032     }
   15033 
   15034     /**
   15035      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
   15036      * that the parent directionality can and will be resolved before its children.
   15037      *
   15038      * @return true if resolution has been done, false otherwise.
   15039      *
   15040      * @hide
   15041      */
   15042     public boolean resolveLayoutDirection() {
   15043         // Clear any previous layout direction resolution
   15044         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   15045 
   15046         if (hasRtlSupport()) {
   15047             // Set resolved depending on layout direction
   15048             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
   15049                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
   15050                 case LAYOUT_DIRECTION_INHERIT:
   15051                     // We cannot resolve yet. LTR is by default and let the resolution happen again
   15052                     // later to get the correct resolved value
   15053                     if (!canResolveLayoutDirection()) return false;
   15054 
   15055                     // Parent has not yet resolved, LTR is still the default
   15056                     try {
   15057                         if (!mParent.isLayoutDirectionResolved()) return false;
   15058 
   15059                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   15060                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   15061                         }
   15062                     } catch (AbstractMethodError e) {
   15063                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   15064                                 " does not fully implement ViewParent", e);
   15065                     }
   15066                     break;
   15067                 case LAYOUT_DIRECTION_RTL:
   15068                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   15069                     break;
   15070                 case LAYOUT_DIRECTION_LOCALE:
   15071                     if((LAYOUT_DIRECTION_RTL ==
   15072                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
   15073                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   15074                     }
   15075                     break;
   15076                 default:
   15077                     // Nothing to do, LTR by default
   15078             }
   15079         }
   15080 
   15081         // Set to resolved
   15082         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   15083         return true;
   15084     }
   15085 
   15086     /**
   15087      * Check if layout direction resolution can be done.
   15088      *
   15089      * @return true if layout direction resolution can be done otherwise return false.
   15090      */
   15091     public boolean canResolveLayoutDirection() {
   15092         switch (getRawLayoutDirection()) {
   15093             case LAYOUT_DIRECTION_INHERIT:
   15094                 if (mParent != null) {
   15095                     try {
   15096                         return mParent.canResolveLayoutDirection();
   15097                     } catch (AbstractMethodError e) {
   15098                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   15099                                 " does not fully implement ViewParent", e);
   15100                     }
   15101                 }
   15102                 return false;
   15103 
   15104             default:
   15105                 return true;
   15106         }
   15107     }
   15108 
   15109     /**
   15110      * Reset the resolved layout direction. Layout direction will be resolved during a call to
   15111      * {@link #onMeasure(int, int)}.
   15112      *
   15113      * @hide
   15114      */
   15115     public void resetResolvedLayoutDirection() {
   15116         // Reset the current resolved bits
   15117         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   15118     }
   15119 
   15120     /**
   15121      * @return true if the layout direction is inherited.
   15122      *
   15123      * @hide
   15124      */
   15125     public boolean isLayoutDirectionInherited() {
   15126         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
   15127     }
   15128 
   15129     /**
   15130      * @return true if layout direction has been resolved.
   15131      */
   15132     public boolean isLayoutDirectionResolved() {
   15133         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   15134     }
   15135 
   15136     /**
   15137      * Return if padding has been resolved
   15138      *
   15139      * @hide
   15140      */
   15141     boolean isPaddingResolved() {
   15142         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
   15143     }
   15144 
   15145     /**
   15146      * Resolves padding depending on layout direction, if applicable, and
   15147      * recomputes internal padding values to adjust for scroll bars.
   15148      *
   15149      * @hide
   15150      */
   15151     public void resolvePadding() {
   15152         final int resolvedLayoutDirection = getLayoutDirection();
   15153 
   15154         if (!isRtlCompatibilityMode()) {
   15155             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
   15156             // If start / end padding are defined, they will be resolved (hence overriding) to
   15157             // left / right or right / left depending on the resolved layout direction.
   15158             // If start / end padding are not defined, use the left / right ones.
   15159             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
   15160                 Rect padding = sThreadLocal.get();
   15161                 if (padding == null) {
   15162                     padding = new Rect();
   15163                     sThreadLocal.set(padding);
   15164                 }
   15165                 mBackground.getPadding(padding);
   15166                 if (!mLeftPaddingDefined) {
   15167                     mUserPaddingLeftInitial = padding.left;
   15168                 }
   15169                 if (!mRightPaddingDefined) {
   15170                     mUserPaddingRightInitial = padding.right;
   15171                 }
   15172             }
   15173             switch (resolvedLayoutDirection) {
   15174                 case LAYOUT_DIRECTION_RTL:
   15175                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   15176                         mUserPaddingRight = mUserPaddingStart;
   15177                     } else {
   15178                         mUserPaddingRight = mUserPaddingRightInitial;
   15179                     }
   15180                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   15181                         mUserPaddingLeft = mUserPaddingEnd;
   15182                     } else {
   15183                         mUserPaddingLeft = mUserPaddingLeftInitial;
   15184                     }
   15185                     break;
   15186                 case LAYOUT_DIRECTION_LTR:
   15187                 default:
   15188                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   15189                         mUserPaddingLeft = mUserPaddingStart;
   15190                     } else {
   15191                         mUserPaddingLeft = mUserPaddingLeftInitial;
   15192                     }
   15193                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   15194                         mUserPaddingRight = mUserPaddingEnd;
   15195                     } else {
   15196                         mUserPaddingRight = mUserPaddingRightInitial;
   15197                     }
   15198             }
   15199 
   15200             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
   15201         }
   15202 
   15203         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   15204         onRtlPropertiesChanged(resolvedLayoutDirection);
   15205 
   15206         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
   15207     }
   15208 
   15209     /**
   15210      * Reset the resolved layout direction.
   15211      *
   15212      * @hide
   15213      */
   15214     public void resetResolvedPadding() {
   15215         resetResolvedPaddingInternal();
   15216     }
   15217 
   15218     /**
   15219      * Used when we only want to reset *this* view's padding and not trigger overrides
   15220      * in ViewGroup that reset children too.
   15221      */
   15222     void resetResolvedPaddingInternal() {
   15223         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
   15224     }
   15225 
   15226     /**
   15227      * This is called when the view is detached from a window.  At this point it
   15228      * no longer has a surface for drawing.
   15229      *
   15230      * @see #onAttachedToWindow()
   15231      */
   15232     @CallSuper
   15233     protected void onDetachedFromWindow() {
   15234     }
   15235 
   15236     /**
   15237      * This is a framework-internal mirror of onDetachedFromWindow() that's called
   15238      * after onDetachedFromWindow().
   15239      *
   15240      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
   15241      * The super method should be called at the end of the overridden method to ensure
   15242      * subclasses are destroyed first
   15243      *
   15244      * @hide
   15245      */
   15246     @CallSuper
   15247     protected void onDetachedFromWindowInternal() {
   15248         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
   15249         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   15250         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
   15251 
   15252         removeUnsetPressCallback();
   15253         removeLongPressCallback();
   15254         removePerformClickCallback();
   15255         removeSendViewScrolledAccessibilityEventCallback();
   15256         stopNestedScroll();
   15257 
   15258         // Anything that started animating right before detach should already
   15259         // be in its final state when re-attached.
   15260         jumpDrawablesToCurrentState();
   15261 
   15262         destroyDrawingCache();
   15263 
   15264         cleanupDraw();
   15265         mCurrentAnimation = null;
   15266     }
   15267 
   15268     private void cleanupDraw() {
   15269         resetDisplayList();
   15270         if (mAttachInfo != null) {
   15271             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
   15272         }
   15273     }
   15274 
   15275     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
   15276     }
   15277 
   15278     /**
   15279      * @return The number of times this view has been attached to a window
   15280      */
   15281     protected int getWindowAttachCount() {
   15282         return mWindowAttachCount;
   15283     }
   15284 
   15285     /**
   15286      * Retrieve a unique token identifying the window this view is attached to.
   15287      * @return Return the window's token for use in
   15288      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
   15289      */
   15290     public IBinder getWindowToken() {
   15291         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
   15292     }
   15293 
   15294     /**
   15295      * Retrieve the {@link WindowId} for the window this view is
   15296      * currently attached to.
   15297      */
   15298     public WindowId getWindowId() {
   15299         if (mAttachInfo == null) {
   15300             return null;
   15301         }
   15302         if (mAttachInfo.mWindowId == null) {
   15303             try {
   15304                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
   15305                         mAttachInfo.mWindowToken);
   15306                 mAttachInfo.mWindowId = new WindowId(
   15307                         mAttachInfo.mIWindowId);
   15308             } catch (RemoteException e) {
   15309             }
   15310         }
   15311         return mAttachInfo.mWindowId;
   15312     }
   15313 
   15314     /**
   15315      * Retrieve a unique token identifying the top-level "real" window of
   15316      * the window that this view is attached to.  That is, this is like
   15317      * {@link #getWindowToken}, except if the window this view in is a panel
   15318      * window (attached to another containing window), then the token of
   15319      * the containing window is returned instead.
   15320      *
   15321      * @return Returns the associated window token, either
   15322      * {@link #getWindowToken()} or the containing window's token.
   15323      */
   15324     public IBinder getApplicationWindowToken() {
   15325         AttachInfo ai = mAttachInfo;
   15326         if (ai != null) {
   15327             IBinder appWindowToken = ai.mPanelParentWindowToken;
   15328             if (appWindowToken == null) {
   15329                 appWindowToken = ai.mWindowToken;
   15330             }
   15331             return appWindowToken;
   15332         }
   15333         return null;
   15334     }
   15335 
   15336     /**
   15337      * Gets the logical display to which the view's window has been attached.
   15338      *
   15339      * @return The logical display, or null if the view is not currently attached to a window.
   15340      */
   15341     public Display getDisplay() {
   15342         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
   15343     }
   15344 
   15345     /**
   15346      * Retrieve private session object this view hierarchy is using to
   15347      * communicate with the window manager.
   15348      * @return the session object to communicate with the window manager
   15349      */
   15350     /*package*/ IWindowSession getWindowSession() {
   15351         return mAttachInfo != null ? mAttachInfo.mSession : null;
   15352     }
   15353 
   15354     /**
   15355      * Return the visibility value of the least visible component passed.
   15356      */
   15357     int combineVisibility(int vis1, int vis2) {
   15358         // This works because VISIBLE < INVISIBLE < GONE.
   15359         return Math.max(vis1, vis2);
   15360     }
   15361 
   15362     /**
   15363      * @param info the {@link android.view.View.AttachInfo} to associated with
   15364      *        this view
   15365      */
   15366     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
   15367         mAttachInfo = info;
   15368         if (mOverlay != null) {
   15369             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
   15370         }
   15371         mWindowAttachCount++;
   15372         // We will need to evaluate the drawable state at least once.
   15373         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   15374         if (mFloatingTreeObserver != null) {
   15375             info.mTreeObserver.merge(mFloatingTreeObserver);
   15376             mFloatingTreeObserver = null;
   15377         }
   15378 
   15379         registerPendingFrameMetricsObservers();
   15380 
   15381         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
   15382             mAttachInfo.mScrollContainers.add(this);
   15383             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   15384         }
   15385         // Transfer all pending runnables.
   15386         if (mRunQueue != null) {
   15387             mRunQueue.executeActions(info.mHandler);
   15388             mRunQueue = null;
   15389         }
   15390         performCollectViewAttributes(mAttachInfo, visibility);
   15391         onAttachedToWindow();
   15392 
   15393         ListenerInfo li = mListenerInfo;
   15394         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   15395                 li != null ? li.mOnAttachStateChangeListeners : null;
   15396         if (listeners != null && listeners.size() > 0) {
   15397             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   15398             // perform the dispatching. The iterator is a safe guard against listeners that
   15399             // could mutate the list by calling the various add/remove methods. This prevents
   15400             // the array from being modified while we iterate it.
   15401             for (OnAttachStateChangeListener listener : listeners) {
   15402                 listener.onViewAttachedToWindow(this);
   15403             }
   15404         }
   15405 
   15406         int vis = info.mWindowVisibility;
   15407         if (vis != GONE) {
   15408             onWindowVisibilityChanged(vis);
   15409             if (isShown()) {
   15410                 // Calling onVisibilityChanged directly here since the subtree will also
   15411                 // receive dispatchAttachedToWindow and this same call
   15412                 onVisibilityAggregated(vis == VISIBLE);
   15413             }
   15414         }
   15415 
   15416         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
   15417         // As all views in the subtree will already receive dispatchAttachedToWindow
   15418         // traversing the subtree again here is not desired.
   15419         onVisibilityChanged(this, visibility);
   15420 
   15421         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
   15422             // If nobody has evaluated the drawable state yet, then do it now.
   15423             refreshDrawableState();
   15424         }
   15425         needGlobalAttributesUpdate(false);
   15426     }
   15427 
   15428     void dispatchDetachedFromWindow() {
   15429         AttachInfo info = mAttachInfo;
   15430         if (info != null) {
   15431             int vis = info.mWindowVisibility;
   15432             if (vis != GONE) {
   15433                 onWindowVisibilityChanged(GONE);
   15434                 if (isShown()) {
   15435                     // Invoking onVisibilityAggregated directly here since the subtree
   15436                     // will also receive detached from window
   15437                     onVisibilityAggregated(false);
   15438                 }
   15439             }
   15440         }
   15441 
   15442         onDetachedFromWindow();
   15443         onDetachedFromWindowInternal();
   15444 
   15445         InputMethodManager imm = InputMethodManager.peekInstance();
   15446         if (imm != null) {
   15447             imm.onViewDetachedFromWindow(this);
   15448         }
   15449 
   15450         ListenerInfo li = mListenerInfo;
   15451         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   15452                 li != null ? li.mOnAttachStateChangeListeners : null;
   15453         if (listeners != null && listeners.size() > 0) {
   15454             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   15455             // perform the dispatching. The iterator is a safe guard against listeners that
   15456             // could mutate the list by calling the various add/remove methods. This prevents
   15457             // the array from being modified while we iterate it.
   15458             for (OnAttachStateChangeListener listener : listeners) {
   15459                 listener.onViewDetachedFromWindow(this);
   15460             }
   15461         }
   15462 
   15463         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   15464             mAttachInfo.mScrollContainers.remove(this);
   15465             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
   15466         }
   15467 
   15468         mAttachInfo = null;
   15469         if (mOverlay != null) {
   15470             mOverlay.getOverlayView().dispatchDetachedFromWindow();
   15471         }
   15472     }
   15473 
   15474     /**
   15475      * Cancel any deferred high-level input events that were previously posted to the event queue.
   15476      *
   15477      * <p>Many views post high-level events such as click handlers to the event queue
   15478      * to run deferred in order to preserve a desired user experience - clearing visible
   15479      * pressed states before executing, etc. This method will abort any events of this nature
   15480      * that are currently in flight.</p>
   15481      *
   15482      * <p>Custom views that generate their own high-level deferred input events should override
   15483      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
   15484      *
   15485      * <p>This will also cancel pending input events for any child views.</p>
   15486      *
   15487      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
   15488      * This will not impact newer events posted after this call that may occur as a result of
   15489      * lower-level input events still waiting in the queue. If you are trying to prevent
   15490      * double-submitted  events for the duration of some sort of asynchronous transaction
   15491      * you should also take other steps to protect against unexpected double inputs e.g. calling
   15492      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
   15493      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
   15494      */
   15495     public final void cancelPendingInputEvents() {
   15496         dispatchCancelPendingInputEvents();
   15497     }
   15498 
   15499     /**
   15500      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
   15501      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
   15502      */
   15503     void dispatchCancelPendingInputEvents() {
   15504         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
   15505         onCancelPendingInputEvents();
   15506         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
   15507             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
   15508                     " did not call through to super.onCancelPendingInputEvents()");
   15509         }
   15510     }
   15511 
   15512     /**
   15513      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
   15514      * a parent view.
   15515      *
   15516      * <p>This method is responsible for removing any pending high-level input events that were
   15517      * posted to the event queue to run later. Custom view classes that post their own deferred
   15518      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
   15519      * {@link android.os.Handler} should override this method, call
   15520      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
   15521      * </p>
   15522      */
   15523     public void onCancelPendingInputEvents() {
   15524         removePerformClickCallback();
   15525         cancelLongPress();
   15526         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
   15527     }
   15528 
   15529     /**
   15530      * Store this view hierarchy's frozen state into the given container.
   15531      *
   15532      * @param container The SparseArray in which to save the view's state.
   15533      *
   15534      * @see #restoreHierarchyState(android.util.SparseArray)
   15535      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   15536      * @see #onSaveInstanceState()
   15537      */
   15538     public void saveHierarchyState(SparseArray<Parcelable> container) {
   15539         dispatchSaveInstanceState(container);
   15540     }
   15541 
   15542     /**
   15543      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
   15544      * this view and its children. May be overridden to modify how freezing happens to a
   15545      * view's children; for example, some views may want to not store state for their children.
   15546      *
   15547      * @param container The SparseArray in which to save the view's state.
   15548      *
   15549      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   15550      * @see #saveHierarchyState(android.util.SparseArray)
   15551      * @see #onSaveInstanceState()
   15552      */
   15553     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
   15554         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
   15555             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   15556             Parcelable state = onSaveInstanceState();
   15557             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   15558                 throw new IllegalStateException(
   15559                         "Derived class did not call super.onSaveInstanceState()");
   15560             }
   15561             if (state != null) {
   15562                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
   15563                 // + ": " + state);
   15564                 container.put(mID, state);
   15565             }
   15566         }
   15567     }
   15568 
   15569     /**
   15570      * Hook allowing a view to generate a representation of its internal state
   15571      * that can later be used to create a new instance with that same state.
   15572      * This state should only contain information that is not persistent or can
   15573      * not be reconstructed later. For example, you will never store your
   15574      * current position on screen because that will be computed again when a
   15575      * new instance of the view is placed in its view hierarchy.
   15576      * <p>
   15577      * Some examples of things you may store here: the current cursor position
   15578      * in a text view (but usually not the text itself since that is stored in a
   15579      * content provider or other persistent storage), the currently selected
   15580      * item in a list view.
   15581      *
   15582      * @return Returns a Parcelable object containing the view's current dynamic
   15583      *         state, or null if there is nothing interesting to save. The
   15584      *         default implementation returns null.
   15585      * @see #onRestoreInstanceState(android.os.Parcelable)
   15586      * @see #saveHierarchyState(android.util.SparseArray)
   15587      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   15588      * @see #setSaveEnabled(boolean)
   15589      */
   15590     @CallSuper
   15591     protected Parcelable onSaveInstanceState() {
   15592         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   15593         if (mStartActivityRequestWho != null) {
   15594             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
   15595             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
   15596             return state;
   15597         }
   15598         return BaseSavedState.EMPTY_STATE;
   15599     }
   15600 
   15601     /**
   15602      * Restore this view hierarchy's frozen state from the given container.
   15603      *
   15604      * @param container The SparseArray which holds previously frozen states.
   15605      *
   15606      * @see #saveHierarchyState(android.util.SparseArray)
   15607      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   15608      * @see #onRestoreInstanceState(android.os.Parcelable)
   15609      */
   15610     public void restoreHierarchyState(SparseArray<Parcelable> container) {
   15611         dispatchRestoreInstanceState(container);
   15612     }
   15613 
   15614     /**
   15615      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
   15616      * state for this view and its children. May be overridden to modify how restoring
   15617      * happens to a view's children; for example, some views may want to not store state
   15618      * for their children.
   15619      *
   15620      * @param container The SparseArray which holds previously saved state.
   15621      *
   15622      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   15623      * @see #restoreHierarchyState(android.util.SparseArray)
   15624      * @see #onRestoreInstanceState(android.os.Parcelable)
   15625      */
   15626     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
   15627         if (mID != NO_ID) {
   15628             Parcelable state = container.get(mID);
   15629             if (state != null) {
   15630                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
   15631                 // + ": " + state);
   15632                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   15633                 onRestoreInstanceState(state);
   15634                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   15635                     throw new IllegalStateException(
   15636                             "Derived class did not call super.onRestoreInstanceState()");
   15637                 }
   15638             }
   15639         }
   15640     }
   15641 
   15642     /**
   15643      * Hook allowing a view to re-apply a representation of its internal state that had previously
   15644      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
   15645      * null state.
   15646      *
   15647      * @param state The frozen state that had previously been returned by
   15648      *        {@link #onSaveInstanceState}.
   15649      *
   15650      * @see #onSaveInstanceState()
   15651      * @see #restoreHierarchyState(android.util.SparseArray)
   15652      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   15653      */
   15654     @CallSuper
   15655     protected void onRestoreInstanceState(Parcelable state) {
   15656         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   15657         if (state != null && !(state instanceof AbsSavedState)) {
   15658             throw new IllegalArgumentException("Wrong state class, expecting View State but "
   15659                     + "received " + state.getClass().toString() + " instead. This usually happens "
   15660                     + "when two views of different type have the same id in the same hierarchy. "
   15661                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
   15662                     + "other views do not use the same id.");
   15663         }
   15664         if (state != null && state instanceof BaseSavedState) {
   15665             mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
   15666         }
   15667     }
   15668 
   15669     /**
   15670      * <p>Return the time at which the drawing of the view hierarchy started.</p>
   15671      *
   15672      * @return the drawing start time in milliseconds
   15673      */
   15674     public long getDrawingTime() {
   15675         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
   15676     }
   15677 
   15678     /**
   15679      * <p>Enables or disables the duplication of the parent's state into this view. When
   15680      * duplication is enabled, this view gets its drawable state from its parent rather
   15681      * than from its own internal properties.</p>
   15682      *
   15683      * <p>Note: in the current implementation, setting this property to true after the
   15684      * view was added to a ViewGroup might have no effect at all. This property should
   15685      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
   15686      *
   15687      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
   15688      * property is enabled, an exception will be thrown.</p>
   15689      *
   15690      * <p>Note: if the child view uses and updates additional states which are unknown to the
   15691      * parent, these states should not be affected by this method.</p>
   15692      *
   15693      * @param enabled True to enable duplication of the parent's drawable state, false
   15694      *                to disable it.
   15695      *
   15696      * @see #getDrawableState()
   15697      * @see #isDuplicateParentStateEnabled()
   15698      */
   15699     public void setDuplicateParentStateEnabled(boolean enabled) {
   15700         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
   15701     }
   15702 
   15703     /**
   15704      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
   15705      *
   15706      * @return True if this view's drawable state is duplicated from the parent,
   15707      *         false otherwise
   15708      *
   15709      * @see #getDrawableState()
   15710      * @see #setDuplicateParentStateEnabled(boolean)
   15711      */
   15712     public boolean isDuplicateParentStateEnabled() {
   15713         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
   15714     }
   15715 
   15716     /**
   15717      * <p>Specifies the type of layer backing this view. The layer can be
   15718      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   15719      * {@link #LAYER_TYPE_HARDWARE}.</p>
   15720      *
   15721      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   15722      * instance that controls how the layer is composed on screen. The following
   15723      * properties of the paint are taken into account when composing the layer:</p>
   15724      * <ul>
   15725      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   15726      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   15727      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   15728      * </ul>
   15729      *
   15730      * <p>If this view has an alpha value set to < 1.0 by calling
   15731      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
   15732      * by this view's alpha value.</p>
   15733      *
   15734      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
   15735      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
   15736      * for more information on when and how to use layers.</p>
   15737      *
   15738      * @param layerType The type of layer to use with this view, must be one of
   15739      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   15740      *        {@link #LAYER_TYPE_HARDWARE}
   15741      * @param paint The paint used to compose the layer. This argument is optional
   15742      *        and can be null. It is ignored when the layer type is
   15743      *        {@link #LAYER_TYPE_NONE}
   15744      *
   15745      * @see #getLayerType()
   15746      * @see #LAYER_TYPE_NONE
   15747      * @see #LAYER_TYPE_SOFTWARE
   15748      * @see #LAYER_TYPE_HARDWARE
   15749      * @see #setAlpha(float)
   15750      *
   15751      * @attr ref android.R.styleable#View_layerType
   15752      */
   15753     public void setLayerType(int layerType, @Nullable Paint paint) {
   15754         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
   15755             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
   15756                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
   15757         }
   15758 
   15759         boolean typeChanged = mRenderNode.setLayerType(layerType);
   15760 
   15761         if (!typeChanged) {
   15762             setLayerPaint(paint);
   15763             return;
   15764         }
   15765 
   15766         if (layerType != LAYER_TYPE_SOFTWARE) {
   15767             // Destroy any previous software drawing cache if present
   15768             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
   15769             // drawing cache created in View#draw when drawing to a SW canvas.
   15770             destroyDrawingCache();
   15771         }
   15772 
   15773         mLayerType = layerType;
   15774         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
   15775         mRenderNode.setLayerPaint(mLayerPaint);
   15776 
   15777         // draw() behaves differently if we are on a layer, so we need to
   15778         // invalidate() here
   15779         invalidateParentCaches();
   15780         invalidate(true);
   15781     }
   15782 
   15783     /**
   15784      * Updates the {@link Paint} object used with the current layer (used only if the current
   15785      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
   15786      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
   15787      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
   15788      * ensure that the view gets redrawn immediately.
   15789      *
   15790      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   15791      * instance that controls how the layer is composed on screen. The following
   15792      * properties of the paint are taken into account when composing the layer:</p>
   15793      * <ul>
   15794      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   15795      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   15796      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   15797      * </ul>
   15798      *
   15799      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
   15800      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
   15801      *
   15802      * @param paint The paint used to compose the layer. This argument is optional
   15803      *        and can be null. It is ignored when the layer type is
   15804      *        {@link #LAYER_TYPE_NONE}
   15805      *
   15806      * @see #setLayerType(int, android.graphics.Paint)
   15807      */
   15808     public void setLayerPaint(@Nullable Paint paint) {
   15809         int layerType = getLayerType();
   15810         if (layerType != LAYER_TYPE_NONE) {
   15811             mLayerPaint = paint;
   15812             if (layerType == LAYER_TYPE_HARDWARE) {
   15813                 if (mRenderNode.setLayerPaint(paint)) {
   15814                     invalidateViewProperty(false, false);
   15815                 }
   15816             } else {
   15817                 invalidate();
   15818             }
   15819         }
   15820     }
   15821 
   15822     /**
   15823      * Indicates what type of layer is currently associated with this view. By default
   15824      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
   15825      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
   15826      * for more information on the different types of layers.
   15827      *
   15828      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   15829      *         {@link #LAYER_TYPE_HARDWARE}
   15830      *
   15831      * @see #setLayerType(int, android.graphics.Paint)
   15832      * @see #buildLayer()
   15833      * @see #LAYER_TYPE_NONE
   15834      * @see #LAYER_TYPE_SOFTWARE
   15835      * @see #LAYER_TYPE_HARDWARE
   15836      */
   15837     public int getLayerType() {
   15838         return mLayerType;
   15839     }
   15840 
   15841     /**
   15842      * Forces this view's layer to be created and this view to be rendered
   15843      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
   15844      * invoking this method will have no effect.
   15845      *
   15846      * This method can for instance be used to render a view into its layer before
   15847      * starting an animation. If this view is complex, rendering into the layer
   15848      * before starting the animation will avoid skipping frames.
   15849      *
   15850      * @throws IllegalStateException If this view is not attached to a window
   15851      *
   15852      * @see #setLayerType(int, android.graphics.Paint)
   15853      */
   15854     public void buildLayer() {
   15855         if (mLayerType == LAYER_TYPE_NONE) return;
   15856 
   15857         final AttachInfo attachInfo = mAttachInfo;
   15858         if (attachInfo == null) {
   15859             throw new IllegalStateException("This view must be attached to a window first");
   15860         }
   15861 
   15862         if (getWidth() == 0 || getHeight() == 0) {
   15863             return;
   15864         }
   15865 
   15866         switch (mLayerType) {
   15867             case LAYER_TYPE_HARDWARE:
   15868                 updateDisplayListIfDirty();
   15869                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
   15870                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
   15871                 }
   15872                 break;
   15873             case LAYER_TYPE_SOFTWARE:
   15874                 buildDrawingCache(true);
   15875                 break;
   15876         }
   15877     }
   15878 
   15879     /**
   15880      * Destroys all hardware rendering resources. This method is invoked
   15881      * when the system needs to reclaim resources. Upon execution of this
   15882      * method, you should free any OpenGL resources created by the view.
   15883      *
   15884      * Note: you <strong>must</strong> call
   15885      * <code>super.destroyHardwareResources()</code> when overriding
   15886      * this method.
   15887      *
   15888      * @hide
   15889      */
   15890     @CallSuper
   15891     protected void destroyHardwareResources() {
   15892         // Although the Layer will be destroyed by RenderNode, we want to release
   15893         // the staging display list, which is also a signal to RenderNode that it's
   15894         // safe to free its copy of the display list as it knows that we will
   15895         // push an updated DisplayList if we try to draw again
   15896         resetDisplayList();
   15897     }
   15898 
   15899     /**
   15900      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
   15901      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
   15902      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
   15903      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
   15904      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
   15905      * null.</p>
   15906      *
   15907      * <p>Enabling the drawing cache is similar to
   15908      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
   15909      * acceleration is turned off. When hardware acceleration is turned on, enabling the
   15910      * drawing cache has no effect on rendering because the system uses a different mechanism
   15911      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
   15912      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
   15913      * for information on how to enable software and hardware layers.</p>
   15914      *
   15915      * <p>This API can be used to manually generate
   15916      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
   15917      * {@link #getDrawingCache()}.</p>
   15918      *
   15919      * @param enabled true to enable the drawing cache, false otherwise
   15920      *
   15921      * @see #isDrawingCacheEnabled()
   15922      * @see #getDrawingCache()
   15923      * @see #buildDrawingCache()
   15924      * @see #setLayerType(int, android.graphics.Paint)
   15925      */
   15926     public void setDrawingCacheEnabled(boolean enabled) {
   15927         mCachingFailed = false;
   15928         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
   15929     }
   15930 
   15931     /**
   15932      * <p>Indicates whether the drawing cache is enabled for this view.</p>
   15933      *
   15934      * @return true if the drawing cache is enabled
   15935      *
   15936      * @see #setDrawingCacheEnabled(boolean)
   15937      * @see #getDrawingCache()
   15938      */
   15939     @ViewDebug.ExportedProperty(category = "drawing")
   15940     public boolean isDrawingCacheEnabled() {
   15941         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
   15942     }
   15943 
   15944     /**
   15945      * Debugging utility which recursively outputs the dirty state of a view and its
   15946      * descendants.
   15947      *
   15948      * @hide
   15949      */
   15950     @SuppressWarnings({"UnusedDeclaration"})
   15951     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
   15952         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
   15953                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
   15954                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
   15955                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
   15956         if (clear) {
   15957             mPrivateFlags &= clearMask;
   15958         }
   15959         if (this instanceof ViewGroup) {
   15960             ViewGroup parent = (ViewGroup) this;
   15961             final int count = parent.getChildCount();
   15962             for (int i = 0; i < count; i++) {
   15963                 final View child = parent.getChildAt(i);
   15964                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
   15965             }
   15966         }
   15967     }
   15968 
   15969     /**
   15970      * This method is used by ViewGroup to cause its children to restore or recreate their
   15971      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
   15972      * to recreate its own display list, which would happen if it went through the normal
   15973      * draw/dispatchDraw mechanisms.
   15974      *
   15975      * @hide
   15976      */
   15977     protected void dispatchGetDisplayList() {}
   15978 
   15979     /**
   15980      * A view that is not attached or hardware accelerated cannot create a display list.
   15981      * This method checks these conditions and returns the appropriate result.
   15982      *
   15983      * @return true if view has the ability to create a display list, false otherwise.
   15984      *
   15985      * @hide
   15986      */
   15987     public boolean canHaveDisplayList() {
   15988         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
   15989     }
   15990 
   15991     /**
   15992      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
   15993      * @hide
   15994      */
   15995     @NonNull
   15996     public RenderNode updateDisplayListIfDirty() {
   15997         final RenderNode renderNode = mRenderNode;
   15998         if (!canHaveDisplayList()) {
   15999             // can't populate RenderNode, don't try
   16000             return renderNode;
   16001         }
   16002 
   16003         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
   16004                 || !renderNode.isValid()
   16005                 || (mRecreateDisplayList)) {
   16006             // Don't need to recreate the display list, just need to tell our
   16007             // children to restore/recreate theirs
   16008             if (renderNode.isValid()
   16009                     && !mRecreateDisplayList) {
   16010                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   16011                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16012                 dispatchGetDisplayList();
   16013 
   16014                 return renderNode; // no work needed
   16015             }
   16016 
   16017             // If we got here, we're recreating it. Mark it as such to ensure that
   16018             // we copy in child display lists into ours in drawChild()
   16019             mRecreateDisplayList = true;
   16020 
   16021             int width = mRight - mLeft;
   16022             int height = mBottom - mTop;
   16023             int layerType = getLayerType();
   16024 
   16025             final DisplayListCanvas canvas = renderNode.start(width, height);
   16026             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
   16027 
   16028             try {
   16029                 if (layerType == LAYER_TYPE_SOFTWARE) {
   16030                     buildDrawingCache(true);
   16031                     Bitmap cache = getDrawingCache(true);
   16032                     if (cache != null) {
   16033                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
   16034                     }
   16035                 } else {
   16036                     computeScroll();
   16037 
   16038                     canvas.translate(-mScrollX, -mScrollY);
   16039                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   16040                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16041 
   16042                     // Fast path for layouts with no backgrounds
   16043                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   16044                         dispatchDraw(canvas);
   16045                         if (mOverlay != null && !mOverlay.isEmpty()) {
   16046                             mOverlay.getOverlayView().draw(canvas);
   16047                         }
   16048                     } else {
   16049                         draw(canvas);
   16050                     }
   16051                 }
   16052             } finally {
   16053                 renderNode.end(canvas);
   16054                 setDisplayListProperties(renderNode);
   16055             }
   16056         } else {
   16057             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   16058             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16059         }
   16060         return renderNode;
   16061     }
   16062 
   16063     private void resetDisplayList() {
   16064         if (mRenderNode.isValid()) {
   16065             mRenderNode.discardDisplayList();
   16066         }
   16067 
   16068         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
   16069             mBackgroundRenderNode.discardDisplayList();
   16070         }
   16071     }
   16072 
   16073     /**
   16074      * Called when the passed RenderNode is removed from the draw tree
   16075      * @hide
   16076      */
   16077     public void onRenderNodeDetached(RenderNode renderNode) {
   16078     }
   16079 
   16080     /**
   16081      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
   16082      *
   16083      * @return A non-scaled bitmap representing this view or null if cache is disabled.
   16084      *
   16085      * @see #getDrawingCache(boolean)
   16086      */
   16087     public Bitmap getDrawingCache() {
   16088         return getDrawingCache(false);
   16089     }
   16090 
   16091     /**
   16092      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
   16093      * is null when caching is disabled. If caching is enabled and the cache is not ready,
   16094      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
   16095      * draw from the cache when the cache is enabled. To benefit from the cache, you must
   16096      * request the drawing cache by calling this method and draw it on screen if the
   16097      * returned bitmap is not null.</p>
   16098      *
   16099      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   16100      * this method will create a bitmap of the same size as this view. Because this bitmap
   16101      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   16102      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   16103      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   16104      * size than the view. This implies that your application must be able to handle this
   16105      * size.</p>
   16106      *
   16107      * @param autoScale Indicates whether the generated bitmap should be scaled based on
   16108      *        the current density of the screen when the application is in compatibility
   16109      *        mode.
   16110      *
   16111      * @return A bitmap representing this view or null if cache is disabled.
   16112      *
   16113      * @see #setDrawingCacheEnabled(boolean)
   16114      * @see #isDrawingCacheEnabled()
   16115      * @see #buildDrawingCache(boolean)
   16116      * @see #destroyDrawingCache()
   16117      */
   16118     public Bitmap getDrawingCache(boolean autoScale) {
   16119         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
   16120             return null;
   16121         }
   16122         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
   16123             buildDrawingCache(autoScale);
   16124         }
   16125         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
   16126     }
   16127 
   16128     /**
   16129      * <p>Frees the resources used by the drawing cache. If you call
   16130      * {@link #buildDrawingCache()} manually without calling
   16131      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   16132      * should cleanup the cache with this method afterwards.</p>
   16133      *
   16134      * @see #setDrawingCacheEnabled(boolean)
   16135      * @see #buildDrawingCache()
   16136      * @see #getDrawingCache()
   16137      */
   16138     public void destroyDrawingCache() {
   16139         if (mDrawingCache != null) {
   16140             mDrawingCache.recycle();
   16141             mDrawingCache = null;
   16142         }
   16143         if (mUnscaledDrawingCache != null) {
   16144             mUnscaledDrawingCache.recycle();
   16145             mUnscaledDrawingCache = null;
   16146         }
   16147     }
   16148 
   16149     /**
   16150      * Setting a solid background color for the drawing cache's bitmaps will improve
   16151      * performance and memory usage. Note, though that this should only be used if this
   16152      * view will always be drawn on top of a solid color.
   16153      *
   16154      * @param color The background color to use for the drawing cache's bitmap
   16155      *
   16156      * @see #setDrawingCacheEnabled(boolean)
   16157      * @see #buildDrawingCache()
   16158      * @see #getDrawingCache()
   16159      */
   16160     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
   16161         if (color != mDrawingCacheBackgroundColor) {
   16162             mDrawingCacheBackgroundColor = color;
   16163             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   16164         }
   16165     }
   16166 
   16167     /**
   16168      * @see #setDrawingCacheBackgroundColor(int)
   16169      *
   16170      * @return The background color to used for the drawing cache's bitmap
   16171      */
   16172     @ColorInt
   16173     public int getDrawingCacheBackgroundColor() {
   16174         return mDrawingCacheBackgroundColor;
   16175     }
   16176 
   16177     /**
   16178      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
   16179      *
   16180      * @see #buildDrawingCache(boolean)
   16181      */
   16182     public void buildDrawingCache() {
   16183         buildDrawingCache(false);
   16184     }
   16185 
   16186     /**
   16187      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
   16188      *
   16189      * <p>If you call {@link #buildDrawingCache()} manually without calling
   16190      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   16191      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
   16192      *
   16193      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   16194      * this method will create a bitmap of the same size as this view. Because this bitmap
   16195      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   16196      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   16197      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   16198      * size than the view. This implies that your application must be able to handle this
   16199      * size.</p>
   16200      *
   16201      * <p>You should avoid calling this method when hardware acceleration is enabled. If
   16202      * you do not need the drawing cache bitmap, calling this method will increase memory
   16203      * usage and cause the view to be rendered in software once, thus negatively impacting
   16204      * performance.</p>
   16205      *
   16206      * @see #getDrawingCache()
   16207      * @see #destroyDrawingCache()
   16208      */
   16209     public void buildDrawingCache(boolean autoScale) {
   16210         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
   16211                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
   16212             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
   16213                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
   16214                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
   16215             }
   16216             try {
   16217                 buildDrawingCacheImpl(autoScale);
   16218             } finally {
   16219                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
   16220             }
   16221         }
   16222     }
   16223 
   16224     /**
   16225      * private, internal implementation of buildDrawingCache, used to enable tracing
   16226      */
   16227     private void buildDrawingCacheImpl(boolean autoScale) {
   16228         mCachingFailed = false;
   16229 
   16230         int width = mRight - mLeft;
   16231         int height = mBottom - mTop;
   16232 
   16233         final AttachInfo attachInfo = mAttachInfo;
   16234         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
   16235 
   16236         if (autoScale && scalingRequired) {
   16237             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
   16238             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
   16239         }
   16240 
   16241         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
   16242         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
   16243         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
   16244 
   16245         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
   16246         final long drawingCacheSize =
   16247                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
   16248         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
   16249             if (width > 0 && height > 0) {
   16250                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
   16251                         + " too large to fit into a software layer (or drawing cache), needs "
   16252                         + projectedBitmapSize + " bytes, only "
   16253                         + drawingCacheSize + " available");
   16254             }
   16255             destroyDrawingCache();
   16256             mCachingFailed = true;
   16257             return;
   16258         }
   16259 
   16260         boolean clear = true;
   16261         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
   16262 
   16263         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
   16264             Bitmap.Config quality;
   16265             if (!opaque) {
   16266                 // Never pick ARGB_4444 because it looks awful
   16267                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
   16268                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
   16269                     case DRAWING_CACHE_QUALITY_AUTO:
   16270                     case DRAWING_CACHE_QUALITY_LOW:
   16271                     case DRAWING_CACHE_QUALITY_HIGH:
   16272                     default:
   16273                         quality = Bitmap.Config.ARGB_8888;
   16274                         break;
   16275                 }
   16276             } else {
   16277                 // Optimization for translucent windows
   16278                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
   16279                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
   16280             }
   16281 
   16282             // Try to cleanup memory
   16283             if (bitmap != null) bitmap.recycle();
   16284 
   16285             try {
   16286                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
   16287                         width, height, quality);
   16288                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
   16289                 if (autoScale) {
   16290                     mDrawingCache = bitmap;
   16291                 } else {
   16292                     mUnscaledDrawingCache = bitmap;
   16293                 }
   16294                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
   16295             } catch (OutOfMemoryError e) {
   16296                 // If there is not enough memory to create the bitmap cache, just
   16297                 // ignore the issue as bitmap caches are not required to draw the
   16298                 // view hierarchy
   16299                 if (autoScale) {
   16300                     mDrawingCache = null;
   16301                 } else {
   16302                     mUnscaledDrawingCache = null;
   16303                 }
   16304                 mCachingFailed = true;
   16305                 return;
   16306             }
   16307 
   16308             clear = drawingCacheBackgroundColor != 0;
   16309         }
   16310 
   16311         Canvas canvas;
   16312         if (attachInfo != null) {
   16313             canvas = attachInfo.mCanvas;
   16314             if (canvas == null) {
   16315                 canvas = new Canvas();
   16316             }
   16317             canvas.setBitmap(bitmap);
   16318             // Temporarily clobber the cached Canvas in case one of our children
   16319             // is also using a drawing cache. Without this, the children would
   16320             // steal the canvas by attaching their own bitmap to it and bad, bad
   16321             // thing would happen (invisible views, corrupted drawings, etc.)
   16322             attachInfo.mCanvas = null;
   16323         } else {
   16324             // This case should hopefully never or seldom happen
   16325             canvas = new Canvas(bitmap);
   16326         }
   16327 
   16328         if (clear) {
   16329             bitmap.eraseColor(drawingCacheBackgroundColor);
   16330         }
   16331 
   16332         computeScroll();
   16333         final int restoreCount = canvas.save();
   16334 
   16335         if (autoScale && scalingRequired) {
   16336             final float scale = attachInfo.mApplicationScale;
   16337             canvas.scale(scale, scale);
   16338         }
   16339 
   16340         canvas.translate(-mScrollX, -mScrollY);
   16341 
   16342         mPrivateFlags |= PFLAG_DRAWN;
   16343         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
   16344                 mLayerType != LAYER_TYPE_NONE) {
   16345             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
   16346         }
   16347 
   16348         // Fast path for layouts with no backgrounds
   16349         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   16350             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16351             dispatchDraw(canvas);
   16352             if (mOverlay != null && !mOverlay.isEmpty()) {
   16353                 mOverlay.getOverlayView().draw(canvas);
   16354             }
   16355         } else {
   16356             draw(canvas);
   16357         }
   16358 
   16359         canvas.restoreToCount(restoreCount);
   16360         canvas.setBitmap(null);
   16361 
   16362         if (attachInfo != null) {
   16363             // Restore the cached Canvas for our siblings
   16364             attachInfo.mCanvas = canvas;
   16365         }
   16366     }
   16367 
   16368     /**
   16369      * Create a snapshot of the view into a bitmap.  We should probably make
   16370      * some form of this public, but should think about the API.
   16371      *
   16372      * @hide
   16373      */
   16374     public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
   16375         int width = mRight - mLeft;
   16376         int height = mBottom - mTop;
   16377 
   16378         final AttachInfo attachInfo = mAttachInfo;
   16379         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
   16380         width = (int) ((width * scale) + 0.5f);
   16381         height = (int) ((height * scale) + 0.5f);
   16382 
   16383         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
   16384                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
   16385         if (bitmap == null) {
   16386             throw new OutOfMemoryError();
   16387         }
   16388 
   16389         Resources resources = getResources();
   16390         if (resources != null) {
   16391             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
   16392         }
   16393 
   16394         Canvas canvas;
   16395         if (attachInfo != null) {
   16396             canvas = attachInfo.mCanvas;
   16397             if (canvas == null) {
   16398                 canvas = new Canvas();
   16399             }
   16400             canvas.setBitmap(bitmap);
   16401             // Temporarily clobber the cached Canvas in case one of our children
   16402             // is also using a drawing cache. Without this, the children would
   16403             // steal the canvas by attaching their own bitmap to it and bad, bad
   16404             // things would happen (invisible views, corrupted drawings, etc.)
   16405             attachInfo.mCanvas = null;
   16406         } else {
   16407             // This case should hopefully never or seldom happen
   16408             canvas = new Canvas(bitmap);
   16409         }
   16410 
   16411         if ((backgroundColor & 0xff000000) != 0) {
   16412             bitmap.eraseColor(backgroundColor);
   16413         }
   16414 
   16415         computeScroll();
   16416         final int restoreCount = canvas.save();
   16417         canvas.scale(scale, scale);
   16418         canvas.translate(-mScrollX, -mScrollY);
   16419 
   16420         // Temporarily remove the dirty mask
   16421         int flags = mPrivateFlags;
   16422         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16423 
   16424         // Fast path for layouts with no backgrounds
   16425         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   16426             dispatchDraw(canvas);
   16427             if (mOverlay != null && !mOverlay.isEmpty()) {
   16428                 mOverlay.getOverlayView().draw(canvas);
   16429             }
   16430         } else {
   16431             draw(canvas);
   16432         }
   16433 
   16434         mPrivateFlags = flags;
   16435 
   16436         canvas.restoreToCount(restoreCount);
   16437         canvas.setBitmap(null);
   16438 
   16439         if (attachInfo != null) {
   16440             // Restore the cached Canvas for our siblings
   16441             attachInfo.mCanvas = canvas;
   16442         }
   16443 
   16444         return bitmap;
   16445     }
   16446 
   16447     /**
   16448      * Indicates whether this View is currently in edit mode. A View is usually
   16449      * in edit mode when displayed within a developer tool. For instance, if
   16450      * this View is being drawn by a visual user interface builder, this method
   16451      * should return true.
   16452      *
   16453      * Subclasses should check the return value of this method to provide
   16454      * different behaviors if their normal behavior might interfere with the
   16455      * host environment. For instance: the class spawns a thread in its
   16456      * constructor, the drawing code relies on device-specific features, etc.
   16457      *
   16458      * This method is usually checked in the drawing code of custom widgets.
   16459      *
   16460      * @return True if this View is in edit mode, false otherwise.
   16461      */
   16462     public boolean isInEditMode() {
   16463         return false;
   16464     }
   16465 
   16466     /**
   16467      * If the View draws content inside its padding and enables fading edges,
   16468      * it needs to support padding offsets. Padding offsets are added to the
   16469      * fading edges to extend the length of the fade so that it covers pixels
   16470      * drawn inside the padding.
   16471      *
   16472      * Subclasses of this class should override this method if they need
   16473      * to draw content inside the padding.
   16474      *
   16475      * @return True if padding offset must be applied, false otherwise.
   16476      *
   16477      * @see #getLeftPaddingOffset()
   16478      * @see #getRightPaddingOffset()
   16479      * @see #getTopPaddingOffset()
   16480      * @see #getBottomPaddingOffset()
   16481      *
   16482      * @since CURRENT
   16483      */
   16484     protected boolean isPaddingOffsetRequired() {
   16485         return false;
   16486     }
   16487 
   16488     /**
   16489      * Amount by which to extend the left fading region. Called only when
   16490      * {@link #isPaddingOffsetRequired()} returns true.
   16491      *
   16492      * @return The left padding offset in pixels.
   16493      *
   16494      * @see #isPaddingOffsetRequired()
   16495      *
   16496      * @since CURRENT
   16497      */
   16498     protected int getLeftPaddingOffset() {
   16499         return 0;
   16500     }
   16501 
   16502     /**
   16503      * Amount by which to extend the right fading region. Called only when
   16504      * {@link #isPaddingOffsetRequired()} returns true.
   16505      *
   16506      * @return The right padding offset in pixels.
   16507      *
   16508      * @see #isPaddingOffsetRequired()
   16509      *
   16510      * @since CURRENT
   16511      */
   16512     protected int getRightPaddingOffset() {
   16513         return 0;
   16514     }
   16515 
   16516     /**
   16517      * Amount by which to extend the top fading region. Called only when
   16518      * {@link #isPaddingOffsetRequired()} returns true.
   16519      *
   16520      * @return The top padding offset in pixels.
   16521      *
   16522      * @see #isPaddingOffsetRequired()
   16523      *
   16524      * @since CURRENT
   16525      */
   16526     protected int getTopPaddingOffset() {
   16527         return 0;
   16528     }
   16529 
   16530     /**
   16531      * Amount by which to extend the bottom fading region. Called only when
   16532      * {@link #isPaddingOffsetRequired()} returns true.
   16533      *
   16534      * @return The bottom padding offset in pixels.
   16535      *
   16536      * @see #isPaddingOffsetRequired()
   16537      *
   16538      * @since CURRENT
   16539      */
   16540     protected int getBottomPaddingOffset() {
   16541         return 0;
   16542     }
   16543 
   16544     /**
   16545      * @hide
   16546      * @param offsetRequired
   16547      */
   16548     protected int getFadeTop(boolean offsetRequired) {
   16549         int top = mPaddingTop;
   16550         if (offsetRequired) top += getTopPaddingOffset();
   16551         return top;
   16552     }
   16553 
   16554     /**
   16555      * @hide
   16556      * @param offsetRequired
   16557      */
   16558     protected int getFadeHeight(boolean offsetRequired) {
   16559         int padding = mPaddingTop;
   16560         if (offsetRequired) padding += getTopPaddingOffset();
   16561         return mBottom - mTop - mPaddingBottom - padding;
   16562     }
   16563 
   16564     /**
   16565      * <p>Indicates whether this view is attached to a hardware accelerated
   16566      * window or not.</p>
   16567      *
   16568      * <p>Even if this method returns true, it does not mean that every call
   16569      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
   16570      * accelerated {@link android.graphics.Canvas}. For instance, if this view
   16571      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
   16572      * window is hardware accelerated,
   16573      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
   16574      * return false, and this method will return true.</p>
   16575      *
   16576      * @return True if the view is attached to a window and the window is
   16577      *         hardware accelerated; false in any other case.
   16578      */
   16579     @ViewDebug.ExportedProperty(category = "drawing")
   16580     public boolean isHardwareAccelerated() {
   16581         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
   16582     }
   16583 
   16584     /**
   16585      * Sets a rectangular area on this view to which the view will be clipped
   16586      * when it is drawn. Setting the value to null will remove the clip bounds
   16587      * and the view will draw normally, using its full bounds.
   16588      *
   16589      * @param clipBounds The rectangular area, in the local coordinates of
   16590      * this view, to which future drawing operations will be clipped.
   16591      */
   16592     public void setClipBounds(Rect clipBounds) {
   16593         if (clipBounds == mClipBounds
   16594                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
   16595             return;
   16596         }
   16597         if (clipBounds != null) {
   16598             if (mClipBounds == null) {
   16599                 mClipBounds = new Rect(clipBounds);
   16600             } else {
   16601                 mClipBounds.set(clipBounds);
   16602             }
   16603         } else {
   16604             mClipBounds = null;
   16605         }
   16606         mRenderNode.setClipBounds(mClipBounds);
   16607         invalidateViewProperty(false, false);
   16608     }
   16609 
   16610     /**
   16611      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
   16612      *
   16613      * @return A copy of the current clip bounds if clip bounds are set,
   16614      * otherwise null.
   16615      */
   16616     public Rect getClipBounds() {
   16617         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
   16618     }
   16619 
   16620 
   16621     /**
   16622      * Populates an output rectangle with the clip bounds of the view,
   16623      * returning {@code true} if successful or {@code false} if the view's
   16624      * clip bounds are {@code null}.
   16625      *
   16626      * @param outRect rectangle in which to place the clip bounds of the view
   16627      * @return {@code true} if successful or {@code false} if the view's
   16628      *         clip bounds are {@code null}
   16629      */
   16630     public boolean getClipBounds(Rect outRect) {
   16631         if (mClipBounds != null) {
   16632             outRect.set(mClipBounds);
   16633             return true;
   16634         }
   16635         return false;
   16636     }
   16637 
   16638     /**
   16639      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
   16640      * case of an active Animation being run on the view.
   16641      */
   16642     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
   16643             Animation a, boolean scalingRequired) {
   16644         Transformation invalidationTransform;
   16645         final int flags = parent.mGroupFlags;
   16646         final boolean initialized = a.isInitialized();
   16647         if (!initialized) {
   16648             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
   16649             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
   16650             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
   16651             onAnimationStart();
   16652         }
   16653 
   16654         final Transformation t = parent.getChildTransformation();
   16655         boolean more = a.getTransformation(drawingTime, t, 1f);
   16656         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
   16657             if (parent.mInvalidationTransformation == null) {
   16658                 parent.mInvalidationTransformation = new Transformation();
   16659             }
   16660             invalidationTransform = parent.mInvalidationTransformation;
   16661             a.getTransformation(drawingTime, invalidationTransform, 1f);
   16662         } else {
   16663             invalidationTransform = t;
   16664         }
   16665 
   16666         if (more) {
   16667             if (!a.willChangeBounds()) {
   16668                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
   16669                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
   16670                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
   16671                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
   16672                     // The child need to draw an animation, potentially offscreen, so
   16673                     // make sure we do not cancel invalidate requests
   16674                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   16675                     parent.invalidate(mLeft, mTop, mRight, mBottom);
   16676                 }
   16677             } else {
   16678                 if (parent.mInvalidateRegion == null) {
   16679                     parent.mInvalidateRegion = new RectF();
   16680                 }
   16681                 final RectF region = parent.mInvalidateRegion;
   16682                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
   16683                         invalidationTransform);
   16684 
   16685                 // The child need to draw an animation, potentially offscreen, so
   16686                 // make sure we do not cancel invalidate requests
   16687                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   16688 
   16689                 final int left = mLeft + (int) region.left;
   16690                 final int top = mTop + (int) region.top;
   16691                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
   16692                         top + (int) (region.height() + .5f));
   16693             }
   16694         }
   16695         return more;
   16696     }
   16697 
   16698     /**
   16699      * This method is called by getDisplayList() when a display list is recorded for a View.
   16700      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
   16701      */
   16702     void setDisplayListProperties(RenderNode renderNode) {
   16703         if (renderNode != null) {
   16704             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
   16705             renderNode.setClipToBounds(mParent instanceof ViewGroup
   16706                     && ((ViewGroup) mParent).getClipChildren());
   16707 
   16708             float alpha = 1;
   16709             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
   16710                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   16711                 ViewGroup parentVG = (ViewGroup) mParent;
   16712                 final Transformation t = parentVG.getChildTransformation();
   16713                 if (parentVG.getChildStaticTransformation(this, t)) {
   16714                     final int transformType = t.getTransformationType();
   16715                     if (transformType != Transformation.TYPE_IDENTITY) {
   16716                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
   16717                             alpha = t.getAlpha();
   16718                         }
   16719                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
   16720                             renderNode.setStaticMatrix(t.getMatrix());
   16721                         }
   16722                     }
   16723                 }
   16724             }
   16725             if (mTransformationInfo != null) {
   16726                 alpha *= getFinalAlpha();
   16727                 if (alpha < 1) {
   16728                     final int multipliedAlpha = (int) (255 * alpha);
   16729                     if (onSetAlpha(multipliedAlpha)) {
   16730                         alpha = 1;
   16731                     }
   16732                 }
   16733                 renderNode.setAlpha(alpha);
   16734             } else if (alpha < 1) {
   16735                 renderNode.setAlpha(alpha);
   16736             }
   16737         }
   16738     }
   16739 
   16740     /**
   16741      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
   16742      *
   16743      * This is where the View specializes rendering behavior based on layer type,
   16744      * and hardware acceleration.
   16745      */
   16746     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
   16747         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
   16748         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
   16749          *
   16750          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
   16751          * HW accelerated, it can't handle drawing RenderNodes.
   16752          */
   16753         boolean drawingWithRenderNode = mAttachInfo != null
   16754                 && mAttachInfo.mHardwareAccelerated
   16755                 && hardwareAcceleratedCanvas;
   16756 
   16757         boolean more = false;
   16758         final boolean childHasIdentityMatrix = hasIdentityMatrix();
   16759         final int parentFlags = parent.mGroupFlags;
   16760 
   16761         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
   16762             parent.getChildTransformation().clear();
   16763             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   16764         }
   16765 
   16766         Transformation transformToApply = null;
   16767         boolean concatMatrix = false;
   16768         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
   16769         final Animation a = getAnimation();
   16770         if (a != null) {
   16771             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
   16772             concatMatrix = a.willChangeTransformationMatrix();
   16773             if (concatMatrix) {
   16774                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   16775             }
   16776             transformToApply = parent.getChildTransformation();
   16777         } else {
   16778             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
   16779                 // No longer animating: clear out old animation matrix
   16780                 mRenderNode.setAnimationMatrix(null);
   16781                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   16782             }
   16783             if (!drawingWithRenderNode
   16784                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   16785                 final Transformation t = parent.getChildTransformation();
   16786                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
   16787                 if (hasTransform) {
   16788                     final int transformType = t.getTransformationType();
   16789                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
   16790                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
   16791                 }
   16792             }
   16793         }
   16794 
   16795         concatMatrix |= !childHasIdentityMatrix;
   16796 
   16797         // Sets the flag as early as possible to allow draw() implementations
   16798         // to call invalidate() successfully when doing animations
   16799         mPrivateFlags |= PFLAG_DRAWN;
   16800 
   16801         if (!concatMatrix &&
   16802                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
   16803                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
   16804                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
   16805                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
   16806             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
   16807             return more;
   16808         }
   16809         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
   16810 
   16811         if (hardwareAcceleratedCanvas) {
   16812             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
   16813             // retain the flag's value temporarily in the mRecreateDisplayList flag
   16814             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
   16815             mPrivateFlags &= ~PFLAG_INVALIDATED;
   16816         }
   16817 
   16818         RenderNode renderNode = null;
   16819         Bitmap cache = null;
   16820         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
   16821         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
   16822              if (layerType != LAYER_TYPE_NONE) {
   16823                  // If not drawing with RenderNode, treat HW layers as SW
   16824                  layerType = LAYER_TYPE_SOFTWARE;
   16825                  buildDrawingCache(true);
   16826             }
   16827             cache = getDrawingCache(true);
   16828         }
   16829 
   16830         if (drawingWithRenderNode) {
   16831             // Delay getting the display list until animation-driven alpha values are
   16832             // set up and possibly passed on to the view
   16833             renderNode = updateDisplayListIfDirty();
   16834             if (!renderNode.isValid()) {
   16835                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
   16836                 // to getDisplayList(), the display list will be marked invalid and we should not
   16837                 // try to use it again.
   16838                 renderNode = null;
   16839                 drawingWithRenderNode = false;
   16840             }
   16841         }
   16842 
   16843         int sx = 0;
   16844         int sy = 0;
   16845         if (!drawingWithRenderNode) {
   16846             computeScroll();
   16847             sx = mScrollX;
   16848             sy = mScrollY;
   16849         }
   16850 
   16851         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
   16852         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
   16853 
   16854         int restoreTo = -1;
   16855         if (!drawingWithRenderNode || transformToApply != null) {
   16856             restoreTo = canvas.save();
   16857         }
   16858         if (offsetForScroll) {
   16859             canvas.translate(mLeft - sx, mTop - sy);
   16860         } else {
   16861             if (!drawingWithRenderNode) {
   16862                 canvas.translate(mLeft, mTop);
   16863             }
   16864             if (scalingRequired) {
   16865                 if (drawingWithRenderNode) {
   16866                     // TODO: Might not need this if we put everything inside the DL
   16867                     restoreTo = canvas.save();
   16868                 }
   16869                 // mAttachInfo cannot be null, otherwise scalingRequired == false
   16870                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
   16871                 canvas.scale(scale, scale);
   16872             }
   16873         }
   16874 
   16875         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
   16876         if (transformToApply != null
   16877                 || alpha < 1
   16878                 || !hasIdentityMatrix()
   16879                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   16880             if (transformToApply != null || !childHasIdentityMatrix) {
   16881                 int transX = 0;
   16882                 int transY = 0;
   16883 
   16884                 if (offsetForScroll) {
   16885                     transX = -sx;
   16886                     transY = -sy;
   16887                 }
   16888 
   16889                 if (transformToApply != null) {
   16890                     if (concatMatrix) {
   16891                         if (drawingWithRenderNode) {
   16892                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
   16893                         } else {
   16894                             // Undo the scroll translation, apply the transformation matrix,
   16895                             // then redo the scroll translate to get the correct result.
   16896                             canvas.translate(-transX, -transY);
   16897                             canvas.concat(transformToApply.getMatrix());
   16898                             canvas.translate(transX, transY);
   16899                         }
   16900                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   16901                     }
   16902 
   16903                     float transformAlpha = transformToApply.getAlpha();
   16904                     if (transformAlpha < 1) {
   16905                         alpha *= transformAlpha;
   16906                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   16907                     }
   16908                 }
   16909 
   16910                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
   16911                     canvas.translate(-transX, -transY);
   16912                     canvas.concat(getMatrix());
   16913                     canvas.translate(transX, transY);
   16914                 }
   16915             }
   16916 
   16917             // Deal with alpha if it is or used to be <1
   16918             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   16919                 if (alpha < 1) {
   16920                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   16921                 } else {
   16922                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   16923                 }
   16924                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   16925                 if (!drawingWithDrawingCache) {
   16926                     final int multipliedAlpha = (int) (255 * alpha);
   16927                     if (!onSetAlpha(multipliedAlpha)) {
   16928                         if (drawingWithRenderNode) {
   16929                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
   16930                         } else if (layerType == LAYER_TYPE_NONE) {
   16931                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
   16932                                     multipliedAlpha);
   16933                         }
   16934                     } else {
   16935                         // Alpha is handled by the child directly, clobber the layer's alpha
   16936                         mPrivateFlags |= PFLAG_ALPHA_SET;
   16937                     }
   16938                 }
   16939             }
   16940         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   16941             onSetAlpha(255);
   16942             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   16943         }
   16944 
   16945         if (!drawingWithRenderNode) {
   16946             // apply clips directly, since RenderNode won't do it for this draw
   16947             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
   16948                 if (offsetForScroll) {
   16949                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
   16950                 } else {
   16951                     if (!scalingRequired || cache == null) {
   16952                         canvas.clipRect(0, 0, getWidth(), getHeight());
   16953                     } else {
   16954                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
   16955                     }
   16956                 }
   16957             }
   16958 
   16959             if (mClipBounds != null) {
   16960                 // clip bounds ignore scroll
   16961                 canvas.clipRect(mClipBounds);
   16962             }
   16963         }
   16964 
   16965         if (!drawingWithDrawingCache) {
   16966             if (drawingWithRenderNode) {
   16967                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16968                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
   16969             } else {
   16970                 // Fast path for layouts with no backgrounds
   16971                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   16972                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16973                     dispatchDraw(canvas);
   16974                 } else {
   16975                     draw(canvas);
   16976                 }
   16977             }
   16978         } else if (cache != null) {
   16979             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16980             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
   16981                 // no layer paint, use temporary paint to draw bitmap
   16982                 Paint cachePaint = parent.mCachePaint;
   16983                 if (cachePaint == null) {
   16984                     cachePaint = new Paint();
   16985                     cachePaint.setDither(false);
   16986                     parent.mCachePaint = cachePaint;
   16987                 }
   16988                 cachePaint.setAlpha((int) (alpha * 255));
   16989                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
   16990             } else {
   16991                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
   16992                 int layerPaintAlpha = mLayerPaint.getAlpha();
   16993                 if (alpha < 1) {
   16994                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
   16995                 }
   16996                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
   16997                 if (alpha < 1) {
   16998                     mLayerPaint.setAlpha(layerPaintAlpha);
   16999                 }
   17000             }
   17001         }
   17002 
   17003         if (restoreTo >= 0) {
   17004             canvas.restoreToCount(restoreTo);
   17005         }
   17006 
   17007         if (a != null && !more) {
   17008             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
   17009                 onSetAlpha(255);
   17010             }
   17011             parent.finishAnimatingView(this, a);
   17012         }
   17013 
   17014         if (more && hardwareAcceleratedCanvas) {
   17015             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   17016                 // alpha animations should cause the child to recreate its display list
   17017                 invalidate(true);
   17018             }
   17019         }
   17020 
   17021         mRecreateDisplayList = false;
   17022 
   17023         return more;
   17024     }
   17025 
   17026     /**
   17027      * Manually render this view (and all of its children) to the given Canvas.
   17028      * The view must have already done a full layout before this function is
   17029      * called.  When implementing a view, implement
   17030      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
   17031      * If you do need to override this method, call the superclass version.
   17032      *
   17033      * @param canvas The Canvas to which the View is rendered.
   17034      */
   17035     @CallSuper
   17036     public void draw(Canvas canvas) {
   17037         final int privateFlags = mPrivateFlags;
   17038         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
   17039                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
   17040         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
   17041 
   17042         /*
   17043          * Draw traversal performs several drawing steps which must be executed
   17044          * in the appropriate order:
   17045          *
   17046          *      1. Draw the background
   17047          *      2. If necessary, save the canvas' layers to prepare for fading
   17048          *      3. Draw view's content
   17049          *      4. Draw children
   17050          *      5. If necessary, draw the fading edges and restore layers
   17051          *      6. Draw decorations (scrollbars for instance)
   17052          */
   17053 
   17054         // Step 1, draw the background, if needed
   17055         int saveCount;
   17056 
   17057         if (!dirtyOpaque) {
   17058             drawBackground(canvas);
   17059         }
   17060 
   17061         // skip step 2 & 5 if possible (common case)
   17062         final int viewFlags = mViewFlags;
   17063         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
   17064         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
   17065         if (!verticalEdges && !horizontalEdges) {
   17066             // Step 3, draw the content
   17067             if (!dirtyOpaque) onDraw(canvas);
   17068 
   17069             // Step 4, draw the children
   17070             dispatchDraw(canvas);
   17071 
   17072             // Overlay is part of the content and draws beneath Foreground
   17073             if (mOverlay != null && !mOverlay.isEmpty()) {
   17074                 mOverlay.getOverlayView().dispatchDraw(canvas);
   17075             }
   17076 
   17077             // Step 6, draw decorations (foreground, scrollbars)
   17078             onDrawForeground(canvas);
   17079 
   17080             // we're done...
   17081             return;
   17082         }
   17083 
   17084         /*
   17085          * Here we do the full fledged routine...
   17086          * (this is an uncommon case where speed matters less,
   17087          * this is why we repeat some of the tests that have been
   17088          * done above)
   17089          */
   17090 
   17091         boolean drawTop = false;
   17092         boolean drawBottom = false;
   17093         boolean drawLeft = false;
   17094         boolean drawRight = false;
   17095 
   17096         float topFadeStrength = 0.0f;
   17097         float bottomFadeStrength = 0.0f;
   17098         float leftFadeStrength = 0.0f;
   17099         float rightFadeStrength = 0.0f;
   17100 
   17101         // Step 2, save the canvas' layers
   17102         int paddingLeft = mPaddingLeft;
   17103 
   17104         final boolean offsetRequired = isPaddingOffsetRequired();
   17105         if (offsetRequired) {
   17106             paddingLeft += getLeftPaddingOffset();
   17107         }
   17108 
   17109         int left = mScrollX + paddingLeft;
   17110         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
   17111         int top = mScrollY + getFadeTop(offsetRequired);
   17112         int bottom = top + getFadeHeight(offsetRequired);
   17113 
   17114         if (offsetRequired) {
   17115             right += getRightPaddingOffset();
   17116             bottom += getBottomPaddingOffset();
   17117         }
   17118 
   17119         final ScrollabilityCache scrollabilityCache = mScrollCache;
   17120         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
   17121         int length = (int) fadeHeight;
   17122 
   17123         // clip the fade length if top and bottom fades overlap
   17124         // overlapping fades produce odd-looking artifacts
   17125         if (verticalEdges && (top + length > bottom - length)) {
   17126             length = (bottom - top) / 2;
   17127         }
   17128 
   17129         // also clip horizontal fades if necessary
   17130         if (horizontalEdges && (left + length > right - length)) {
   17131             length = (right - left) / 2;
   17132         }
   17133 
   17134         if (verticalEdges) {
   17135             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
   17136             drawTop = topFadeStrength * fadeHeight > 1.0f;
   17137             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
   17138             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
   17139         }
   17140 
   17141         if (horizontalEdges) {
   17142             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
   17143             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
   17144             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
   17145             drawRight = rightFadeStrength * fadeHeight > 1.0f;
   17146         }
   17147 
   17148         saveCount = canvas.getSaveCount();
   17149 
   17150         int solidColor = getSolidColor();
   17151         if (solidColor == 0) {
   17152             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
   17153 
   17154             if (drawTop) {
   17155                 canvas.saveLayer(left, top, right, top + length, null, flags);
   17156             }
   17157 
   17158             if (drawBottom) {
   17159                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
   17160             }
   17161 
   17162             if (drawLeft) {
   17163                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
   17164             }
   17165 
   17166             if (drawRight) {
   17167                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
   17168             }
   17169         } else {
   17170             scrollabilityCache.setFadeColor(solidColor);
   17171         }
   17172 
   17173         // Step 3, draw the content
   17174         if (!dirtyOpaque) onDraw(canvas);
   17175 
   17176         // Step 4, draw the children
   17177         dispatchDraw(canvas);
   17178 
   17179         // Step 5, draw the fade effect and restore layers
   17180         final Paint p = scrollabilityCache.paint;
   17181         final Matrix matrix = scrollabilityCache.matrix;
   17182         final Shader fade = scrollabilityCache.shader;
   17183 
   17184         if (drawTop) {
   17185             matrix.setScale(1, fadeHeight * topFadeStrength);
   17186             matrix.postTranslate(left, top);
   17187             fade.setLocalMatrix(matrix);
   17188             p.setShader(fade);
   17189             canvas.drawRect(left, top, right, top + length, p);
   17190         }
   17191 
   17192         if (drawBottom) {
   17193             matrix.setScale(1, fadeHeight * bottomFadeStrength);
   17194             matrix.postRotate(180);
   17195             matrix.postTranslate(left, bottom);
   17196             fade.setLocalMatrix(matrix);
   17197             p.setShader(fade);
   17198             canvas.drawRect(left, bottom - length, right, bottom, p);
   17199         }
   17200 
   17201         if (drawLeft) {
   17202             matrix.setScale(1, fadeHeight * leftFadeStrength);
   17203             matrix.postRotate(-90);
   17204             matrix.postTranslate(left, top);
   17205             fade.setLocalMatrix(matrix);
   17206             p.setShader(fade);
   17207             canvas.drawRect(left, top, left + length, bottom, p);
   17208         }
   17209 
   17210         if (drawRight) {
   17211             matrix.setScale(1, fadeHeight * rightFadeStrength);
   17212             matrix.postRotate(90);
   17213             matrix.postTranslate(right, top);
   17214             fade.setLocalMatrix(matrix);
   17215             p.setShader(fade);
   17216             canvas.drawRect(right - length, top, right, bottom, p);
   17217         }
   17218 
   17219         canvas.restoreToCount(saveCount);
   17220 
   17221         // Overlay is part of the content and draws beneath Foreground
   17222         if (mOverlay != null && !mOverlay.isEmpty()) {
   17223             mOverlay.getOverlayView().dispatchDraw(canvas);
   17224         }
   17225 
   17226         // Step 6, draw decorations (foreground, scrollbars)
   17227         onDrawForeground(canvas);
   17228     }
   17229 
   17230     /**
   17231      * Draws the background onto the specified canvas.
   17232      *
   17233      * @param canvas Canvas on which to draw the background
   17234      */
   17235     private void drawBackground(Canvas canvas) {
   17236         final Drawable background = mBackground;
   17237         if (background == null) {
   17238             return;
   17239         }
   17240 
   17241         setBackgroundBounds();
   17242 
   17243         // Attempt to use a display list if requested.
   17244         if (canvas.isHardwareAccelerated() && mAttachInfo != null
   17245                 && mAttachInfo.mHardwareRenderer != null) {
   17246             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
   17247 
   17248             final RenderNode renderNode = mBackgroundRenderNode;
   17249             if (renderNode != null && renderNode.isValid()) {
   17250                 setBackgroundRenderNodeProperties(renderNode);
   17251                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
   17252                 return;
   17253             }
   17254         }
   17255 
   17256         final int scrollX = mScrollX;
   17257         final int scrollY = mScrollY;
   17258         if ((scrollX | scrollY) == 0) {
   17259             background.draw(canvas);
   17260         } else {
   17261             canvas.translate(scrollX, scrollY);
   17262             background.draw(canvas);
   17263             canvas.translate(-scrollX, -scrollY);
   17264         }
   17265     }
   17266 
   17267     /**
   17268      * Sets the correct background bounds and rebuilds the outline, if needed.
   17269      * <p/>
   17270      * This is called by LayoutLib.
   17271      */
   17272     void setBackgroundBounds() {
   17273         if (mBackgroundSizeChanged && mBackground != null) {
   17274             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
   17275             mBackgroundSizeChanged = false;
   17276             rebuildOutline();
   17277         }
   17278     }
   17279 
   17280     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
   17281         renderNode.setTranslationX(mScrollX);
   17282         renderNode.setTranslationY(mScrollY);
   17283     }
   17284 
   17285     /**
   17286      * Creates a new display list or updates the existing display list for the
   17287      * specified Drawable.
   17288      *
   17289      * @param drawable Drawable for which to create a display list
   17290      * @param renderNode Existing RenderNode, or {@code null}
   17291      * @return A valid display list for the specified drawable
   17292      */
   17293     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
   17294         if (renderNode == null) {
   17295             renderNode = RenderNode.create(drawable.getClass().getName(), this);
   17296         }
   17297 
   17298         final Rect bounds = drawable.getBounds();
   17299         final int width = bounds.width();
   17300         final int height = bounds.height();
   17301         final DisplayListCanvas canvas = renderNode.start(width, height);
   17302 
   17303         // Reverse left/top translation done by drawable canvas, which will
   17304         // instead be applied by rendernode's LTRB bounds below. This way, the
   17305         // drawable's bounds match with its rendernode bounds and its content
   17306         // will lie within those bounds in the rendernode tree.
   17307         canvas.translate(-bounds.left, -bounds.top);
   17308 
   17309         try {
   17310             drawable.draw(canvas);
   17311         } finally {
   17312             renderNode.end(canvas);
   17313         }
   17314 
   17315         // Set up drawable properties that are view-independent.
   17316         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
   17317         renderNode.setProjectBackwards(drawable.isProjected());
   17318         renderNode.setProjectionReceiver(true);
   17319         renderNode.setClipToBounds(false);
   17320         return renderNode;
   17321     }
   17322 
   17323     /**
   17324      * Returns the overlay for this view, creating it if it does not yet exist.
   17325      * Adding drawables to the overlay will cause them to be displayed whenever
   17326      * the view itself is redrawn. Objects in the overlay should be actively
   17327      * managed: remove them when they should not be displayed anymore. The
   17328      * overlay will always have the same size as its host view.
   17329      *
   17330      * <p>Note: Overlays do not currently work correctly with {@link
   17331      * SurfaceView} or {@link TextureView}; contents in overlays for these
   17332      * types of views may not display correctly.</p>
   17333      *
   17334      * @return The ViewOverlay object for this view.
   17335      * @see ViewOverlay
   17336      */
   17337     public ViewOverlay getOverlay() {
   17338         if (mOverlay == null) {
   17339             mOverlay = new ViewOverlay(mContext, this);
   17340         }
   17341         return mOverlay;
   17342     }
   17343 
   17344     /**
   17345      * Override this if your view is known to always be drawn on top of a solid color background,
   17346      * and needs to draw fading edges. Returning a non-zero color enables the view system to
   17347      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
   17348      * should be set to 0xFF.
   17349      *
   17350      * @see #setVerticalFadingEdgeEnabled(boolean)
   17351      * @see #setHorizontalFadingEdgeEnabled(boolean)
   17352      *
   17353      * @return The known solid color background for this view, or 0 if the color may vary
   17354      */
   17355     @ViewDebug.ExportedProperty(category = "drawing")
   17356     @ColorInt
   17357     public int getSolidColor() {
   17358         return 0;
   17359     }
   17360 
   17361     /**
   17362      * Build a human readable string representation of the specified view flags.
   17363      *
   17364      * @param flags the view flags to convert to a string
   17365      * @return a String representing the supplied flags
   17366      */
   17367     private static String printFlags(int flags) {
   17368         String output = "";
   17369         int numFlags = 0;
   17370         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
   17371             output += "TAKES_FOCUS";
   17372             numFlags++;
   17373         }
   17374 
   17375         switch (flags & VISIBILITY_MASK) {
   17376         case INVISIBLE:
   17377             if (numFlags > 0) {
   17378                 output += " ";
   17379             }
   17380             output += "INVISIBLE";
   17381             // USELESS HERE numFlags++;
   17382             break;
   17383         case GONE:
   17384             if (numFlags > 0) {
   17385                 output += " ";
   17386             }
   17387             output += "GONE";
   17388             // USELESS HERE numFlags++;
   17389             break;
   17390         default:
   17391             break;
   17392         }
   17393         return output;
   17394     }
   17395 
   17396     /**
   17397      * Build a human readable string representation of the specified private
   17398      * view flags.
   17399      *
   17400      * @param privateFlags the private view flags to convert to a string
   17401      * @return a String representing the supplied flags
   17402      */
   17403     private static String printPrivateFlags(int privateFlags) {
   17404         String output = "";
   17405         int numFlags = 0;
   17406 
   17407         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
   17408             output += "WANTS_FOCUS";
   17409             numFlags++;
   17410         }
   17411 
   17412         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
   17413             if (numFlags > 0) {
   17414                 output += " ";
   17415             }
   17416             output += "FOCUSED";
   17417             numFlags++;
   17418         }
   17419 
   17420         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
   17421             if (numFlags > 0) {
   17422                 output += " ";
   17423             }
   17424             output += "SELECTED";
   17425             numFlags++;
   17426         }
   17427 
   17428         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
   17429             if (numFlags > 0) {
   17430                 output += " ";
   17431             }
   17432             output += "IS_ROOT_NAMESPACE";
   17433             numFlags++;
   17434         }
   17435 
   17436         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
   17437             if (numFlags > 0) {
   17438                 output += " ";
   17439             }
   17440             output += "HAS_BOUNDS";
   17441             numFlags++;
   17442         }
   17443 
   17444         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
   17445             if (numFlags > 0) {
   17446                 output += " ";
   17447             }
   17448             output += "DRAWN";
   17449             // USELESS HERE numFlags++;
   17450         }
   17451         return output;
   17452     }
   17453 
   17454     /**
   17455      * <p>Indicates whether or not this view's layout will be requested during
   17456      * the next hierarchy layout pass.</p>
   17457      *
   17458      * @return true if the layout will be forced during next layout pass
   17459      */
   17460     public boolean isLayoutRequested() {
   17461         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   17462     }
   17463 
   17464     /**
   17465      * Return true if o is a ViewGroup that is laying out using optical bounds.
   17466      * @hide
   17467      */
   17468     public static boolean isLayoutModeOptical(Object o) {
   17469         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
   17470     }
   17471 
   17472     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
   17473         Insets parentInsets = mParent instanceof View ?
   17474                 ((View) mParent).getOpticalInsets() : Insets.NONE;
   17475         Insets childInsets = getOpticalInsets();
   17476         return setFrame(
   17477                 left   + parentInsets.left - childInsets.left,
   17478                 top    + parentInsets.top  - childInsets.top,
   17479                 right  + parentInsets.left + childInsets.right,
   17480                 bottom + parentInsets.top  + childInsets.bottom);
   17481     }
   17482 
   17483     /**
   17484      * Assign a size and position to a view and all of its
   17485      * descendants
   17486      *
   17487      * <p>This is the second phase of the layout mechanism.
   17488      * (The first is measuring). In this phase, each parent calls
   17489      * layout on all of its children to position them.
   17490      * This is typically done using the child measurements
   17491      * that were stored in the measure pass().</p>
   17492      *
   17493      * <p>Derived classes should not override this method.
   17494      * Derived classes with children should override
   17495      * onLayout. In that method, they should
   17496      * call layout on each of their children.</p>
   17497      *
   17498      * @param l Left position, relative to parent
   17499      * @param t Top position, relative to parent
   17500      * @param r Right position, relative to parent
   17501      * @param b Bottom position, relative to parent
   17502      */
   17503     @SuppressWarnings({"unchecked"})
   17504     public void layout(int l, int t, int r, int b) {
   17505         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
   17506             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
   17507             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   17508         }
   17509 
   17510         int oldL = mLeft;
   17511         int oldT = mTop;
   17512         int oldB = mBottom;
   17513         int oldR = mRight;
   17514 
   17515         boolean changed = isLayoutModeOptical(mParent) ?
   17516                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
   17517 
   17518         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
   17519             onLayout(changed, l, t, r, b);
   17520             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
   17521 
   17522             ListenerInfo li = mListenerInfo;
   17523             if (li != null && li.mOnLayoutChangeListeners != null) {
   17524                 ArrayList<OnLayoutChangeListener> listenersCopy =
   17525                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
   17526                 int numListeners = listenersCopy.size();
   17527                 for (int i = 0; i < numListeners; ++i) {
   17528                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
   17529                 }
   17530             }
   17531         }
   17532 
   17533         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
   17534         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
   17535     }
   17536 
   17537     /**
   17538      * Called from layout when this view should
   17539      * assign a size and position to each of its children.
   17540      *
   17541      * Derived classes with children should override
   17542      * this method and call layout on each of
   17543      * their children.
   17544      * @param changed This is a new size or position for this view
   17545      * @param left Left position, relative to parent
   17546      * @param top Top position, relative to parent
   17547      * @param right Right position, relative to parent
   17548      * @param bottom Bottom position, relative to parent
   17549      */
   17550     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   17551     }
   17552 
   17553     /**
   17554      * Assign a size and position to this view.
   17555      *
   17556      * This is called from layout.
   17557      *
   17558      * @param left Left position, relative to parent
   17559      * @param top Top position, relative to parent
   17560      * @param right Right position, relative to parent
   17561      * @param bottom Bottom position, relative to parent
   17562      * @return true if the new size and position are different than the
   17563      *         previous ones
   17564      * {@hide}
   17565      */
   17566     protected boolean setFrame(int left, int top, int right, int bottom) {
   17567         boolean changed = false;
   17568 
   17569         if (DBG) {
   17570             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
   17571                     + right + "," + bottom + ")");
   17572         }
   17573 
   17574         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
   17575             changed = true;
   17576 
   17577             // Remember our drawn bit
   17578             int drawn = mPrivateFlags & PFLAG_DRAWN;
   17579 
   17580             int oldWidth = mRight - mLeft;
   17581             int oldHeight = mBottom - mTop;
   17582             int newWidth = right - left;
   17583             int newHeight = bottom - top;
   17584             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
   17585 
   17586             // Invalidate our old position
   17587             invalidate(sizeChanged);
   17588 
   17589             mLeft = left;
   17590             mTop = top;
   17591             mRight = right;
   17592             mBottom = bottom;
   17593             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
   17594 
   17595             mPrivateFlags |= PFLAG_HAS_BOUNDS;
   17596 
   17597 
   17598             if (sizeChanged) {
   17599                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
   17600             }
   17601 
   17602             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
   17603                 // If we are visible, force the DRAWN bit to on so that
   17604                 // this invalidate will go through (at least to our parent).
   17605                 // This is because someone may have invalidated this view
   17606                 // before this call to setFrame came in, thereby clearing
   17607                 // the DRAWN bit.
   17608                 mPrivateFlags |= PFLAG_DRAWN;
   17609                 invalidate(sizeChanged);
   17610                 // parent display list may need to be recreated based on a change in the bounds
   17611                 // of any child
   17612                 invalidateParentCaches();
   17613             }
   17614 
   17615             // Reset drawn bit to original value (invalidate turns it off)
   17616             mPrivateFlags |= drawn;
   17617 
   17618             mBackgroundSizeChanged = true;
   17619             if (mForegroundInfo != null) {
   17620                 mForegroundInfo.mBoundsChanged = true;
   17621             }
   17622 
   17623             notifySubtreeAccessibilityStateChangedIfNeeded();
   17624         }
   17625         return changed;
   17626     }
   17627 
   17628     /**
   17629      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
   17630      * @hide
   17631      */
   17632     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
   17633         setFrame(left, top, right, bottom);
   17634     }
   17635 
   17636     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
   17637         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
   17638         if (mOverlay != null) {
   17639             mOverlay.getOverlayView().setRight(newWidth);
   17640             mOverlay.getOverlayView().setBottom(newHeight);
   17641         }
   17642         rebuildOutline();
   17643     }
   17644 
   17645     /**
   17646      * Finalize inflating a view from XML.  This is called as the last phase
   17647      * of inflation, after all child views have been added.
   17648      *
   17649      * <p>Even if the subclass overrides onFinishInflate, they should always be
   17650      * sure to call the super method, so that we get called.
   17651      */
   17652     @CallSuper
   17653     protected void onFinishInflate() {
   17654     }
   17655 
   17656     /**
   17657      * Returns the resources associated with this view.
   17658      *
   17659      * @return Resources object.
   17660      */
   17661     public Resources getResources() {
   17662         return mResources;
   17663     }
   17664 
   17665     /**
   17666      * Invalidates the specified Drawable.
   17667      *
   17668      * @param drawable the drawable to invalidate
   17669      */
   17670     @Override
   17671     public void invalidateDrawable(@NonNull Drawable drawable) {
   17672         if (verifyDrawable(drawable)) {
   17673             final Rect dirty = drawable.getDirtyBounds();
   17674             final int scrollX = mScrollX;
   17675             final int scrollY = mScrollY;
   17676 
   17677             invalidate(dirty.left + scrollX, dirty.top + scrollY,
   17678                     dirty.right + scrollX, dirty.bottom + scrollY);
   17679             rebuildOutline();
   17680         }
   17681     }
   17682 
   17683     /**
   17684      * Schedules an action on a drawable to occur at a specified time.
   17685      *
   17686      * @param who the recipient of the action
   17687      * @param what the action to run on the drawable
   17688      * @param when the time at which the action must occur. Uses the
   17689      *        {@link SystemClock#uptimeMillis} timebase.
   17690      */
   17691     @Override
   17692     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
   17693         if (verifyDrawable(who) && what != null) {
   17694             final long delay = when - SystemClock.uptimeMillis();
   17695             if (mAttachInfo != null) {
   17696                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   17697                         Choreographer.CALLBACK_ANIMATION, what, who,
   17698                         Choreographer.subtractFrameDelay(delay));
   17699             } else {
   17700                 // Postpone the runnable until we know
   17701                 // on which thread it needs to run.
   17702                 getRunQueue().postDelayed(what, delay);
   17703             }
   17704         }
   17705     }
   17706 
   17707     /**
   17708      * Cancels a scheduled action on a drawable.
   17709      *
   17710      * @param who the recipient of the action
   17711      * @param what the action to cancel
   17712      */
   17713     @Override
   17714     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
   17715         if (verifyDrawable(who) && what != null) {
   17716             if (mAttachInfo != null) {
   17717                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   17718                         Choreographer.CALLBACK_ANIMATION, what, who);
   17719             }
   17720             getRunQueue().removeCallbacks(what);
   17721         }
   17722     }
   17723 
   17724     /**
   17725      * Unschedule any events associated with the given Drawable.  This can be
   17726      * used when selecting a new Drawable into a view, so that the previous
   17727      * one is completely unscheduled.
   17728      *
   17729      * @param who The Drawable to unschedule.
   17730      *
   17731      * @see #drawableStateChanged
   17732      */
   17733     public void unscheduleDrawable(Drawable who) {
   17734         if (mAttachInfo != null && who != null) {
   17735             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   17736                     Choreographer.CALLBACK_ANIMATION, null, who);
   17737         }
   17738     }
   17739 
   17740     /**
   17741      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
   17742      * that the View directionality can and will be resolved before its Drawables.
   17743      *
   17744      * Will call {@link View#onResolveDrawables} when resolution is done.
   17745      *
   17746      * @hide
   17747      */
   17748     protected void resolveDrawables() {
   17749         // Drawables resolution may need to happen before resolving the layout direction (which is
   17750         // done only during the measure() call).
   17751         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
   17752         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
   17753         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
   17754         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
   17755         // direction to be resolved as its resolved value will be the same as its raw value.
   17756         if (!isLayoutDirectionResolved() &&
   17757                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
   17758             return;
   17759         }
   17760 
   17761         final int layoutDirection = isLayoutDirectionResolved() ?
   17762                 getLayoutDirection() : getRawLayoutDirection();
   17763 
   17764         if (mBackground != null) {
   17765             mBackground.setLayoutDirection(layoutDirection);
   17766         }
   17767         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   17768             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
   17769         }
   17770         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
   17771         onResolveDrawables(layoutDirection);
   17772     }
   17773 
   17774     boolean areDrawablesResolved() {
   17775         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
   17776     }
   17777 
   17778     /**
   17779      * Called when layout direction has been resolved.
   17780      *
   17781      * The default implementation does nothing.
   17782      *
   17783      * @param layoutDirection The resolved layout direction.
   17784      *
   17785      * @see #LAYOUT_DIRECTION_LTR
   17786      * @see #LAYOUT_DIRECTION_RTL
   17787      *
   17788      * @hide
   17789      */
   17790     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
   17791     }
   17792 
   17793     /**
   17794      * @hide
   17795      */
   17796     protected void resetResolvedDrawables() {
   17797         resetResolvedDrawablesInternal();
   17798     }
   17799 
   17800     void resetResolvedDrawablesInternal() {
   17801         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
   17802     }
   17803 
   17804     /**
   17805      * If your view subclass is displaying its own Drawable objects, it should
   17806      * override this function and return true for any Drawable it is
   17807      * displaying.  This allows animations for those drawables to be
   17808      * scheduled.
   17809      *
   17810      * <p>Be sure to call through to the super class when overriding this
   17811      * function.
   17812      *
   17813      * @param who The Drawable to verify.  Return true if it is one you are
   17814      *            displaying, else return the result of calling through to the
   17815      *            super class.
   17816      *
   17817      * @return boolean If true than the Drawable is being displayed in the
   17818      *         view; else false and it is not allowed to animate.
   17819      *
   17820      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
   17821      * @see #drawableStateChanged()
   17822      */
   17823     @CallSuper
   17824     protected boolean verifyDrawable(@NonNull Drawable who) {
   17825         // Avoid verifying the scroll bar drawable so that we don't end up in
   17826         // an invalidation loop. This effectively prevents the scroll bar
   17827         // drawable from triggering invalidations and scheduling runnables.
   17828         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
   17829     }
   17830 
   17831     /**
   17832      * This function is called whenever the state of the view changes in such
   17833      * a way that it impacts the state of drawables being shown.
   17834      * <p>
   17835      * If the View has a StateListAnimator, it will also be called to run necessary state
   17836      * change animations.
   17837      * <p>
   17838      * Be sure to call through to the superclass when overriding this function.
   17839      *
   17840      * @see Drawable#setState(int[])
   17841      */
   17842     @CallSuper
   17843     protected void drawableStateChanged() {
   17844         final int[] state = getDrawableState();
   17845         boolean changed = false;
   17846 
   17847         final Drawable bg = mBackground;
   17848         if (bg != null && bg.isStateful()) {
   17849             changed |= bg.setState(state);
   17850         }
   17851 
   17852         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   17853         if (fg != null && fg.isStateful()) {
   17854             changed |= fg.setState(state);
   17855         }
   17856 
   17857         if (mScrollCache != null) {
   17858             final Drawable scrollBar = mScrollCache.scrollBar;
   17859             if (scrollBar != null && scrollBar.isStateful()) {
   17860                 changed |= scrollBar.setState(state)
   17861                         && mScrollCache.state != ScrollabilityCache.OFF;
   17862             }
   17863         }
   17864 
   17865         if (mStateListAnimator != null) {
   17866             mStateListAnimator.setState(state);
   17867         }
   17868 
   17869         if (changed) {
   17870             invalidate();
   17871         }
   17872     }
   17873 
   17874     /**
   17875      * This function is called whenever the view hotspot changes and needs to
   17876      * be propagated to drawables or child views managed by the view.
   17877      * <p>
   17878      * Dispatching to child views is handled by
   17879      * {@link #dispatchDrawableHotspotChanged(float, float)}.
   17880      * <p>
   17881      * Be sure to call through to the superclass when overriding this function.
   17882      *
   17883      * @param x hotspot x coordinate
   17884      * @param y hotspot y coordinate
   17885      */
   17886     @CallSuper
   17887     public void drawableHotspotChanged(float x, float y) {
   17888         if (mBackground != null) {
   17889             mBackground.setHotspot(x, y);
   17890         }
   17891         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   17892             mForegroundInfo.mDrawable.setHotspot(x, y);
   17893         }
   17894 
   17895         dispatchDrawableHotspotChanged(x, y);
   17896     }
   17897 
   17898     /**
   17899      * Dispatches drawableHotspotChanged to all of this View's children.
   17900      *
   17901      * @param x hotspot x coordinate
   17902      * @param y hotspot y coordinate
   17903      * @see #drawableHotspotChanged(float, float)
   17904      */
   17905     public void dispatchDrawableHotspotChanged(float x, float y) {
   17906     }
   17907 
   17908     /**
   17909      * Call this to force a view to update its drawable state. This will cause
   17910      * drawableStateChanged to be called on this view. Views that are interested
   17911      * in the new state should call getDrawableState.
   17912      *
   17913      * @see #drawableStateChanged
   17914      * @see #getDrawableState
   17915      */
   17916     public void refreshDrawableState() {
   17917         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   17918         drawableStateChanged();
   17919 
   17920         ViewParent parent = mParent;
   17921         if (parent != null) {
   17922             parent.childDrawableStateChanged(this);
   17923         }
   17924     }
   17925 
   17926     /**
   17927      * Return an array of resource IDs of the drawable states representing the
   17928      * current state of the view.
   17929      *
   17930      * @return The current drawable state
   17931      *
   17932      * @see Drawable#setState(int[])
   17933      * @see #drawableStateChanged()
   17934      * @see #onCreateDrawableState(int)
   17935      */
   17936     public final int[] getDrawableState() {
   17937         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
   17938             return mDrawableState;
   17939         } else {
   17940             mDrawableState = onCreateDrawableState(0);
   17941             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
   17942             return mDrawableState;
   17943         }
   17944     }
   17945 
   17946     /**
   17947      * Generate the new {@link android.graphics.drawable.Drawable} state for
   17948      * this view. This is called by the view
   17949      * system when the cached Drawable state is determined to be invalid.  To
   17950      * retrieve the current state, you should use {@link #getDrawableState}.
   17951      *
   17952      * @param extraSpace if non-zero, this is the number of extra entries you
   17953      * would like in the returned array in which you can place your own
   17954      * states.
   17955      *
   17956      * @return Returns an array holding the current {@link Drawable} state of
   17957      * the view.
   17958      *
   17959      * @see #mergeDrawableStates(int[], int[])
   17960      */
   17961     protected int[] onCreateDrawableState(int extraSpace) {
   17962         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
   17963                 mParent instanceof View) {
   17964             return ((View) mParent).onCreateDrawableState(extraSpace);
   17965         }
   17966 
   17967         int[] drawableState;
   17968 
   17969         int privateFlags = mPrivateFlags;
   17970 
   17971         int viewStateIndex = 0;
   17972         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
   17973         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
   17974         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
   17975         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
   17976         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
   17977         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
   17978         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
   17979                 ThreadedRenderer.isAvailable()) {
   17980             // This is set if HW acceleration is requested, even if the current
   17981             // process doesn't allow it.  This is just to allow app preview
   17982             // windows to better match their app.
   17983             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
   17984         }
   17985         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
   17986 
   17987         final int privateFlags2 = mPrivateFlags2;
   17988         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
   17989             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
   17990         }
   17991         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
   17992             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
   17993         }
   17994 
   17995         drawableState = StateSet.get(viewStateIndex);
   17996 
   17997         //noinspection ConstantIfStatement
   17998         if (false) {
   17999             Log.i("View", "drawableStateIndex=" + viewStateIndex);
   18000             Log.i("View", toString()
   18001                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
   18002                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
   18003                     + " fo=" + hasFocus()
   18004                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
   18005                     + " wf=" + hasWindowFocus()
   18006                     + ": " + Arrays.toString(drawableState));
   18007         }
   18008 
   18009         if (extraSpace == 0) {
   18010             return drawableState;
   18011         }
   18012 
   18013         final int[] fullState;
   18014         if (drawableState != null) {
   18015             fullState = new int[drawableState.length + extraSpace];
   18016             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
   18017         } else {
   18018             fullState = new int[extraSpace];
   18019         }
   18020 
   18021         return fullState;
   18022     }
   18023 
   18024     /**
   18025      * Merge your own state values in <var>additionalState</var> into the base
   18026      * state values <var>baseState</var> that were returned by
   18027      * {@link #onCreateDrawableState(int)}.
   18028      *
   18029      * @param baseState The base state values returned by
   18030      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
   18031      * own additional state values.
   18032      *
   18033      * @param additionalState The additional state values you would like
   18034      * added to <var>baseState</var>; this array is not modified.
   18035      *
   18036      * @return As a convenience, the <var>baseState</var> array you originally
   18037      * passed into the function is returned.
   18038      *
   18039      * @see #onCreateDrawableState(int)
   18040      */
   18041     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
   18042         final int N = baseState.length;
   18043         int i = N - 1;
   18044         while (i >= 0 && baseState[i] == 0) {
   18045             i--;
   18046         }
   18047         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
   18048         return baseState;
   18049     }
   18050 
   18051     /**
   18052      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
   18053      * on all Drawable objects associated with this view.
   18054      * <p>
   18055      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
   18056      * attached to this view.
   18057      */
   18058     @CallSuper
   18059     public void jumpDrawablesToCurrentState() {
   18060         if (mBackground != null) {
   18061             mBackground.jumpToCurrentState();
   18062         }
   18063         if (mStateListAnimator != null) {
   18064             mStateListAnimator.jumpToCurrentState();
   18065         }
   18066         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   18067             mForegroundInfo.mDrawable.jumpToCurrentState();
   18068         }
   18069     }
   18070 
   18071     /**
   18072      * Sets the background color for this view.
   18073      * @param color the color of the background
   18074      */
   18075     @RemotableViewMethod
   18076     public void setBackgroundColor(@ColorInt int color) {
   18077         if (mBackground instanceof ColorDrawable) {
   18078             ((ColorDrawable) mBackground.mutate()).setColor(color);
   18079             computeOpaqueFlags();
   18080             mBackgroundResource = 0;
   18081         } else {
   18082             setBackground(new ColorDrawable(color));
   18083         }
   18084     }
   18085 
   18086     /**
   18087      * Set the background to a given resource. The resource should refer to
   18088      * a Drawable object or 0 to remove the background.
   18089      * @param resid The identifier of the resource.
   18090      *
   18091      * @attr ref android.R.styleable#View_background
   18092      */
   18093     @RemotableViewMethod
   18094     public void setBackgroundResource(@DrawableRes int resid) {
   18095         if (resid != 0 && resid == mBackgroundResource) {
   18096             return;
   18097         }
   18098 
   18099         Drawable d = null;
   18100         if (resid != 0) {
   18101             d = mContext.getDrawable(resid);
   18102         }
   18103         setBackground(d);
   18104 
   18105         mBackgroundResource = resid;
   18106     }
   18107 
   18108     /**
   18109      * Set the background to a given Drawable, or remove the background. If the
   18110      * background has padding, this View's padding is set to the background's
   18111      * padding. However, when a background is removed, this View's padding isn't
   18112      * touched. If setting the padding is desired, please use
   18113      * {@link #setPadding(int, int, int, int)}.
   18114      *
   18115      * @param background The Drawable to use as the background, or null to remove the
   18116      *        background
   18117      */
   18118     public void setBackground(Drawable background) {
   18119         //noinspection deprecation
   18120         setBackgroundDrawable(background);
   18121     }
   18122 
   18123     /**
   18124      * @deprecated use {@link #setBackground(Drawable)} instead
   18125      */
   18126     @Deprecated
   18127     public void setBackgroundDrawable(Drawable background) {
   18128         computeOpaqueFlags();
   18129 
   18130         if (background == mBackground) {
   18131             return;
   18132         }
   18133 
   18134         boolean requestLayout = false;
   18135 
   18136         mBackgroundResource = 0;
   18137 
   18138         /*
   18139          * Regardless of whether we're setting a new background or not, we want
   18140          * to clear the previous drawable. setVisible first while we still have the callback set.
   18141          */
   18142         if (mBackground != null) {
   18143             if (isAttachedToWindow()) {
   18144                 mBackground.setVisible(false, false);
   18145             }
   18146             mBackground.setCallback(null);
   18147             unscheduleDrawable(mBackground);
   18148         }
   18149 
   18150         if (background != null) {
   18151             Rect padding = sThreadLocal.get();
   18152             if (padding == null) {
   18153                 padding = new Rect();
   18154                 sThreadLocal.set(padding);
   18155             }
   18156             resetResolvedDrawablesInternal();
   18157             background.setLayoutDirection(getLayoutDirection());
   18158             if (background.getPadding(padding)) {
   18159                 resetResolvedPaddingInternal();
   18160                 switch (background.getLayoutDirection()) {
   18161                     case LAYOUT_DIRECTION_RTL:
   18162                         mUserPaddingLeftInitial = padding.right;
   18163                         mUserPaddingRightInitial = padding.left;
   18164                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
   18165                         break;
   18166                     case LAYOUT_DIRECTION_LTR:
   18167                     default:
   18168                         mUserPaddingLeftInitial = padding.left;
   18169                         mUserPaddingRightInitial = padding.right;
   18170                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
   18171                 }
   18172                 mLeftPaddingDefined = false;
   18173                 mRightPaddingDefined = false;
   18174             }
   18175 
   18176             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
   18177             // if it has a different minimum size, we should layout again
   18178             if (mBackground == null
   18179                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
   18180                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
   18181                 requestLayout = true;
   18182             }
   18183 
   18184             // Set mBackground before we set this as the callback and start making other
   18185             // background drawable state change calls. In particular, the setVisible call below
   18186             // can result in drawables attempting to start animations or otherwise invalidate,
   18187             // which requires the view set as the callback (us) to recognize the drawable as
   18188             // belonging to it as per verifyDrawable.
   18189             mBackground = background;
   18190             if (background.isStateful()) {
   18191                 background.setState(getDrawableState());
   18192             }
   18193             if (isAttachedToWindow()) {
   18194                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   18195             }
   18196 
   18197             applyBackgroundTint();
   18198 
   18199             // Set callback last, since the view may still be initializing.
   18200             background.setCallback(this);
   18201 
   18202             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   18203                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   18204                 requestLayout = true;
   18205             }
   18206         } else {
   18207             /* Remove the background */
   18208             mBackground = null;
   18209             if ((mViewFlags & WILL_NOT_DRAW) != 0
   18210                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
   18211                 mPrivateFlags |= PFLAG_SKIP_DRAW;
   18212             }
   18213 
   18214             /*
   18215              * When the background is set, we try to apply its padding to this
   18216              * View. When the background is removed, we don't touch this View's
   18217              * padding. This is noted in the Javadocs. Hence, we don't need to
   18218              * requestLayout(), the invalidate() below is sufficient.
   18219              */
   18220 
   18221             // The old background's minimum size could have affected this
   18222             // View's layout, so let's requestLayout
   18223             requestLayout = true;
   18224         }
   18225 
   18226         computeOpaqueFlags();
   18227 
   18228         if (requestLayout) {
   18229             requestLayout();
   18230         }
   18231 
   18232         mBackgroundSizeChanged = true;
   18233         invalidate(true);
   18234         invalidateOutline();
   18235     }
   18236 
   18237     /**
   18238      * Gets the background drawable
   18239      *
   18240      * @return The drawable used as the background for this view, if any.
   18241      *
   18242      * @see #setBackground(Drawable)
   18243      *
   18244      * @attr ref android.R.styleable#View_background
   18245      */
   18246     public Drawable getBackground() {
   18247         return mBackground;
   18248     }
   18249 
   18250     /**
   18251      * Applies a tint to the background drawable. Does not modify the current tint
   18252      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   18253      * <p>
   18254      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
   18255      * mutate the drawable and apply the specified tint and tint mode using
   18256      * {@link Drawable#setTintList(ColorStateList)}.
   18257      *
   18258      * @param tint the tint to apply, may be {@code null} to clear tint
   18259      *
   18260      * @attr ref android.R.styleable#View_backgroundTint
   18261      * @see #getBackgroundTintList()
   18262      * @see Drawable#setTintList(ColorStateList)
   18263      */
   18264     public void setBackgroundTintList(@Nullable ColorStateList tint) {
   18265         if (mBackgroundTint == null) {
   18266             mBackgroundTint = new TintInfo();
   18267         }
   18268         mBackgroundTint.mTintList = tint;
   18269         mBackgroundTint.mHasTintList = true;
   18270 
   18271         applyBackgroundTint();
   18272     }
   18273 
   18274     /**
   18275      * Return the tint applied to the background drawable, if specified.
   18276      *
   18277      * @return the tint applied to the background drawable
   18278      * @attr ref android.R.styleable#View_backgroundTint
   18279      * @see #setBackgroundTintList(ColorStateList)
   18280      */
   18281     @Nullable
   18282     public ColorStateList getBackgroundTintList() {
   18283         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
   18284     }
   18285 
   18286     /**
   18287      * Specifies the blending mode used to apply the tint specified by
   18288      * {@link #setBackgroundTintList(ColorStateList)}} to the background
   18289      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   18290      *
   18291      * @param tintMode the blending mode used to apply the tint, may be
   18292      *                 {@code null} to clear tint
   18293      * @attr ref android.R.styleable#View_backgroundTintMode
   18294      * @see #getBackgroundTintMode()
   18295      * @see Drawable#setTintMode(PorterDuff.Mode)
   18296      */
   18297     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   18298         if (mBackgroundTint == null) {
   18299             mBackgroundTint = new TintInfo();
   18300         }
   18301         mBackgroundTint.mTintMode = tintMode;
   18302         mBackgroundTint.mHasTintMode = true;
   18303 
   18304         applyBackgroundTint();
   18305     }
   18306 
   18307     /**
   18308      * Return the blending mode used to apply the tint to the background
   18309      * drawable, if specified.
   18310      *
   18311      * @return the blending mode used to apply the tint to the background
   18312      *         drawable
   18313      * @attr ref android.R.styleable#View_backgroundTintMode
   18314      * @see #setBackgroundTintMode(PorterDuff.Mode)
   18315      */
   18316     @Nullable
   18317     public PorterDuff.Mode getBackgroundTintMode() {
   18318         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
   18319     }
   18320 
   18321     private void applyBackgroundTint() {
   18322         if (mBackground != null && mBackgroundTint != null) {
   18323             final TintInfo tintInfo = mBackgroundTint;
   18324             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   18325                 mBackground = mBackground.mutate();
   18326 
   18327                 if (tintInfo.mHasTintList) {
   18328                     mBackground.setTintList(tintInfo.mTintList);
   18329                 }
   18330 
   18331                 if (tintInfo.mHasTintMode) {
   18332                     mBackground.setTintMode(tintInfo.mTintMode);
   18333                 }
   18334 
   18335                 // The drawable (or one of its children) may not have been
   18336                 // stateful before applying the tint, so let's try again.
   18337                 if (mBackground.isStateful()) {
   18338                     mBackground.setState(getDrawableState());
   18339                 }
   18340             }
   18341         }
   18342     }
   18343 
   18344     /**
   18345      * Returns the drawable used as the foreground of this View. The
   18346      * foreground drawable, if non-null, is always drawn on top of the view's content.
   18347      *
   18348      * @return a Drawable or null if no foreground was set
   18349      *
   18350      * @see #onDrawForeground(Canvas)
   18351      */
   18352     public Drawable getForeground() {
   18353         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   18354     }
   18355 
   18356     /**
   18357      * Supply a Drawable that is to be rendered on top of all of the content in the view.
   18358      *
   18359      * @param foreground the Drawable to be drawn on top of the children
   18360      *
   18361      * @attr ref android.R.styleable#View_foreground
   18362      */
   18363     public void setForeground(Drawable foreground) {
   18364         if (mForegroundInfo == null) {
   18365             if (foreground == null) {
   18366                 // Nothing to do.
   18367                 return;
   18368             }
   18369             mForegroundInfo = new ForegroundInfo();
   18370         }
   18371 
   18372         if (foreground == mForegroundInfo.mDrawable) {
   18373             // Nothing to do
   18374             return;
   18375         }
   18376 
   18377         if (mForegroundInfo.mDrawable != null) {
   18378             if (isAttachedToWindow()) {
   18379                 mForegroundInfo.mDrawable.setVisible(false, false);
   18380             }
   18381             mForegroundInfo.mDrawable.setCallback(null);
   18382             unscheduleDrawable(mForegroundInfo.mDrawable);
   18383         }
   18384 
   18385         mForegroundInfo.mDrawable = foreground;
   18386         mForegroundInfo.mBoundsChanged = true;
   18387         if (foreground != null) {
   18388             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   18389                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   18390             }
   18391             foreground.setLayoutDirection(getLayoutDirection());
   18392             if (foreground.isStateful()) {
   18393                 foreground.setState(getDrawableState());
   18394             }
   18395             applyForegroundTint();
   18396             if (isAttachedToWindow()) {
   18397                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   18398             }
   18399             // Set callback last, since the view may still be initializing.
   18400             foreground.setCallback(this);
   18401         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
   18402             mPrivateFlags |= PFLAG_SKIP_DRAW;
   18403         }
   18404         requestLayout();
   18405         invalidate();
   18406     }
   18407 
   18408     /**
   18409      * Magic bit used to support features of framework-internal window decor implementation details.
   18410      * This used to live exclusively in FrameLayout.
   18411      *
   18412      * @return true if the foreground should draw inside the padding region or false
   18413      *         if it should draw inset by the view's padding
   18414      * @hide internal use only; only used by FrameLayout and internal screen layouts.
   18415      */
   18416     public boolean isForegroundInsidePadding() {
   18417         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
   18418     }
   18419 
   18420     /**
   18421      * Describes how the foreground is positioned.
   18422      *
   18423      * @return foreground gravity.
   18424      *
   18425      * @see #setForegroundGravity(int)
   18426      *
   18427      * @attr ref android.R.styleable#View_foregroundGravity
   18428      */
   18429     public int getForegroundGravity() {
   18430         return mForegroundInfo != null ? mForegroundInfo.mGravity
   18431                 : Gravity.START | Gravity.TOP;
   18432     }
   18433 
   18434     /**
   18435      * Describes how the foreground is positioned. Defaults to START and TOP.
   18436      *
   18437      * @param gravity see {@link android.view.Gravity}
   18438      *
   18439      * @see #getForegroundGravity()
   18440      *
   18441      * @attr ref android.R.styleable#View_foregroundGravity
   18442      */
   18443     public void setForegroundGravity(int gravity) {
   18444         if (mForegroundInfo == null) {
   18445             mForegroundInfo = new ForegroundInfo();
   18446         }
   18447 
   18448         if (mForegroundInfo.mGravity != gravity) {
   18449             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
   18450                 gravity |= Gravity.START;
   18451             }
   18452 
   18453             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
   18454                 gravity |= Gravity.TOP;
   18455             }
   18456 
   18457             mForegroundInfo.mGravity = gravity;
   18458             requestLayout();
   18459         }
   18460     }
   18461 
   18462     /**
   18463      * Applies a tint to the foreground drawable. Does not modify the current tint
   18464      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   18465      * <p>
   18466      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
   18467      * mutate the drawable and apply the specified tint and tint mode using
   18468      * {@link Drawable#setTintList(ColorStateList)}.
   18469      *
   18470      * @param tint the tint to apply, may be {@code null} to clear tint
   18471      *
   18472      * @attr ref android.R.styleable#View_foregroundTint
   18473      * @see #getForegroundTintList()
   18474      * @see Drawable#setTintList(ColorStateList)
   18475      */
   18476     public void setForegroundTintList(@Nullable ColorStateList tint) {
   18477         if (mForegroundInfo == null) {
   18478             mForegroundInfo = new ForegroundInfo();
   18479         }
   18480         if (mForegroundInfo.mTintInfo == null) {
   18481             mForegroundInfo.mTintInfo = new TintInfo();
   18482         }
   18483         mForegroundInfo.mTintInfo.mTintList = tint;
   18484         mForegroundInfo.mTintInfo.mHasTintList = true;
   18485 
   18486         applyForegroundTint();
   18487     }
   18488 
   18489     /**
   18490      * Return the tint applied to the foreground drawable, if specified.
   18491      *
   18492      * @return the tint applied to the foreground drawable
   18493      * @attr ref android.R.styleable#View_foregroundTint
   18494      * @see #setForegroundTintList(ColorStateList)
   18495      */
   18496     @Nullable
   18497     public ColorStateList getForegroundTintList() {
   18498         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   18499                 ? mForegroundInfo.mTintInfo.mTintList : null;
   18500     }
   18501 
   18502     /**
   18503      * Specifies the blending mode used to apply the tint specified by
   18504      * {@link #setForegroundTintList(ColorStateList)}} to the background
   18505      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   18506      *
   18507      * @param tintMode the blending mode used to apply the tint, may be
   18508      *                 {@code null} to clear tint
   18509      * @attr ref android.R.styleable#View_foregroundTintMode
   18510      * @see #getForegroundTintMode()
   18511      * @see Drawable#setTintMode(PorterDuff.Mode)
   18512      */
   18513     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   18514         if (mForegroundInfo == null) {
   18515             mForegroundInfo = new ForegroundInfo();
   18516         }
   18517         if (mForegroundInfo.mTintInfo == null) {
   18518             mForegroundInfo.mTintInfo = new TintInfo();
   18519         }
   18520         mForegroundInfo.mTintInfo.mTintMode = tintMode;
   18521         mForegroundInfo.mTintInfo.mHasTintMode = true;
   18522 
   18523         applyForegroundTint();
   18524     }
   18525 
   18526     /**
   18527      * Return the blending mode used to apply the tint to the foreground
   18528      * drawable, if specified.
   18529      *
   18530      * @return the blending mode used to apply the tint to the foreground
   18531      *         drawable
   18532      * @attr ref android.R.styleable#View_foregroundTintMode
   18533      * @see #setForegroundTintMode(PorterDuff.Mode)
   18534      */
   18535     @Nullable
   18536     public PorterDuff.Mode getForegroundTintMode() {
   18537         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   18538                 ? mForegroundInfo.mTintInfo.mTintMode : null;
   18539     }
   18540 
   18541     private void applyForegroundTint() {
   18542         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   18543                 && mForegroundInfo.mTintInfo != null) {
   18544             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
   18545             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   18546                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
   18547 
   18548                 if (tintInfo.mHasTintList) {
   18549                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
   18550                 }
   18551 
   18552                 if (tintInfo.mHasTintMode) {
   18553                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
   18554                 }
   18555 
   18556                 // The drawable (or one of its children) may not have been
   18557                 // stateful before applying the tint, so let's try again.
   18558                 if (mForegroundInfo.mDrawable.isStateful()) {
   18559                     mForegroundInfo.mDrawable.setState(getDrawableState());
   18560                 }
   18561             }
   18562         }
   18563     }
   18564 
   18565     /**
   18566      * Draw any foreground content for this view.
   18567      *
   18568      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
   18569      * drawable or other view-specific decorations. The foreground is drawn on top of the
   18570      * primary view content.</p>
   18571      *
   18572      * @param canvas canvas to draw into
   18573      */
   18574     public void onDrawForeground(Canvas canvas) {
   18575         onDrawScrollIndicators(canvas);
   18576         onDrawScrollBars(canvas);
   18577 
   18578         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   18579         if (foreground != null) {
   18580             if (mForegroundInfo.mBoundsChanged) {
   18581                 mForegroundInfo.mBoundsChanged = false;
   18582                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
   18583                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
   18584 
   18585                 if (mForegroundInfo.mInsidePadding) {
   18586                     selfBounds.set(0, 0, getWidth(), getHeight());
   18587                 } else {
   18588                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
   18589                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
   18590                 }
   18591 
   18592                 final int ld = getLayoutDirection();
   18593                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
   18594                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
   18595                 foreground.setBounds(overlayBounds);
   18596             }
   18597 
   18598             foreground.draw(canvas);
   18599         }
   18600     }
   18601 
   18602     /**
   18603      * Sets the padding. The view may add on the space required to display
   18604      * the scrollbars, depending on the style and visibility of the scrollbars.
   18605      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
   18606      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
   18607      * from the values set in this call.
   18608      *
   18609      * @attr ref android.R.styleable#View_padding
   18610      * @attr ref android.R.styleable#View_paddingBottom
   18611      * @attr ref android.R.styleable#View_paddingLeft
   18612      * @attr ref android.R.styleable#View_paddingRight
   18613      * @attr ref android.R.styleable#View_paddingTop
   18614      * @param left the left padding in pixels
   18615      * @param top the top padding in pixels
   18616      * @param right the right padding in pixels
   18617      * @param bottom the bottom padding in pixels
   18618      */
   18619     public void setPadding(int left, int top, int right, int bottom) {
   18620         resetResolvedPaddingInternal();
   18621 
   18622         mUserPaddingStart = UNDEFINED_PADDING;
   18623         mUserPaddingEnd = UNDEFINED_PADDING;
   18624 
   18625         mUserPaddingLeftInitial = left;
   18626         mUserPaddingRightInitial = right;
   18627 
   18628         mLeftPaddingDefined = true;
   18629         mRightPaddingDefined = true;
   18630 
   18631         internalSetPadding(left, top, right, bottom);
   18632     }
   18633 
   18634     /**
   18635      * @hide
   18636      */
   18637     protected void internalSetPadding(int left, int top, int right, int bottom) {
   18638         mUserPaddingLeft = left;
   18639         mUserPaddingRight = right;
   18640         mUserPaddingBottom = bottom;
   18641 
   18642         final int viewFlags = mViewFlags;
   18643         boolean changed = false;
   18644 
   18645         // Common case is there are no scroll bars.
   18646         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
   18647             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
   18648                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
   18649                         ? 0 : getVerticalScrollbarWidth();
   18650                 switch (mVerticalScrollbarPosition) {
   18651                     case SCROLLBAR_POSITION_DEFAULT:
   18652                         if (isLayoutRtl()) {
   18653                             left += offset;
   18654                         } else {
   18655                             right += offset;
   18656                         }
   18657                         break;
   18658                     case SCROLLBAR_POSITION_RIGHT:
   18659                         right += offset;
   18660                         break;
   18661                     case SCROLLBAR_POSITION_LEFT:
   18662                         left += offset;
   18663                         break;
   18664                 }
   18665             }
   18666             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
   18667                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
   18668                         ? 0 : getHorizontalScrollbarHeight();
   18669             }
   18670         }
   18671 
   18672         if (mPaddingLeft != left) {
   18673             changed = true;
   18674             mPaddingLeft = left;
   18675         }
   18676         if (mPaddingTop != top) {
   18677             changed = true;
   18678             mPaddingTop = top;
   18679         }
   18680         if (mPaddingRight != right) {
   18681             changed = true;
   18682             mPaddingRight = right;
   18683         }
   18684         if (mPaddingBottom != bottom) {
   18685             changed = true;
   18686             mPaddingBottom = bottom;
   18687         }
   18688 
   18689         if (changed) {
   18690             requestLayout();
   18691             invalidateOutline();
   18692         }
   18693     }
   18694 
   18695     /**
   18696      * Sets the relative padding. The view may add on the space required to display
   18697      * the scrollbars, depending on the style and visibility of the scrollbars.
   18698      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
   18699      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
   18700      * from the values set in this call.
   18701      *
   18702      * @attr ref android.R.styleable#View_padding
   18703      * @attr ref android.R.styleable#View_paddingBottom
   18704      * @attr ref android.R.styleable#View_paddingStart
   18705      * @attr ref android.R.styleable#View_paddingEnd
   18706      * @attr ref android.R.styleable#View_paddingTop
   18707      * @param start the start padding in pixels
   18708      * @param top the top padding in pixels
   18709      * @param end the end padding in pixels
   18710      * @param bottom the bottom padding in pixels
   18711      */
   18712     public void setPaddingRelative(int start, int top, int end, int bottom) {
   18713         resetResolvedPaddingInternal();
   18714 
   18715         mUserPaddingStart = start;
   18716         mUserPaddingEnd = end;
   18717         mLeftPaddingDefined = true;
   18718         mRightPaddingDefined = true;
   18719 
   18720         switch(getLayoutDirection()) {
   18721             case LAYOUT_DIRECTION_RTL:
   18722                 mUserPaddingLeftInitial = end;
   18723                 mUserPaddingRightInitial = start;
   18724                 internalSetPadding(end, top, start, bottom);
   18725                 break;
   18726             case LAYOUT_DIRECTION_LTR:
   18727             default:
   18728                 mUserPaddingLeftInitial = start;
   18729                 mUserPaddingRightInitial = end;
   18730                 internalSetPadding(start, top, end, bottom);
   18731         }
   18732     }
   18733 
   18734     /**
   18735      * Returns the top padding of this view.
   18736      *
   18737      * @return the top padding in pixels
   18738      */
   18739     public int getPaddingTop() {
   18740         return mPaddingTop;
   18741     }
   18742 
   18743     /**
   18744      * Returns the bottom padding of this view. If there are inset and enabled
   18745      * scrollbars, this value may include the space required to display the
   18746      * scrollbars as well.
   18747      *
   18748      * @return the bottom padding in pixels
   18749      */
   18750     public int getPaddingBottom() {
   18751         return mPaddingBottom;
   18752     }
   18753 
   18754     /**
   18755      * Returns the left padding of this view. If there are inset and enabled
   18756      * scrollbars, this value may include the space required to display the
   18757      * scrollbars as well.
   18758      *
   18759      * @return the left padding in pixels
   18760      */
   18761     public int getPaddingLeft() {
   18762         if (!isPaddingResolved()) {
   18763             resolvePadding();
   18764         }
   18765         return mPaddingLeft;
   18766     }
   18767 
   18768     /**
   18769      * Returns the start padding of this view depending on its resolved layout direction.
   18770      * If there are inset and enabled scrollbars, this value may include the space
   18771      * required to display the scrollbars as well.
   18772      *
   18773      * @return the start padding in pixels
   18774      */
   18775     public int getPaddingStart() {
   18776         if (!isPaddingResolved()) {
   18777             resolvePadding();
   18778         }
   18779         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   18780                 mPaddingRight : mPaddingLeft;
   18781     }
   18782 
   18783     /**
   18784      * Returns the right padding of this view. If there are inset and enabled
   18785      * scrollbars, this value may include the space required to display the
   18786      * scrollbars as well.
   18787      *
   18788      * @return the right padding in pixels
   18789      */
   18790     public int getPaddingRight() {
   18791         if (!isPaddingResolved()) {
   18792             resolvePadding();
   18793         }
   18794         return mPaddingRight;
   18795     }
   18796 
   18797     /**
   18798      * Returns the end padding of this view depending on its resolved layout direction.
   18799      * If there are inset and enabled scrollbars, this value may include the space
   18800      * required to display the scrollbars as well.
   18801      *
   18802      * @return the end padding in pixels
   18803      */
   18804     public int getPaddingEnd() {
   18805         if (!isPaddingResolved()) {
   18806             resolvePadding();
   18807         }
   18808         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   18809                 mPaddingLeft : mPaddingRight;
   18810     }
   18811 
   18812     /**
   18813      * Return if the padding has been set through relative values
   18814      * {@link #setPaddingRelative(int, int, int, int)} or through
   18815      * @attr ref android.R.styleable#View_paddingStart or
   18816      * @attr ref android.R.styleable#View_paddingEnd
   18817      *
   18818      * @return true if the padding is relative or false if it is not.
   18819      */
   18820     public boolean isPaddingRelative() {
   18821         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
   18822     }
   18823 
   18824     Insets computeOpticalInsets() {
   18825         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
   18826     }
   18827 
   18828     /**
   18829      * @hide
   18830      */
   18831     public void resetPaddingToInitialValues() {
   18832         if (isRtlCompatibilityMode()) {
   18833             mPaddingLeft = mUserPaddingLeftInitial;
   18834             mPaddingRight = mUserPaddingRightInitial;
   18835             return;
   18836         }
   18837         if (isLayoutRtl()) {
   18838             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
   18839             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
   18840         } else {
   18841             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
   18842             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
   18843         }
   18844     }
   18845 
   18846     /**
   18847      * @hide
   18848      */
   18849     public Insets getOpticalInsets() {
   18850         if (mLayoutInsets == null) {
   18851             mLayoutInsets = computeOpticalInsets();
   18852         }
   18853         return mLayoutInsets;
   18854     }
   18855 
   18856     /**
   18857      * Set this view's optical insets.
   18858      *
   18859      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
   18860      * property. Views that compute their own optical insets should call it as part of measurement.
   18861      * This method does not request layout. If you are setting optical insets outside of
   18862      * measure/layout itself you will want to call requestLayout() yourself.
   18863      * </p>
   18864      * @hide
   18865      */
   18866     public void setOpticalInsets(Insets insets) {
   18867         mLayoutInsets = insets;
   18868     }
   18869 
   18870     /**
   18871      * Changes the selection state of this view. A view can be selected or not.
   18872      * Note that selection is not the same as focus. Views are typically
   18873      * selected in the context of an AdapterView like ListView or GridView;
   18874      * the selected view is the view that is highlighted.
   18875      *
   18876      * @param selected true if the view must be selected, false otherwise
   18877      */
   18878     public void setSelected(boolean selected) {
   18879         //noinspection DoubleNegation
   18880         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
   18881             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
   18882             if (!selected) resetPressedState();
   18883             invalidate(true);
   18884             refreshDrawableState();
   18885             dispatchSetSelected(selected);
   18886             if (selected) {
   18887                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
   18888             } else {
   18889                 notifyViewAccessibilityStateChangedIfNeeded(
   18890                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   18891             }
   18892         }
   18893     }
   18894 
   18895     /**
   18896      * Dispatch setSelected to all of this View's children.
   18897      *
   18898      * @see #setSelected(boolean)
   18899      *
   18900      * @param selected The new selected state
   18901      */
   18902     protected void dispatchSetSelected(boolean selected) {
   18903     }
   18904 
   18905     /**
   18906      * Indicates the selection state of this view.
   18907      *
   18908      * @return true if the view is selected, false otherwise
   18909      */
   18910     @ViewDebug.ExportedProperty
   18911     public boolean isSelected() {
   18912         return (mPrivateFlags & PFLAG_SELECTED) != 0;
   18913     }
   18914 
   18915     /**
   18916      * Changes the activated state of this view. A view can be activated or not.
   18917      * Note that activation is not the same as selection.  Selection is
   18918      * a transient property, representing the view (hierarchy) the user is
   18919      * currently interacting with.  Activation is a longer-term state that the
   18920      * user can move views in and out of.  For example, in a list view with
   18921      * single or multiple selection enabled, the views in the current selection
   18922      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
   18923      * here.)  The activated state is propagated down to children of the view it
   18924      * is set on.
   18925      *
   18926      * @param activated true if the view must be activated, false otherwise
   18927      */
   18928     public void setActivated(boolean activated) {
   18929         //noinspection DoubleNegation
   18930         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
   18931             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
   18932             invalidate(true);
   18933             refreshDrawableState();
   18934             dispatchSetActivated(activated);
   18935         }
   18936     }
   18937 
   18938     /**
   18939      * Dispatch setActivated to all of this View's children.
   18940      *
   18941      * @see #setActivated(boolean)
   18942      *
   18943      * @param activated The new activated state
   18944      */
   18945     protected void dispatchSetActivated(boolean activated) {
   18946     }
   18947 
   18948     /**
   18949      * Indicates the activation state of this view.
   18950      *
   18951      * @return true if the view is activated, false otherwise
   18952      */
   18953     @ViewDebug.ExportedProperty
   18954     public boolean isActivated() {
   18955         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
   18956     }
   18957 
   18958     /**
   18959      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
   18960      * observer can be used to get notifications when global events, like
   18961      * layout, happen.
   18962      *
   18963      * The returned ViewTreeObserver observer is not guaranteed to remain
   18964      * valid for the lifetime of this View. If the caller of this method keeps
   18965      * a long-lived reference to ViewTreeObserver, it should always check for
   18966      * the return value of {@link ViewTreeObserver#isAlive()}.
   18967      *
   18968      * @return The ViewTreeObserver for this view's hierarchy.
   18969      */
   18970     public ViewTreeObserver getViewTreeObserver() {
   18971         if (mAttachInfo != null) {
   18972             return mAttachInfo.mTreeObserver;
   18973         }
   18974         if (mFloatingTreeObserver == null) {
   18975             mFloatingTreeObserver = new ViewTreeObserver();
   18976         }
   18977         return mFloatingTreeObserver;
   18978     }
   18979 
   18980     /**
   18981      * <p>Finds the topmost view in the current view hierarchy.</p>
   18982      *
   18983      * @return the topmost view containing this view
   18984      */
   18985     public View getRootView() {
   18986         if (mAttachInfo != null) {
   18987             final View v = mAttachInfo.mRootView;
   18988             if (v != null) {
   18989                 return v;
   18990             }
   18991         }
   18992 
   18993         View parent = this;
   18994 
   18995         while (parent.mParent != null && parent.mParent instanceof View) {
   18996             parent = (View) parent.mParent;
   18997         }
   18998 
   18999         return parent;
   19000     }
   19001 
   19002     /**
   19003      * Transforms a motion event from view-local coordinates to on-screen
   19004      * coordinates.
   19005      *
   19006      * @param ev the view-local motion event
   19007      * @return false if the transformation could not be applied
   19008      * @hide
   19009      */
   19010     public boolean toGlobalMotionEvent(MotionEvent ev) {
   19011         final AttachInfo info = mAttachInfo;
   19012         if (info == null) {
   19013             return false;
   19014         }
   19015 
   19016         final Matrix m = info.mTmpMatrix;
   19017         m.set(Matrix.IDENTITY_MATRIX);
   19018         transformMatrixToGlobal(m);
   19019         ev.transform(m);
   19020         return true;
   19021     }
   19022 
   19023     /**
   19024      * Transforms a motion event from on-screen coordinates to view-local
   19025      * coordinates.
   19026      *
   19027      * @param ev the on-screen motion event
   19028      * @return false if the transformation could not be applied
   19029      * @hide
   19030      */
   19031     public boolean toLocalMotionEvent(MotionEvent ev) {
   19032         final AttachInfo info = mAttachInfo;
   19033         if (info == null) {
   19034             return false;
   19035         }
   19036 
   19037         final Matrix m = info.mTmpMatrix;
   19038         m.set(Matrix.IDENTITY_MATRIX);
   19039         transformMatrixToLocal(m);
   19040         ev.transform(m);
   19041         return true;
   19042     }
   19043 
   19044     /**
   19045      * Modifies the input matrix such that it maps view-local coordinates to
   19046      * on-screen coordinates.
   19047      *
   19048      * @param m input matrix to modify
   19049      * @hide
   19050      */
   19051     public void transformMatrixToGlobal(Matrix m) {
   19052         final ViewParent parent = mParent;
   19053         if (parent instanceof View) {
   19054             final View vp = (View) parent;
   19055             vp.transformMatrixToGlobal(m);
   19056             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
   19057         } else if (parent instanceof ViewRootImpl) {
   19058             final ViewRootImpl vr = (ViewRootImpl) parent;
   19059             vr.transformMatrixToGlobal(m);
   19060             m.preTranslate(0, -vr.mCurScrollY);
   19061         }
   19062 
   19063         m.preTranslate(mLeft, mTop);
   19064 
   19065         if (!hasIdentityMatrix()) {
   19066             m.preConcat(getMatrix());
   19067         }
   19068     }
   19069 
   19070     /**
   19071      * Modifies the input matrix such that it maps on-screen coordinates to
   19072      * view-local coordinates.
   19073      *
   19074      * @param m input matrix to modify
   19075      * @hide
   19076      */
   19077     public void transformMatrixToLocal(Matrix m) {
   19078         final ViewParent parent = mParent;
   19079         if (parent instanceof View) {
   19080             final View vp = (View) parent;
   19081             vp.transformMatrixToLocal(m);
   19082             m.postTranslate(vp.mScrollX, vp.mScrollY);
   19083         } else if (parent instanceof ViewRootImpl) {
   19084             final ViewRootImpl vr = (ViewRootImpl) parent;
   19085             vr.transformMatrixToLocal(m);
   19086             m.postTranslate(0, vr.mCurScrollY);
   19087         }
   19088 
   19089         m.postTranslate(-mLeft, -mTop);
   19090 
   19091         if (!hasIdentityMatrix()) {
   19092             m.postConcat(getInverseMatrix());
   19093         }
   19094     }
   19095 
   19096     /**
   19097      * @hide
   19098      */
   19099     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
   19100             @ViewDebug.IntToString(from = 0, to = "x"),
   19101             @ViewDebug.IntToString(from = 1, to = "y")
   19102     })
   19103     public int[] getLocationOnScreen() {
   19104         int[] location = new int[2];
   19105         getLocationOnScreen(location);
   19106         return location;
   19107     }
   19108 
   19109     /**
   19110      * <p>Computes the coordinates of this view on the screen. The argument
   19111      * must be an array of two integers. After the method returns, the array
   19112      * contains the x and y location in that order.</p>
   19113      *
   19114      * @param outLocation an array of two integers in which to hold the coordinates
   19115      */
   19116     public void getLocationOnScreen(@Size(2) int[] outLocation) {
   19117         getLocationInWindow(outLocation);
   19118 
   19119         final AttachInfo info = mAttachInfo;
   19120         if (info != null) {
   19121             outLocation[0] += info.mWindowLeft;
   19122             outLocation[1] += info.mWindowTop;
   19123         }
   19124     }
   19125 
   19126     /**
   19127      * <p>Computes the coordinates of this view in its window. The argument
   19128      * must be an array of two integers. After the method returns, the array
   19129      * contains the x and y location in that order.</p>
   19130      *
   19131      * @param outLocation an array of two integers in which to hold the coordinates
   19132      */
   19133     public void getLocationInWindow(@Size(2) int[] outLocation) {
   19134         if (outLocation == null || outLocation.length < 2) {
   19135             throw new IllegalArgumentException("outLocation must be an array of two integers");
   19136         }
   19137 
   19138         outLocation[0] = 0;
   19139         outLocation[1] = 0;
   19140 
   19141         transformFromViewToWindowSpace(outLocation);
   19142     }
   19143 
   19144     /** @hide */
   19145     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
   19146         if (inOutLocation == null || inOutLocation.length < 2) {
   19147             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
   19148         }
   19149 
   19150         if (mAttachInfo == null) {
   19151             // When the view is not attached to a window, this method does not make sense
   19152             inOutLocation[0] = inOutLocation[1] = 0;
   19153             return;
   19154         }
   19155 
   19156         float position[] = mAttachInfo.mTmpTransformLocation;
   19157         position[0] = inOutLocation[0];
   19158         position[1] = inOutLocation[1];
   19159 
   19160         if (!hasIdentityMatrix()) {
   19161             getMatrix().mapPoints(position);
   19162         }
   19163 
   19164         position[0] += mLeft;
   19165         position[1] += mTop;
   19166 
   19167         ViewParent viewParent = mParent;
   19168         while (viewParent instanceof View) {
   19169             final View view = (View) viewParent;
   19170 
   19171             position[0] -= view.mScrollX;
   19172             position[1] -= view.mScrollY;
   19173 
   19174             if (!view.hasIdentityMatrix()) {
   19175                 view.getMatrix().mapPoints(position);
   19176             }
   19177 
   19178             position[0] += view.mLeft;
   19179             position[1] += view.mTop;
   19180 
   19181             viewParent = view.mParent;
   19182          }
   19183 
   19184         if (viewParent instanceof ViewRootImpl) {
   19185             // *cough*
   19186             final ViewRootImpl vr = (ViewRootImpl) viewParent;
   19187             position[1] -= vr.mCurScrollY;
   19188         }
   19189 
   19190         inOutLocation[0] = Math.round(position[0]);
   19191         inOutLocation[1] = Math.round(position[1]);
   19192     }
   19193 
   19194     /**
   19195      * {@hide}
   19196      * @param id the id of the view to be found
   19197      * @return the view of the specified id, null if cannot be found
   19198      */
   19199     protected View findViewTraversal(@IdRes int id) {
   19200         if (id == mID) {
   19201             return this;
   19202         }
   19203         return null;
   19204     }
   19205 
   19206     /**
   19207      * {@hide}
   19208      * @param tag the tag of the view to be found
   19209      * @return the view of specified tag, null if cannot be found
   19210      */
   19211     protected View findViewWithTagTraversal(Object tag) {
   19212         if (tag != null && tag.equals(mTag)) {
   19213             return this;
   19214         }
   19215         return null;
   19216     }
   19217 
   19218     /**
   19219      * {@hide}
   19220      * @param predicate The predicate to evaluate.
   19221      * @param childToSkip If not null, ignores this child during the recursive traversal.
   19222      * @return The first view that matches the predicate or null.
   19223      */
   19224     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
   19225         if (predicate.apply(this)) {
   19226             return this;
   19227         }
   19228         return null;
   19229     }
   19230 
   19231     /**
   19232      * Look for a child view with the given id.  If this view has the given
   19233      * id, return this view.
   19234      *
   19235      * @param id The id to search for.
   19236      * @return The view that has the given id in the hierarchy or null
   19237      */
   19238     @Nullable
   19239     public final View findViewById(@IdRes int id) {
   19240         if (id < 0) {
   19241             return null;
   19242         }
   19243         return findViewTraversal(id);
   19244     }
   19245 
   19246     /**
   19247      * Finds a view by its unuque and stable accessibility id.
   19248      *
   19249      * @param accessibilityId The searched accessibility id.
   19250      * @return The found view.
   19251      */
   19252     final View findViewByAccessibilityId(int accessibilityId) {
   19253         if (accessibilityId < 0) {
   19254             return null;
   19255         }
   19256         View view = findViewByAccessibilityIdTraversal(accessibilityId);
   19257         if (view != null) {
   19258             return view.includeForAccessibility() ? view : null;
   19259         }
   19260         return null;
   19261     }
   19262 
   19263     /**
   19264      * Performs the traversal to find a view by its unuque and stable accessibility id.
   19265      *
   19266      * <strong>Note:</strong>This method does not stop at the root namespace
   19267      * boundary since the user can touch the screen at an arbitrary location
   19268      * potentially crossing the root namespace bounday which will send an
   19269      * accessibility event to accessibility services and they should be able
   19270      * to obtain the event source. Also accessibility ids are guaranteed to be
   19271      * unique in the window.
   19272      *
   19273      * @param accessibilityId The accessibility id.
   19274      * @return The found view.
   19275      *
   19276      * @hide
   19277      */
   19278     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
   19279         if (getAccessibilityViewId() == accessibilityId) {
   19280             return this;
   19281         }
   19282         return null;
   19283     }
   19284 
   19285     /**
   19286      * Look for a child view with the given tag.  If this view has the given
   19287      * tag, return this view.
   19288      *
   19289      * @param tag The tag to search for, using "tag.equals(getTag())".
   19290      * @return The View that has the given tag in the hierarchy or null
   19291      */
   19292     public final View findViewWithTag(Object tag) {
   19293         if (tag == null) {
   19294             return null;
   19295         }
   19296         return findViewWithTagTraversal(tag);
   19297     }
   19298 
   19299     /**
   19300      * {@hide}
   19301      * Look for a child view that matches the specified predicate.
   19302      * If this view matches the predicate, return this view.
   19303      *
   19304      * @param predicate The predicate to evaluate.
   19305      * @return The first view that matches the predicate or null.
   19306      */
   19307     public final View findViewByPredicate(Predicate<View> predicate) {
   19308         return findViewByPredicateTraversal(predicate, null);
   19309     }
   19310 
   19311     /**
   19312      * {@hide}
   19313      * Look for a child view that matches the specified predicate,
   19314      * starting with the specified view and its descendents and then
   19315      * recusively searching the ancestors and siblings of that view
   19316      * until this view is reached.
   19317      *
   19318      * This method is useful in cases where the predicate does not match
   19319      * a single unique view (perhaps multiple views use the same id)
   19320      * and we are trying to find the view that is "closest" in scope to the
   19321      * starting view.
   19322      *
   19323      * @param start The view to start from.
   19324      * @param predicate The predicate to evaluate.
   19325      * @return The first view that matches the predicate or null.
   19326      */
   19327     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
   19328         View childToSkip = null;
   19329         for (;;) {
   19330             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
   19331             if (view != null || start == this) {
   19332                 return view;
   19333             }
   19334 
   19335             ViewParent parent = start.getParent();
   19336             if (parent == null || !(parent instanceof View)) {
   19337                 return null;
   19338             }
   19339 
   19340             childToSkip = start;
   19341             start = (View) parent;
   19342         }
   19343     }
   19344 
   19345     /**
   19346      * Sets the identifier for this view. The identifier does not have to be
   19347      * unique in this view's hierarchy. The identifier should be a positive
   19348      * number.
   19349      *
   19350      * @see #NO_ID
   19351      * @see #getId()
   19352      * @see #findViewById(int)
   19353      *
   19354      * @param id a number used to identify the view
   19355      *
   19356      * @attr ref android.R.styleable#View_id
   19357      */
   19358     public void setId(@IdRes int id) {
   19359         mID = id;
   19360         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
   19361             mID = generateViewId();
   19362         }
   19363     }
   19364 
   19365     /**
   19366      * {@hide}
   19367      *
   19368      * @param isRoot true if the view belongs to the root namespace, false
   19369      *        otherwise
   19370      */
   19371     public void setIsRootNamespace(boolean isRoot) {
   19372         if (isRoot) {
   19373             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
   19374         } else {
   19375             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
   19376         }
   19377     }
   19378 
   19379     /**
   19380      * {@hide}
   19381      *
   19382      * @return true if the view belongs to the root namespace, false otherwise
   19383      */
   19384     public boolean isRootNamespace() {
   19385         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
   19386     }
   19387 
   19388     /**
   19389      * Returns this view's identifier.
   19390      *
   19391      * @return a positive integer used to identify the view or {@link #NO_ID}
   19392      *         if the view has no ID
   19393      *
   19394      * @see #setId(int)
   19395      * @see #findViewById(int)
   19396      * @attr ref android.R.styleable#View_id
   19397      */
   19398     @IdRes
   19399     @ViewDebug.CapturedViewProperty
   19400     public int getId() {
   19401         return mID;
   19402     }
   19403 
   19404     /**
   19405      * Returns this view's tag.
   19406      *
   19407      * @return the Object stored in this view as a tag, or {@code null} if not
   19408      *         set
   19409      *
   19410      * @see #setTag(Object)
   19411      * @see #getTag(int)
   19412      */
   19413     @ViewDebug.ExportedProperty
   19414     public Object getTag() {
   19415         return mTag;
   19416     }
   19417 
   19418     /**
   19419      * Sets the tag associated with this view. A tag can be used to mark
   19420      * a view in its hierarchy and does not have to be unique within the
   19421      * hierarchy. Tags can also be used to store data within a view without
   19422      * resorting to another data structure.
   19423      *
   19424      * @param tag an Object to tag the view with
   19425      *
   19426      * @see #getTag()
   19427      * @see #setTag(int, Object)
   19428      */
   19429     public void setTag(final Object tag) {
   19430         mTag = tag;
   19431     }
   19432 
   19433     /**
   19434      * Returns the tag associated with this view and the specified key.
   19435      *
   19436      * @param key The key identifying the tag
   19437      *
   19438      * @return the Object stored in this view as a tag, or {@code null} if not
   19439      *         set
   19440      *
   19441      * @see #setTag(int, Object)
   19442      * @see #getTag()
   19443      */
   19444     public Object getTag(int key) {
   19445         if (mKeyedTags != null) return mKeyedTags.get(key);
   19446         return null;
   19447     }
   19448 
   19449     /**
   19450      * Sets a tag associated with this view and a key. A tag can be used
   19451      * to mark a view in its hierarchy and does not have to be unique within
   19452      * the hierarchy. Tags can also be used to store data within a view
   19453      * without resorting to another data structure.
   19454      *
   19455      * The specified key should be an id declared in the resources of the
   19456      * application to ensure it is unique (see the <a
   19457      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
   19458      * Keys identified as belonging to
   19459      * the Android framework or not associated with any package will cause
   19460      * an {@link IllegalArgumentException} to be thrown.
   19461      *
   19462      * @param key The key identifying the tag
   19463      * @param tag An Object to tag the view with
   19464      *
   19465      * @throws IllegalArgumentException If they specified key is not valid
   19466      *
   19467      * @see #setTag(Object)
   19468      * @see #getTag(int)
   19469      */
   19470     public void setTag(int key, final Object tag) {
   19471         // If the package id is 0x00 or 0x01, it's either an undefined package
   19472         // or a framework id
   19473         if ((key >>> 24) < 2) {
   19474             throw new IllegalArgumentException("The key must be an application-specific "
   19475                     + "resource id.");
   19476         }
   19477 
   19478         setKeyedTag(key, tag);
   19479     }
   19480 
   19481     /**
   19482      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
   19483      * framework id.
   19484      *
   19485      * @hide
   19486      */
   19487     public void setTagInternal(int key, Object tag) {
   19488         if ((key >>> 24) != 0x1) {
   19489             throw new IllegalArgumentException("The key must be a framework-specific "
   19490                     + "resource id.");
   19491         }
   19492 
   19493         setKeyedTag(key, tag);
   19494     }
   19495 
   19496     private void setKeyedTag(int key, Object tag) {
   19497         if (mKeyedTags == null) {
   19498             mKeyedTags = new SparseArray<Object>(2);
   19499         }
   19500 
   19501         mKeyedTags.put(key, tag);
   19502     }
   19503 
   19504     /**
   19505      * Prints information about this view in the log output, with the tag
   19506      * {@link #VIEW_LOG_TAG}.
   19507      *
   19508      * @hide
   19509      */
   19510     public void debug() {
   19511         debug(0);
   19512     }
   19513 
   19514     /**
   19515      * Prints information about this view in the log output, with the tag
   19516      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
   19517      * indentation defined by the <code>depth</code>.
   19518      *
   19519      * @param depth the indentation level
   19520      *
   19521      * @hide
   19522      */
   19523     protected void debug(int depth) {
   19524         String output = debugIndent(depth - 1);
   19525 
   19526         output += "+ " + this;
   19527         int id = getId();
   19528         if (id != -1) {
   19529             output += " (id=" + id + ")";
   19530         }
   19531         Object tag = getTag();
   19532         if (tag != null) {
   19533             output += " (tag=" + tag + ")";
   19534         }
   19535         Log.d(VIEW_LOG_TAG, output);
   19536 
   19537         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   19538             output = debugIndent(depth) + " FOCUSED";
   19539             Log.d(VIEW_LOG_TAG, output);
   19540         }
   19541 
   19542         output = debugIndent(depth);
   19543         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
   19544                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
   19545                 + "} ";
   19546         Log.d(VIEW_LOG_TAG, output);
   19547 
   19548         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
   19549                 || mPaddingBottom != 0) {
   19550             output = debugIndent(depth);
   19551             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
   19552                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
   19553             Log.d(VIEW_LOG_TAG, output);
   19554         }
   19555 
   19556         output = debugIndent(depth);
   19557         output += "mMeasureWidth=" + mMeasuredWidth +
   19558                 " mMeasureHeight=" + mMeasuredHeight;
   19559         Log.d(VIEW_LOG_TAG, output);
   19560 
   19561         output = debugIndent(depth);
   19562         if (mLayoutParams == null) {
   19563             output += "BAD! no layout params";
   19564         } else {
   19565             output = mLayoutParams.debug(output);
   19566         }
   19567         Log.d(VIEW_LOG_TAG, output);
   19568 
   19569         output = debugIndent(depth);
   19570         output += "flags={";
   19571         output += View.printFlags(mViewFlags);
   19572         output += "}";
   19573         Log.d(VIEW_LOG_TAG, output);
   19574 
   19575         output = debugIndent(depth);
   19576         output += "privateFlags={";
   19577         output += View.printPrivateFlags(mPrivateFlags);
   19578         output += "}";
   19579         Log.d(VIEW_LOG_TAG, output);
   19580     }
   19581 
   19582     /**
   19583      * Creates a string of whitespaces used for indentation.
   19584      *
   19585      * @param depth the indentation level
   19586      * @return a String containing (depth * 2 + 3) * 2 white spaces
   19587      *
   19588      * @hide
   19589      */
   19590     protected static String debugIndent(int depth) {
   19591         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
   19592         for (int i = 0; i < (depth * 2) + 3; i++) {
   19593             spaces.append(' ').append(' ');
   19594         }
   19595         return spaces.toString();
   19596     }
   19597 
   19598     /**
   19599      * <p>Return the offset of the widget's text baseline from the widget's top
   19600      * boundary. If this widget does not support baseline alignment, this
   19601      * method returns -1. </p>
   19602      *
   19603      * @return the offset of the baseline within the widget's bounds or -1
   19604      *         if baseline alignment is not supported
   19605      */
   19606     @ViewDebug.ExportedProperty(category = "layout")
   19607     public int getBaseline() {
   19608         return -1;
   19609     }
   19610 
   19611     /**
   19612      * Returns whether the view hierarchy is currently undergoing a layout pass. This
   19613      * information is useful to avoid situations such as calling {@link #requestLayout()} during
   19614      * a layout pass.
   19615      *
   19616      * @return whether the view hierarchy is currently undergoing a layout pass
   19617      */
   19618     public boolean isInLayout() {
   19619         ViewRootImpl viewRoot = getViewRootImpl();
   19620         return (viewRoot != null && viewRoot.isInLayout());
   19621     }
   19622 
   19623     /**
   19624      * Call this when something has changed which has invalidated the
   19625      * layout of this view. This will schedule a layout pass of the view
   19626      * tree. This should not be called while the view hierarchy is currently in a layout
   19627      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
   19628      * end of the current layout pass (and then layout will run again) or after the current
   19629      * frame is drawn and the next layout occurs.
   19630      *
   19631      * <p>Subclasses which override this method should call the superclass method to
   19632      * handle possible request-during-layout errors correctly.</p>
   19633      */
   19634     @CallSuper
   19635     public void requestLayout() {
   19636         if (mMeasureCache != null) mMeasureCache.clear();
   19637 
   19638         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
   19639             // Only trigger request-during-layout logic if this is the view requesting it,
   19640             // not the views in its parent hierarchy
   19641             ViewRootImpl viewRoot = getViewRootImpl();
   19642             if (viewRoot != null && viewRoot.isInLayout()) {
   19643                 if (!viewRoot.requestLayoutDuringLayout(this)) {
   19644                     return;
   19645                 }
   19646             }
   19647             mAttachInfo.mViewRequestingLayout = this;
   19648         }
   19649 
   19650         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   19651         mPrivateFlags |= PFLAG_INVALIDATED;
   19652 
   19653         if (mParent != null && !mParent.isLayoutRequested()) {
   19654             mParent.requestLayout();
   19655         }
   19656         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
   19657             mAttachInfo.mViewRequestingLayout = null;
   19658         }
   19659     }
   19660 
   19661     /**
   19662      * Forces this view to be laid out during the next layout pass.
   19663      * This method does not call requestLayout() or forceLayout()
   19664      * on the parent.
   19665      */
   19666     public void forceLayout() {
   19667         if (mMeasureCache != null) mMeasureCache.clear();
   19668 
   19669         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   19670         mPrivateFlags |= PFLAG_INVALIDATED;
   19671     }
   19672 
   19673     /**
   19674      * <p>
   19675      * This is called to find out how big a view should be. The parent
   19676      * supplies constraint information in the width and height parameters.
   19677      * </p>
   19678      *
   19679      * <p>
   19680      * The actual measurement work of a view is performed in
   19681      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
   19682      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
   19683      * </p>
   19684      *
   19685      *
   19686      * @param widthMeasureSpec Horizontal space requirements as imposed by the
   19687      *        parent
   19688      * @param heightMeasureSpec Vertical space requirements as imposed by the
   19689      *        parent
   19690      *
   19691      * @see #onMeasure(int, int)
   19692      */
   19693     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
   19694         boolean optical = isLayoutModeOptical(this);
   19695         if (optical != isLayoutModeOptical(mParent)) {
   19696             Insets insets = getOpticalInsets();
   19697             int oWidth  = insets.left + insets.right;
   19698             int oHeight = insets.top  + insets.bottom;
   19699             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
   19700             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
   19701         }
   19702 
   19703         // Suppress sign extension for the low bytes
   19704         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
   19705         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
   19706 
   19707         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   19708 
   19709         // Optimize layout by avoiding an extra EXACTLY pass when the view is
   19710         // already measured as the correct size. In API 23 and below, this
   19711         // extra pass is required to make LinearLayout re-distribute weight.
   19712         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
   19713                 || heightMeasureSpec != mOldHeightMeasureSpec;
   19714         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
   19715                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
   19716         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
   19717                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
   19718         final boolean needsLayout = specChanged
   19719                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
   19720 
   19721         if (forceLayout || needsLayout) {
   19722             // first clears the measured dimension flag
   19723             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
   19724 
   19725             resolveRtlPropertiesIfNeeded();
   19726 
   19727             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
   19728             if (cacheIndex < 0 || sIgnoreMeasureCache) {
   19729                 // measure ourselves, this should set the measured dimension flag back
   19730                 onMeasure(widthMeasureSpec, heightMeasureSpec);
   19731                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   19732             } else {
   19733                 long value = mMeasureCache.valueAt(cacheIndex);
   19734                 // Casting a long to int drops the high 32 bits, no mask needed
   19735                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
   19736                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   19737             }
   19738 
   19739             // flag not set, setMeasuredDimension() was not invoked, we raise
   19740             // an exception to warn the developer
   19741             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
   19742                 throw new IllegalStateException("View with id " + getId() + ": "
   19743                         + getClass().getName() + "#onMeasure() did not set the"
   19744                         + " measured dimension by calling"
   19745                         + " setMeasuredDimension()");
   19746             }
   19747 
   19748             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
   19749         }
   19750 
   19751         mOldWidthMeasureSpec = widthMeasureSpec;
   19752         mOldHeightMeasureSpec = heightMeasureSpec;
   19753 
   19754         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
   19755                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
   19756     }
   19757 
   19758     /**
   19759      * <p>
   19760      * Measure the view and its content to determine the measured width and the
   19761      * measured height. This method is invoked by {@link #measure(int, int)} and
   19762      * should be overridden by subclasses to provide accurate and efficient
   19763      * measurement of their contents.
   19764      * </p>
   19765      *
   19766      * <p>
   19767      * <strong>CONTRACT:</strong> When overriding this method, you
   19768      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
   19769      * measured width and height of this view. Failure to do so will trigger an
   19770      * <code>IllegalStateException</code>, thrown by
   19771      * {@link #measure(int, int)}. Calling the superclass'
   19772      * {@link #onMeasure(int, int)} is a valid use.
   19773      * </p>
   19774      *
   19775      * <p>
   19776      * The base class implementation of measure defaults to the background size,
   19777      * unless a larger size is allowed by the MeasureSpec. Subclasses should
   19778      * override {@link #onMeasure(int, int)} to provide better measurements of
   19779      * their content.
   19780      * </p>
   19781      *
   19782      * <p>
   19783      * If this method is overridden, it is the subclass's responsibility to make
   19784      * sure the measured height and width are at least the view's minimum height
   19785      * and width ({@link #getSuggestedMinimumHeight()} and
   19786      * {@link #getSuggestedMinimumWidth()}).
   19787      * </p>
   19788      *
   19789      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
   19790      *                         The requirements are encoded with
   19791      *                         {@link android.view.View.MeasureSpec}.
   19792      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
   19793      *                         The requirements are encoded with
   19794      *                         {@link android.view.View.MeasureSpec}.
   19795      *
   19796      * @see #getMeasuredWidth()
   19797      * @see #getMeasuredHeight()
   19798      * @see #setMeasuredDimension(int, int)
   19799      * @see #getSuggestedMinimumHeight()
   19800      * @see #getSuggestedMinimumWidth()
   19801      * @see android.view.View.MeasureSpec#getMode(int)
   19802      * @see android.view.View.MeasureSpec#getSize(int)
   19803      */
   19804     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   19805         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
   19806                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
   19807     }
   19808 
   19809     /**
   19810      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
   19811      * measured width and measured height. Failing to do so will trigger an
   19812      * exception at measurement time.</p>
   19813      *
   19814      * @param measuredWidth The measured width of this view.  May be a complex
   19815      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   19816      * {@link #MEASURED_STATE_TOO_SMALL}.
   19817      * @param measuredHeight The measured height of this view.  May be a complex
   19818      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   19819      * {@link #MEASURED_STATE_TOO_SMALL}.
   19820      */
   19821     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
   19822         boolean optical = isLayoutModeOptical(this);
   19823         if (optical != isLayoutModeOptical(mParent)) {
   19824             Insets insets = getOpticalInsets();
   19825             int opticalWidth  = insets.left + insets.right;
   19826             int opticalHeight = insets.top  + insets.bottom;
   19827 
   19828             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
   19829             measuredHeight += optical ? opticalHeight : -opticalHeight;
   19830         }
   19831         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
   19832     }
   19833 
   19834     /**
   19835      * Sets the measured dimension without extra processing for things like optical bounds.
   19836      * Useful for reapplying consistent values that have already been cooked with adjustments
   19837      * for optical bounds, etc. such as those from the measurement cache.
   19838      *
   19839      * @param measuredWidth The measured width of this view.  May be a complex
   19840      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   19841      * {@link #MEASURED_STATE_TOO_SMALL}.
   19842      * @param measuredHeight The measured height of this view.  May be a complex
   19843      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   19844      * {@link #MEASURED_STATE_TOO_SMALL}.
   19845      */
   19846     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
   19847         mMeasuredWidth = measuredWidth;
   19848         mMeasuredHeight = measuredHeight;
   19849 
   19850         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
   19851     }
   19852 
   19853     /**
   19854      * Merge two states as returned by {@link #getMeasuredState()}.
   19855      * @param curState The current state as returned from a view or the result
   19856      * of combining multiple views.
   19857      * @param newState The new view state to combine.
   19858      * @return Returns a new integer reflecting the combination of the two
   19859      * states.
   19860      */
   19861     public static int combineMeasuredStates(int curState, int newState) {
   19862         return curState | newState;
   19863     }
   19864 
   19865     /**
   19866      * Version of {@link #resolveSizeAndState(int, int, int)}
   19867      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
   19868      */
   19869     public static int resolveSize(int size, int measureSpec) {
   19870         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
   19871     }
   19872 
   19873     /**
   19874      * Utility to reconcile a desired size and state, with constraints imposed
   19875      * by a MeasureSpec. Will take the desired size, unless a different size
   19876      * is imposed by the constraints. The returned value is a compound integer,
   19877      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
   19878      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
   19879      * resulting size is smaller than the size the view wants to be.
   19880      *
   19881      * @param size How big the view wants to be.
   19882      * @param measureSpec Constraints imposed by the parent.
   19883      * @param childMeasuredState Size information bit mask for the view's
   19884      *                           children.
   19885      * @return Size information bit mask as defined by
   19886      *         {@link #MEASURED_SIZE_MASK} and
   19887      *         {@link #MEASURED_STATE_TOO_SMALL}.
   19888      */
   19889     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
   19890         final int specMode = MeasureSpec.getMode(measureSpec);
   19891         final int specSize = MeasureSpec.getSize(measureSpec);
   19892         final int result;
   19893         switch (specMode) {
   19894             case MeasureSpec.AT_MOST:
   19895                 if (specSize < size) {
   19896                     result = specSize | MEASURED_STATE_TOO_SMALL;
   19897                 } else {
   19898                     result = size;
   19899                 }
   19900                 break;
   19901             case MeasureSpec.EXACTLY:
   19902                 result = specSize;
   19903                 break;
   19904             case MeasureSpec.UNSPECIFIED:
   19905             default:
   19906                 result = size;
   19907         }
   19908         return result | (childMeasuredState & MEASURED_STATE_MASK);
   19909     }
   19910 
   19911     /**
   19912      * Utility to return a default size. Uses the supplied size if the
   19913      * MeasureSpec imposed no constraints. Will get larger if allowed
   19914      * by the MeasureSpec.
   19915      *
   19916      * @param size Default size for this view
   19917      * @param measureSpec Constraints imposed by the parent
   19918      * @return The size this view should be.
   19919      */
   19920     public static int getDefaultSize(int size, int measureSpec) {
   19921         int result = size;
   19922         int specMode = MeasureSpec.getMode(measureSpec);
   19923         int specSize = MeasureSpec.getSize(measureSpec);
   19924 
   19925         switch (specMode) {
   19926         case MeasureSpec.UNSPECIFIED:
   19927             result = size;
   19928             break;
   19929         case MeasureSpec.AT_MOST:
   19930         case MeasureSpec.EXACTLY:
   19931             result = specSize;
   19932             break;
   19933         }
   19934         return result;
   19935     }
   19936 
   19937     /**
   19938      * Returns the suggested minimum height that the view should use. This
   19939      * returns the maximum of the view's minimum height
   19940      * and the background's minimum height
   19941      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
   19942      * <p>
   19943      * When being used in {@link #onMeasure(int, int)}, the caller should still
   19944      * ensure the returned height is within the requirements of the parent.
   19945      *
   19946      * @return The suggested minimum height of the view.
   19947      */
   19948     protected int getSuggestedMinimumHeight() {
   19949         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
   19950 
   19951     }
   19952 
   19953     /**
   19954      * Returns the suggested minimum width that the view should use. This
   19955      * returns the maximum of the view's minimum width
   19956      * and the background's minimum width
   19957      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
   19958      * <p>
   19959      * When being used in {@link #onMeasure(int, int)}, the caller should still
   19960      * ensure the returned width is within the requirements of the parent.
   19961      *
   19962      * @return The suggested minimum width of the view.
   19963      */
   19964     protected int getSuggestedMinimumWidth() {
   19965         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
   19966     }
   19967 
   19968     /**
   19969      * Returns the minimum height of the view.
   19970      *
   19971      * @return the minimum height the view will try to be.
   19972      *
   19973      * @see #setMinimumHeight(int)
   19974      *
   19975      * @attr ref android.R.styleable#View_minHeight
   19976      */
   19977     public int getMinimumHeight() {
   19978         return mMinHeight;
   19979     }
   19980 
   19981     /**
   19982      * Sets the minimum height of the view. It is not guaranteed the view will
   19983      * be able to achieve this minimum height (for example, if its parent layout
   19984      * constrains it with less available height).
   19985      *
   19986      * @param minHeight The minimum height the view will try to be.
   19987      *
   19988      * @see #getMinimumHeight()
   19989      *
   19990      * @attr ref android.R.styleable#View_minHeight
   19991      */
   19992     @RemotableViewMethod
   19993     public void setMinimumHeight(int minHeight) {
   19994         mMinHeight = minHeight;
   19995         requestLayout();
   19996     }
   19997 
   19998     /**
   19999      * Returns the minimum width of the view.
   20000      *
   20001      * @return the minimum width the view will try to be.
   20002      *
   20003      * @see #setMinimumWidth(int)
   20004      *
   20005      * @attr ref android.R.styleable#View_minWidth
   20006      */
   20007     public int getMinimumWidth() {
   20008         return mMinWidth;
   20009     }
   20010 
   20011     /**
   20012      * Sets the minimum width of the view. It is not guaranteed the view will
   20013      * be able to achieve this minimum width (for example, if its parent layout
   20014      * constrains it with less available width).
   20015      *
   20016      * @param minWidth The minimum width the view will try to be.
   20017      *
   20018      * @see #getMinimumWidth()
   20019      *
   20020      * @attr ref android.R.styleable#View_minWidth
   20021      */
   20022     public void setMinimumWidth(int minWidth) {
   20023         mMinWidth = minWidth;
   20024         requestLayout();
   20025 
   20026     }
   20027 
   20028     /**
   20029      * Get the animation currently associated with this view.
   20030      *
   20031      * @return The animation that is currently playing or
   20032      *         scheduled to play for this view.
   20033      */
   20034     public Animation getAnimation() {
   20035         return mCurrentAnimation;
   20036     }
   20037 
   20038     /**
   20039      * Start the specified animation now.
   20040      *
   20041      * @param animation the animation to start now
   20042      */
   20043     public void startAnimation(Animation animation) {
   20044         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
   20045         setAnimation(animation);
   20046         invalidateParentCaches();
   20047         invalidate(true);
   20048     }
   20049 
   20050     /**
   20051      * Cancels any animations for this view.
   20052      */
   20053     public void clearAnimation() {
   20054         if (mCurrentAnimation != null) {
   20055             mCurrentAnimation.detach();
   20056         }
   20057         mCurrentAnimation = null;
   20058         invalidateParentIfNeeded();
   20059     }
   20060 
   20061     /**
   20062      * Sets the next animation to play for this view.
   20063      * If you want the animation to play immediately, use
   20064      * {@link #startAnimation(android.view.animation.Animation)} instead.
   20065      * This method provides allows fine-grained
   20066      * control over the start time and invalidation, but you
   20067      * must make sure that 1) the animation has a start time set, and
   20068      * 2) the view's parent (which controls animations on its children)
   20069      * will be invalidated when the animation is supposed to
   20070      * start.
   20071      *
   20072      * @param animation The next animation, or null.
   20073      */
   20074     public void setAnimation(Animation animation) {
   20075         mCurrentAnimation = animation;
   20076 
   20077         if (animation != null) {
   20078             // If the screen is off assume the animation start time is now instead of
   20079             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
   20080             // would cause the animation to start when the screen turns back on
   20081             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
   20082                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
   20083                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
   20084             }
   20085             animation.reset();
   20086         }
   20087     }
   20088 
   20089     /**
   20090      * Invoked by a parent ViewGroup to notify the start of the animation
   20091      * currently associated with this view. If you override this method,
   20092      * always call super.onAnimationStart();
   20093      *
   20094      * @see #setAnimation(android.view.animation.Animation)
   20095      * @see #getAnimation()
   20096      */
   20097     @CallSuper
   20098     protected void onAnimationStart() {
   20099         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
   20100     }
   20101 
   20102     /**
   20103      * Invoked by a parent ViewGroup to notify the end of the animation
   20104      * currently associated with this view. If you override this method,
   20105      * always call super.onAnimationEnd();
   20106      *
   20107      * @see #setAnimation(android.view.animation.Animation)
   20108      * @see #getAnimation()
   20109      */
   20110     @CallSuper
   20111     protected void onAnimationEnd() {
   20112         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
   20113     }
   20114 
   20115     /**
   20116      * Invoked if there is a Transform that involves alpha. Subclass that can
   20117      * draw themselves with the specified alpha should return true, and then
   20118      * respect that alpha when their onDraw() is called. If this returns false
   20119      * then the view may be redirected to draw into an offscreen buffer to
   20120      * fulfill the request, which will look fine, but may be slower than if the
   20121      * subclass handles it internally. The default implementation returns false.
   20122      *
   20123      * @param alpha The alpha (0..255) to apply to the view's drawing
   20124      * @return true if the view can draw with the specified alpha.
   20125      */
   20126     protected boolean onSetAlpha(int alpha) {
   20127         return false;
   20128     }
   20129 
   20130     /**
   20131      * This is used by the RootView to perform an optimization when
   20132      * the view hierarchy contains one or several SurfaceView.
   20133      * SurfaceView is always considered transparent, but its children are not,
   20134      * therefore all View objects remove themselves from the global transparent
   20135      * region (passed as a parameter to this function).
   20136      *
   20137      * @param region The transparent region for this ViewAncestor (window).
   20138      *
   20139      * @return Returns true if the effective visibility of the view at this
   20140      * point is opaque, regardless of the transparent region; returns false
   20141      * if it is possible for underlying windows to be seen behind the view.
   20142      *
   20143      * {@hide}
   20144      */
   20145     public boolean gatherTransparentRegion(Region region) {
   20146         final AttachInfo attachInfo = mAttachInfo;
   20147         if (region != null && attachInfo != null) {
   20148             final int pflags = mPrivateFlags;
   20149             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
   20150                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
   20151                 // remove it from the transparent region.
   20152                 final int[] location = attachInfo.mTransparentLocation;
   20153                 getLocationInWindow(location);
   20154                 region.op(location[0], location[1], location[0] + mRight - mLeft,
   20155                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
   20156             } else {
   20157                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
   20158                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
   20159                     // the background drawable's non-transparent parts from this transparent region.
   20160                     applyDrawableToTransparentRegion(mBackground, region);
   20161                 }
   20162                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   20163                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
   20164                     // Similarly, we remove the foreground drawable's non-transparent parts.
   20165                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
   20166                 }
   20167             }
   20168         }
   20169         return true;
   20170     }
   20171 
   20172     /**
   20173      * Play a sound effect for this view.
   20174      *
   20175      * <p>The framework will play sound effects for some built in actions, such as
   20176      * clicking, but you may wish to play these effects in your widget,
   20177      * for instance, for internal navigation.
   20178      *
   20179      * <p>The sound effect will only be played if sound effects are enabled by the user, and
   20180      * {@link #isSoundEffectsEnabled()} is true.
   20181      *
   20182      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
   20183      */
   20184     public void playSoundEffect(int soundConstant) {
   20185         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
   20186             return;
   20187         }
   20188         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
   20189     }
   20190 
   20191     /**
   20192      * BZZZTT!!1!
   20193      *
   20194      * <p>Provide haptic feedback to the user for this view.
   20195      *
   20196      * <p>The framework will provide haptic feedback for some built in actions,
   20197      * such as long presses, but you may wish to provide feedback for your
   20198      * own widget.
   20199      *
   20200      * <p>The feedback will only be performed if
   20201      * {@link #isHapticFeedbackEnabled()} is true.
   20202      *
   20203      * @param feedbackConstant One of the constants defined in
   20204      * {@link HapticFeedbackConstants}
   20205      */
   20206     public boolean performHapticFeedback(int feedbackConstant) {
   20207         return performHapticFeedback(feedbackConstant, 0);
   20208     }
   20209 
   20210     /**
   20211      * BZZZTT!!1!
   20212      *
   20213      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
   20214      *
   20215      * @param feedbackConstant One of the constants defined in
   20216      * {@link HapticFeedbackConstants}
   20217      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
   20218      */
   20219     public boolean performHapticFeedback(int feedbackConstant, int flags) {
   20220         if (mAttachInfo == null) {
   20221             return false;
   20222         }
   20223         //noinspection SimplifiableIfStatement
   20224         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
   20225                 && !isHapticFeedbackEnabled()) {
   20226             return false;
   20227         }
   20228         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
   20229                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
   20230     }
   20231 
   20232     /**
   20233      * Request that the visibility of the status bar or other screen/window
   20234      * decorations be changed.
   20235      *
   20236      * <p>This method is used to put the over device UI into temporary modes
   20237      * where the user's attention is focused more on the application content,
   20238      * by dimming or hiding surrounding system affordances.  This is typically
   20239      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   20240      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
   20241      * to be placed behind the action bar (and with these flags other system
   20242      * affordances) so that smooth transitions between hiding and showing them
   20243      * can be done.
   20244      *
   20245      * <p>Two representative examples of the use of system UI visibility is
   20246      * implementing a content browsing application (like a magazine reader)
   20247      * and a video playing application.
   20248      *
   20249      * <p>The first code shows a typical implementation of a View in a content
   20250      * browsing application.  In this implementation, the application goes
   20251      * into a content-oriented mode by hiding the status bar and action bar,
   20252      * and putting the navigation elements into lights out mode.  The user can
   20253      * then interact with content while in this mode.  Such an application should
   20254      * provide an easy way for the user to toggle out of the mode (such as to
   20255      * check information in the status bar or access notifications).  In the
   20256      * implementation here, this is done simply by tapping on the content.
   20257      *
   20258      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
   20259      *      content}
   20260      *
   20261      * <p>This second code sample shows a typical implementation of a View
   20262      * in a video playing application.  In this situation, while the video is
   20263      * playing the application would like to go into a complete full-screen mode,
   20264      * to use as much of the display as possible for the video.  When in this state
   20265      * the user can not interact with the application; the system intercepts
   20266      * touching on the screen to pop the UI out of full screen mode.  See
   20267      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
   20268      *
   20269      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
   20270      *      content}
   20271      *
   20272      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   20273      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   20274      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   20275      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   20276      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   20277      */
   20278     public void setSystemUiVisibility(int visibility) {
   20279         if (visibility != mSystemUiVisibility) {
   20280             mSystemUiVisibility = visibility;
   20281             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   20282                 mParent.recomputeViewAttributes(this);
   20283             }
   20284         }
   20285     }
   20286 
   20287     /**
   20288      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
   20289      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   20290      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   20291      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   20292      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   20293      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   20294      */
   20295     public int getSystemUiVisibility() {
   20296         return mSystemUiVisibility;
   20297     }
   20298 
   20299     /**
   20300      * Returns the current system UI visibility that is currently set for
   20301      * the entire window.  This is the combination of the
   20302      * {@link #setSystemUiVisibility(int)} values supplied by all of the
   20303      * views in the window.
   20304      */
   20305     public int getWindowSystemUiVisibility() {
   20306         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
   20307     }
   20308 
   20309     /**
   20310      * Override to find out when the window's requested system UI visibility
   20311      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
   20312      * This is different from the callbacks received through
   20313      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
   20314      * in that this is only telling you about the local request of the window,
   20315      * not the actual values applied by the system.
   20316      */
   20317     public void onWindowSystemUiVisibilityChanged(int visible) {
   20318     }
   20319 
   20320     /**
   20321      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
   20322      * the view hierarchy.
   20323      */
   20324     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
   20325         onWindowSystemUiVisibilityChanged(visible);
   20326     }
   20327 
   20328     /**
   20329      * Set a listener to receive callbacks when the visibility of the system bar changes.
   20330      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
   20331      */
   20332     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
   20333         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
   20334         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   20335             mParent.recomputeViewAttributes(this);
   20336         }
   20337     }
   20338 
   20339     /**
   20340      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
   20341      * the view hierarchy.
   20342      */
   20343     public void dispatchSystemUiVisibilityChanged(int visibility) {
   20344         ListenerInfo li = mListenerInfo;
   20345         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   20346             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
   20347                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
   20348         }
   20349     }
   20350 
   20351     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
   20352         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
   20353         if (val != mSystemUiVisibility) {
   20354             setSystemUiVisibility(val);
   20355             return true;
   20356         }
   20357         return false;
   20358     }
   20359 
   20360     /** @hide */
   20361     public void setDisabledSystemUiVisibility(int flags) {
   20362         if (mAttachInfo != null) {
   20363             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
   20364                 mAttachInfo.mDisabledSystemUiVisibility = flags;
   20365                 if (mParent != null) {
   20366                     mParent.recomputeViewAttributes(this);
   20367                 }
   20368             }
   20369         }
   20370     }
   20371 
   20372     /**
   20373      * Creates an image that the system displays during the drag and drop
   20374      * operation. This is called a &quot;drag shadow&quot;. The default implementation
   20375      * for a DragShadowBuilder based on a View returns an image that has exactly the same
   20376      * appearance as the given View. The default also positions the center of the drag shadow
   20377      * directly under the touch point. If no View is provided (the constructor with no parameters
   20378      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
   20379      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
   20380      * default is an invisible drag shadow.
   20381      * <p>
   20382      * You are not required to use the View you provide to the constructor as the basis of the
   20383      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
   20384      * anything you want as the drag shadow.
   20385      * </p>
   20386      * <p>
   20387      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
   20388      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
   20389      *  size and position of the drag shadow. It uses this data to construct a
   20390      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
   20391      *  so that your application can draw the shadow image in the Canvas.
   20392      * </p>
   20393      *
   20394      * <div class="special reference">
   20395      * <h3>Developer Guides</h3>
   20396      * <p>For a guide to implementing drag and drop features, read the
   20397      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   20398      * </div>
   20399      */
   20400     public static class DragShadowBuilder {
   20401         private final WeakReference<View> mView;
   20402 
   20403         /**
   20404          * Constructs a shadow image builder based on a View. By default, the resulting drag
   20405          * shadow will have the same appearance and dimensions as the View, with the touch point
   20406          * over the center of the View.
   20407          * @param view A View. Any View in scope can be used.
   20408          */
   20409         public DragShadowBuilder(View view) {
   20410             mView = new WeakReference<View>(view);
   20411         }
   20412 
   20413         /**
   20414          * Construct a shadow builder object with no associated View.  This
   20415          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
   20416          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
   20417          * to supply the drag shadow's dimensions and appearance without
   20418          * reference to any View object. If they are not overridden, then the result is an
   20419          * invisible drag shadow.
   20420          */
   20421         public DragShadowBuilder() {
   20422             mView = new WeakReference<View>(null);
   20423         }
   20424 
   20425         /**
   20426          * Returns the View object that had been passed to the
   20427          * {@link #View.DragShadowBuilder(View)}
   20428          * constructor.  If that View parameter was {@code null} or if the
   20429          * {@link #View.DragShadowBuilder()}
   20430          * constructor was used to instantiate the builder object, this method will return
   20431          * null.
   20432          *
   20433          * @return The View object associate with this builder object.
   20434          */
   20435         @SuppressWarnings({"JavadocReference"})
   20436         final public View getView() {
   20437             return mView.get();
   20438         }
   20439 
   20440         /**
   20441          * Provides the metrics for the shadow image. These include the dimensions of
   20442          * the shadow image, and the point within that shadow that should
   20443          * be centered under the touch location while dragging.
   20444          * <p>
   20445          * The default implementation sets the dimensions of the shadow to be the
   20446          * same as the dimensions of the View itself and centers the shadow under
   20447          * the touch point.
   20448          * </p>
   20449          *
   20450          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
   20451          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
   20452          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
   20453          * image.
   20454          *
   20455          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
   20456          * shadow image that should be underneath the touch point during the drag and drop
   20457          * operation. Your application must set {@link android.graphics.Point#x} to the
   20458          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
   20459          */
   20460         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
   20461             final View view = mView.get();
   20462             if (view != null) {
   20463                 outShadowSize.set(view.getWidth(), view.getHeight());
   20464                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
   20465             } else {
   20466                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
   20467             }
   20468         }
   20469 
   20470         /**
   20471          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
   20472          * based on the dimensions it received from the
   20473          * {@link #onProvideShadowMetrics(Point, Point)} callback.
   20474          *
   20475          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
   20476          */
   20477         public void onDrawShadow(Canvas canvas) {
   20478             final View view = mView.get();
   20479             if (view != null) {
   20480                 view.draw(canvas);
   20481             } else {
   20482                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
   20483             }
   20484         }
   20485     }
   20486 
   20487     /**
   20488      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
   20489      * startDragAndDrop()} for newer platform versions.
   20490      */
   20491     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
   20492                                    Object myLocalState, int flags) {
   20493         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
   20494     }
   20495 
   20496     /**
   20497      * Starts a drag and drop operation. When your application calls this method, it passes a
   20498      * {@link android.view.View.DragShadowBuilder} object to the system. The
   20499      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
   20500      * to get metrics for the drag shadow, and then calls the object's
   20501      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
   20502      * <p>
   20503      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
   20504      *  drag events to all the View objects in your application that are currently visible. It does
   20505      *  this either by calling the View object's drag listener (an implementation of
   20506      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
   20507      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
   20508      *  Both are passed a {@link android.view.DragEvent} object that has a
   20509      *  {@link android.view.DragEvent#getAction()} value of
   20510      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
   20511      * </p>
   20512      * <p>
   20513      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
   20514      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
   20515      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
   20516      * to the View the user selected for dragging.
   20517      * </p>
   20518      * @param data A {@link android.content.ClipData} object pointing to the data to be
   20519      * transferred by the drag and drop operation.
   20520      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   20521      * drag shadow.
   20522      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
   20523      * drop operation. This Object is put into every DragEvent object sent by the system during the
   20524      * current drag.
   20525      * <p>
   20526      * myLocalState is a lightweight mechanism for the sending information from the dragged View
   20527      * to the target Views. For example, it can contain flags that differentiate between a
   20528      * a copy operation and a move operation.
   20529      * </p>
   20530      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
   20531      * flags, or any combination of the following:
   20532      *     <ul>
   20533      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
   20534      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
   20535      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
   20536      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
   20537      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
   20538      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
   20539      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
   20540      *     </ul>
   20541      * @return {@code true} if the method completes successfully, or
   20542      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
   20543      * do a drag, and so no drag operation is in progress.
   20544      */
   20545     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
   20546             Object myLocalState, int flags) {
   20547         if (ViewDebug.DEBUG_DRAG) {
   20548             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
   20549         }
   20550         if (mAttachInfo == null) {
   20551             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
   20552             return false;
   20553         }
   20554         boolean okay = false;
   20555 
   20556         Point shadowSize = new Point();
   20557         Point shadowTouchPoint = new Point();
   20558         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
   20559 
   20560         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
   20561                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
   20562             throw new IllegalStateException("Drag shadow dimensions must not be negative");
   20563         }
   20564 
   20565         if (ViewDebug.DEBUG_DRAG) {
   20566             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
   20567                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
   20568         }
   20569         if (mAttachInfo.mDragSurface != null) {
   20570             mAttachInfo.mDragSurface.release();
   20571         }
   20572         mAttachInfo.mDragSurface = new Surface();
   20573         try {
   20574             mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
   20575                     flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
   20576             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
   20577                     + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
   20578             if (mAttachInfo.mDragToken != null) {
   20579                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
   20580                 try {
   20581                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   20582                     shadowBuilder.onDrawShadow(canvas);
   20583                 } finally {
   20584                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
   20585                 }
   20586 
   20587                 final ViewRootImpl root = getViewRootImpl();
   20588 
   20589                 // Cache the local state object for delivery with DragEvents
   20590                 root.setLocalDragState(myLocalState);
   20591 
   20592                 // repurpose 'shadowSize' for the last touch point
   20593                 root.getLastTouchPoint(shadowSize);
   20594 
   20595                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
   20596                         root.getLastTouchSource(), shadowSize.x, shadowSize.y,
   20597                         shadowTouchPoint.x, shadowTouchPoint.y, data);
   20598                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
   20599             }
   20600         } catch (Exception e) {
   20601             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
   20602             mAttachInfo.mDragSurface.destroy();
   20603             mAttachInfo.mDragSurface = null;
   20604         }
   20605 
   20606         return okay;
   20607     }
   20608 
   20609     /**
   20610      * Cancels an ongoing drag and drop operation.
   20611      * <p>
   20612      * A {@link android.view.DragEvent} object with
   20613      * {@link android.view.DragEvent#getAction()} value of
   20614      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
   20615      * {@link android.view.DragEvent#getResult()} value of {@code false}
   20616      * will be sent to every
   20617      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
   20618      * even if they are not currently visible.
   20619      * </p>
   20620      * <p>
   20621      * This method can be called on any View in the same window as the View on which
   20622      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
   20623      * was called.
   20624      * </p>
   20625      */
   20626     public final void cancelDragAndDrop() {
   20627         if (ViewDebug.DEBUG_DRAG) {
   20628             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
   20629         }
   20630         if (mAttachInfo == null) {
   20631             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
   20632             return;
   20633         }
   20634         if (mAttachInfo.mDragToken != null) {
   20635             try {
   20636                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
   20637             } catch (Exception e) {
   20638                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
   20639             }
   20640             mAttachInfo.mDragToken = null;
   20641         } else {
   20642             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
   20643         }
   20644     }
   20645 
   20646     /**
   20647      * Updates the drag shadow for the ongoing drag and drop operation.
   20648      *
   20649      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   20650      * new drag shadow.
   20651      */
   20652     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
   20653         if (ViewDebug.DEBUG_DRAG) {
   20654             Log.d(VIEW_LOG_TAG, "updateDragShadow");
   20655         }
   20656         if (mAttachInfo == null) {
   20657             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
   20658             return;
   20659         }
   20660         if (mAttachInfo.mDragToken != null) {
   20661             try {
   20662                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
   20663                 try {
   20664                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   20665                     shadowBuilder.onDrawShadow(canvas);
   20666                 } finally {
   20667                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
   20668                 }
   20669             } catch (Exception e) {
   20670                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
   20671             }
   20672         } else {
   20673             Log.e(VIEW_LOG_TAG, "No active drag");
   20674         }
   20675     }
   20676 
   20677     /**
   20678      * Starts a move from {startX, startY}, the amount of the movement will be the offset
   20679      * between {startX, startY} and the new cursor positon.
   20680      * @param startX horizontal coordinate where the move started.
   20681      * @param startY vertical coordinate where the move started.
   20682      * @return whether moving was started successfully.
   20683      * @hide
   20684      */
   20685     public final boolean startMovingTask(float startX, float startY) {
   20686         if (ViewDebug.DEBUG_POSITIONING) {
   20687             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
   20688         }
   20689         try {
   20690             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
   20691         } catch (RemoteException e) {
   20692             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
   20693         }
   20694         return false;
   20695     }
   20696 
   20697     /**
   20698      * Handles drag events sent by the system following a call to
   20699      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
   20700      * startDragAndDrop()}.
   20701      *<p>
   20702      * When the system calls this method, it passes a
   20703      * {@link android.view.DragEvent} object. A call to
   20704      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
   20705      * in DragEvent. The method uses these to determine what is happening in the drag and drop
   20706      * operation.
   20707      * @param event The {@link android.view.DragEvent} sent by the system.
   20708      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
   20709      * in DragEvent, indicating the type of drag event represented by this object.
   20710      * @return {@code true} if the method was successful, otherwise {@code false}.
   20711      * <p>
   20712      *  The method should return {@code true} in response to an action type of
   20713      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
   20714      *  operation.
   20715      * </p>
   20716      * <p>
   20717      *  The method should also return {@code true} in response to an action type of
   20718      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
   20719      *  {@code false} if it didn't.
   20720      * </p>
   20721      */
   20722     public boolean onDragEvent(DragEvent event) {
   20723         return false;
   20724     }
   20725 
   20726     /**
   20727      * Detects if this View is enabled and has a drag event listener.
   20728      * If both are true, then it calls the drag event listener with the
   20729      * {@link android.view.DragEvent} it received. If the drag event listener returns
   20730      * {@code true}, then dispatchDragEvent() returns {@code true}.
   20731      * <p>
   20732      * For all other cases, the method calls the
   20733      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
   20734      * method and returns its result.
   20735      * </p>
   20736      * <p>
   20737      * This ensures that a drag event is always consumed, even if the View does not have a drag
   20738      * event listener. However, if the View has a listener and the listener returns true, then
   20739      * onDragEvent() is not called.
   20740      * </p>
   20741      */
   20742     public boolean dispatchDragEvent(DragEvent event) {
   20743         ListenerInfo li = mListenerInfo;
   20744         //noinspection SimplifiableIfStatement
   20745         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   20746                 && li.mOnDragListener.onDrag(this, event)) {
   20747             return true;
   20748         }
   20749         return onDragEvent(event);
   20750     }
   20751 
   20752     boolean canAcceptDrag() {
   20753         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
   20754     }
   20755 
   20756     /**
   20757      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
   20758      * it is ever exposed at all.
   20759      * @hide
   20760      */
   20761     public void onCloseSystemDialogs(String reason) {
   20762     }
   20763 
   20764     /**
   20765      * Given a Drawable whose bounds have been set to draw into this view,
   20766      * update a Region being computed for
   20767      * {@link #gatherTransparentRegion(android.graphics.Region)} so
   20768      * that any non-transparent parts of the Drawable are removed from the
   20769      * given transparent region.
   20770      *
   20771      * @param dr The Drawable whose transparency is to be applied to the region.
   20772      * @param region A Region holding the current transparency information,
   20773      * where any parts of the region that are set are considered to be
   20774      * transparent.  On return, this region will be modified to have the
   20775      * transparency information reduced by the corresponding parts of the
   20776      * Drawable that are not transparent.
   20777      * {@hide}
   20778      */
   20779     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
   20780         if (DBG) {
   20781             Log.i("View", "Getting transparent region for: " + this);
   20782         }
   20783         final Region r = dr.getTransparentRegion();
   20784         final Rect db = dr.getBounds();
   20785         final AttachInfo attachInfo = mAttachInfo;
   20786         if (r != null && attachInfo != null) {
   20787             final int w = getRight()-getLeft();
   20788             final int h = getBottom()-getTop();
   20789             if (db.left > 0) {
   20790                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
   20791                 r.op(0, 0, db.left, h, Region.Op.UNION);
   20792             }
   20793             if (db.right < w) {
   20794                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
   20795                 r.op(db.right, 0, w, h, Region.Op.UNION);
   20796             }
   20797             if (db.top > 0) {
   20798                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
   20799                 r.op(0, 0, w, db.top, Region.Op.UNION);
   20800             }
   20801             if (db.bottom < h) {
   20802                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
   20803                 r.op(0, db.bottom, w, h, Region.Op.UNION);
   20804             }
   20805             final int[] location = attachInfo.mTransparentLocation;
   20806             getLocationInWindow(location);
   20807             r.translate(location[0], location[1]);
   20808             region.op(r, Region.Op.INTERSECT);
   20809         } else {
   20810             region.op(db, Region.Op.DIFFERENCE);
   20811         }
   20812     }
   20813 
   20814     private void checkForLongClick(int delayOffset, float x, float y) {
   20815         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
   20816             mHasPerformedLongPress = false;
   20817 
   20818             if (mPendingCheckForLongPress == null) {
   20819                 mPendingCheckForLongPress = new CheckForLongPress();
   20820             }
   20821             mPendingCheckForLongPress.setAnchor(x, y);
   20822             mPendingCheckForLongPress.rememberWindowAttachCount();
   20823             postDelayed(mPendingCheckForLongPress,
   20824                     ViewConfiguration.getLongPressTimeout() - delayOffset);
   20825         }
   20826     }
   20827 
   20828     /**
   20829      * Inflate a view from an XML resource.  This convenience method wraps the {@link
   20830      * LayoutInflater} class, which provides a full range of options for view inflation.
   20831      *
   20832      * @param context The Context object for your activity or application.
   20833      * @param resource The resource ID to inflate
   20834      * @param root A view group that will be the parent.  Used to properly inflate the
   20835      * layout_* parameters.
   20836      * @see LayoutInflater
   20837      */
   20838     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
   20839         LayoutInflater factory = LayoutInflater.from(context);
   20840         return factory.inflate(resource, root);
   20841     }
   20842 
   20843     /**
   20844      * Scroll the view with standard behavior for scrolling beyond the normal
   20845      * content boundaries. Views that call this method should override
   20846      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
   20847      * results of an over-scroll operation.
   20848      *
   20849      * Views can use this method to handle any touch or fling-based scrolling.
   20850      *
   20851      * @param deltaX Change in X in pixels
   20852      * @param deltaY Change in Y in pixels
   20853      * @param scrollX Current X scroll value in pixels before applying deltaX
   20854      * @param scrollY Current Y scroll value in pixels before applying deltaY
   20855      * @param scrollRangeX Maximum content scroll range along the X axis
   20856      * @param scrollRangeY Maximum content scroll range along the Y axis
   20857      * @param maxOverScrollX Number of pixels to overscroll by in either direction
   20858      *          along the X axis.
   20859      * @param maxOverScrollY Number of pixels to overscroll by in either direction
   20860      *          along the Y axis.
   20861      * @param isTouchEvent true if this scroll operation is the result of a touch event.
   20862      * @return true if scrolling was clamped to an over-scroll boundary along either
   20863      *          axis, false otherwise.
   20864      */
   20865     @SuppressWarnings({"UnusedParameters"})
   20866     protected boolean overScrollBy(int deltaX, int deltaY,
   20867             int scrollX, int scrollY,
   20868             int scrollRangeX, int scrollRangeY,
   20869             int maxOverScrollX, int maxOverScrollY,
   20870             boolean isTouchEvent) {
   20871         final int overScrollMode = mOverScrollMode;
   20872         final boolean canScrollHorizontal =
   20873                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
   20874         final boolean canScrollVertical =
   20875                 computeVerticalScrollRange() > computeVerticalScrollExtent();
   20876         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
   20877                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
   20878         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
   20879                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
   20880 
   20881         int newScrollX = scrollX + deltaX;
   20882         if (!overScrollHorizontal) {
   20883             maxOverScrollX = 0;
   20884         }
   20885 
   20886         int newScrollY = scrollY + deltaY;
   20887         if (!overScrollVertical) {
   20888             maxOverScrollY = 0;
   20889         }
   20890 
   20891         // Clamp values if at the limits and record
   20892         final int left = -maxOverScrollX;
   20893         final int right = maxOverScrollX + scrollRangeX;
   20894         final int top = -maxOverScrollY;
   20895         final int bottom = maxOverScrollY + scrollRangeY;
   20896 
   20897         boolean clampedX = false;
   20898         if (newScrollX > right) {
   20899             newScrollX = right;
   20900             clampedX = true;
   20901         } else if (newScrollX < left) {
   20902             newScrollX = left;
   20903             clampedX = true;
   20904         }
   20905 
   20906         boolean clampedY = false;
   20907         if (newScrollY > bottom) {
   20908             newScrollY = bottom;
   20909             clampedY = true;
   20910         } else if (newScrollY < top) {
   20911             newScrollY = top;
   20912             clampedY = true;
   20913         }
   20914 
   20915         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
   20916 
   20917         return clampedX || clampedY;
   20918     }
   20919 
   20920     /**
   20921      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
   20922      * respond to the results of an over-scroll operation.
   20923      *
   20924      * @param scrollX New X scroll value in pixels
   20925      * @param scrollY New Y scroll value in pixels
   20926      * @param clampedX True if scrollX was clamped to an over-scroll boundary
   20927      * @param clampedY True if scrollY was clamped to an over-scroll boundary
   20928      */
   20929     protected void onOverScrolled(int scrollX, int scrollY,
   20930             boolean clampedX, boolean clampedY) {
   20931         // Intentionally empty.
   20932     }
   20933 
   20934     /**
   20935      * Returns the over-scroll mode for this view. The result will be
   20936      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   20937      * (allow over-scrolling only if the view content is larger than the container),
   20938      * or {@link #OVER_SCROLL_NEVER}.
   20939      *
   20940      * @return This view's over-scroll mode.
   20941      */
   20942     public int getOverScrollMode() {
   20943         return mOverScrollMode;
   20944     }
   20945 
   20946     /**
   20947      * Set the over-scroll mode for this view. Valid over-scroll modes are
   20948      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   20949      * (allow over-scrolling only if the view content is larger than the container),
   20950      * or {@link #OVER_SCROLL_NEVER}.
   20951      *
   20952      * Setting the over-scroll mode of a view will have an effect only if the
   20953      * view is capable of scrolling.
   20954      *
   20955      * @param overScrollMode The new over-scroll mode for this view.
   20956      */
   20957     public void setOverScrollMode(int overScrollMode) {
   20958         if (overScrollMode != OVER_SCROLL_ALWAYS &&
   20959                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
   20960                 overScrollMode != OVER_SCROLL_NEVER) {
   20961             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
   20962         }
   20963         mOverScrollMode = overScrollMode;
   20964     }
   20965 
   20966     /**
   20967      * Enable or disable nested scrolling for this view.
   20968      *
   20969      * <p>If this property is set to true the view will be permitted to initiate nested
   20970      * scrolling operations with a compatible parent view in the current hierarchy. If this
   20971      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
   20972      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
   20973      * the nested scroll.</p>
   20974      *
   20975      * @param enabled true to enable nested scrolling, false to disable
   20976      *
   20977      * @see #isNestedScrollingEnabled()
   20978      */
   20979     public void setNestedScrollingEnabled(boolean enabled) {
   20980         if (enabled) {
   20981             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
   20982         } else {
   20983             stopNestedScroll();
   20984             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
   20985         }
   20986     }
   20987 
   20988     /**
   20989      * Returns true if nested scrolling is enabled for this view.
   20990      *
   20991      * <p>If nested scrolling is enabled and this View class implementation supports it,
   20992      * this view will act as a nested scrolling child view when applicable, forwarding data
   20993      * about the scroll operation in progress to a compatible and cooperating nested scrolling
   20994      * parent.</p>
   20995      *
   20996      * @return true if nested scrolling is enabled
   20997      *
   20998      * @see #setNestedScrollingEnabled(boolean)
   20999      */
   21000     public boolean isNestedScrollingEnabled() {
   21001         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
   21002                 PFLAG3_NESTED_SCROLLING_ENABLED;
   21003     }
   21004 
   21005     /**
   21006      * Begin a nestable scroll operation along the given axes.
   21007      *
   21008      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
   21009      *
   21010      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
   21011      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
   21012      * In the case of touch scrolling the nested scroll will be terminated automatically in
   21013      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
   21014      * In the event of programmatic scrolling the caller must explicitly call
   21015      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
   21016      *
   21017      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
   21018      * If it returns false the caller may ignore the rest of this contract until the next scroll.
   21019      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
   21020      *
   21021      * <p>At each incremental step of the scroll the caller should invoke
   21022      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
   21023      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
   21024      * parent at least partially consumed the scroll and the caller should adjust the amount it
   21025      * scrolls by.</p>
   21026      *
   21027      * <p>After applying the remainder of the scroll delta the caller should invoke
   21028      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
   21029      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
   21030      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
   21031      * </p>
   21032      *
   21033      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
   21034      *             {@link #SCROLL_AXIS_VERTICAL}.
   21035      * @return true if a cooperative parent was found and nested scrolling has been enabled for
   21036      *         the current gesture.
   21037      *
   21038      * @see #stopNestedScroll()
   21039      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   21040      * @see #dispatchNestedScroll(int, int, int, int, int[])
   21041      */
   21042     public boolean startNestedScroll(int axes) {
   21043         if (hasNestedScrollingParent()) {
   21044             // Already in progress
   21045             return true;
   21046         }
   21047         if (isNestedScrollingEnabled()) {
   21048             ViewParent p = getParent();
   21049             View child = this;
   21050             while (p != null) {
   21051                 try {
   21052                     if (p.onStartNestedScroll(child, this, axes)) {
   21053                         mNestedScrollingParent = p;
   21054                         p.onNestedScrollAccepted(child, this, axes);
   21055                         return true;
   21056                     }
   21057                 } catch (AbstractMethodError e) {
   21058                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
   21059                             "method onStartNestedScroll", e);
   21060                     // Allow the search upward to continue
   21061                 }
   21062                 if (p instanceof View) {
   21063                     child = (View) p;
   21064                 }
   21065                 p = p.getParent();
   21066             }
   21067         }
   21068         return false;
   21069     }
   21070 
   21071     /**
   21072      * Stop a nested scroll in progress.
   21073      *
   21074      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
   21075      *
   21076      * @see #startNestedScroll(int)
   21077      */
   21078     public void stopNestedScroll() {
   21079         if (mNestedScrollingParent != null) {
   21080             mNestedScrollingParent.onStopNestedScroll(this);
   21081             mNestedScrollingParent = null;
   21082         }
   21083     }
   21084 
   21085     /**
   21086      * Returns true if this view has a nested scrolling parent.
   21087      *
   21088      * <p>The presence of a nested scrolling parent indicates that this view has initiated
   21089      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
   21090      *
   21091      * @return whether this view has a nested scrolling parent
   21092      */
   21093     public boolean hasNestedScrollingParent() {
   21094         return mNestedScrollingParent != null;
   21095     }
   21096 
   21097     /**
   21098      * Dispatch one step of a nested scroll in progress.
   21099      *
   21100      * <p>Implementations of views that support nested scrolling should call this to report
   21101      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
   21102      * is not currently in progress or nested scrolling is not
   21103      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
   21104      *
   21105      * <p>Compatible View implementations should also call
   21106      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
   21107      * consuming a component of the scroll event themselves.</p>
   21108      *
   21109      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
   21110      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
   21111      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
   21112      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
   21113      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   21114      *                       in local view coordinates of this view from before this operation
   21115      *                       to after it completes. View implementations may use this to adjust
   21116      *                       expected input coordinate tracking.
   21117      * @return true if the event was dispatched, false if it could not be dispatched.
   21118      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   21119      */
   21120     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
   21121             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
   21122         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   21123             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
   21124                 int startX = 0;
   21125                 int startY = 0;
   21126                 if (offsetInWindow != null) {
   21127                     getLocationInWindow(offsetInWindow);
   21128                     startX = offsetInWindow[0];
   21129                     startY = offsetInWindow[1];
   21130                 }
   21131 
   21132                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
   21133                         dxUnconsumed, dyUnconsumed);
   21134 
   21135                 if (offsetInWindow != null) {
   21136                     getLocationInWindow(offsetInWindow);
   21137                     offsetInWindow[0] -= startX;
   21138                     offsetInWindow[1] -= startY;
   21139                 }
   21140                 return true;
   21141             } else if (offsetInWindow != null) {
   21142                 // No motion, no dispatch. Keep offsetInWindow up to date.
   21143                 offsetInWindow[0] = 0;
   21144                 offsetInWindow[1] = 0;
   21145             }
   21146         }
   21147         return false;
   21148     }
   21149 
   21150     /**
   21151      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
   21152      *
   21153      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
   21154      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
   21155      * scrolling operation to consume some or all of the scroll operation before the child view
   21156      * consumes it.</p>
   21157      *
   21158      * @param dx Horizontal scroll distance in pixels
   21159      * @param dy Vertical scroll distance in pixels
   21160      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
   21161      *                 and consumed[1] the consumed dy.
   21162      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   21163      *                       in local view coordinates of this view from before this operation
   21164      *                       to after it completes. View implementations may use this to adjust
   21165      *                       expected input coordinate tracking.
   21166      * @return true if the parent consumed some or all of the scroll delta
   21167      * @see #dispatchNestedScroll(int, int, int, int, int[])
   21168      */
   21169     public boolean dispatchNestedPreScroll(int dx, int dy,
   21170             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
   21171         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   21172             if (dx != 0 || dy != 0) {
   21173                 int startX = 0;
   21174                 int startY = 0;
   21175                 if (offsetInWindow != null) {
   21176                     getLocationInWindow(offsetInWindow);
   21177                     startX = offsetInWindow[0];
   21178                     startY = offsetInWindow[1];
   21179                 }
   21180 
   21181                 if (consumed == null) {
   21182                     if (mTempNestedScrollConsumed == null) {
   21183                         mTempNestedScrollConsumed = new int[2];
   21184                     }
   21185                     consumed = mTempNestedScrollConsumed;
   21186                 }
   21187                 consumed[0] = 0;
   21188                 consumed[1] = 0;
   21189                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
   21190 
   21191                 if (offsetInWindow != null) {
   21192                     getLocationInWindow(offsetInWindow);
   21193                     offsetInWindow[0] -= startX;
   21194                     offsetInWindow[1] -= startY;
   21195                 }
   21196                 return consumed[0] != 0 || consumed[1] != 0;
   21197             } else if (offsetInWindow != null) {
   21198                 offsetInWindow[0] = 0;
   21199                 offsetInWindow[1] = 0;
   21200             }
   21201         }
   21202         return false;
   21203     }
   21204 
   21205     /**
   21206      * Dispatch a fling to a nested scrolling parent.
   21207      *
   21208      * <p>This method should be used to indicate that a nested scrolling child has detected
   21209      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
   21210      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
   21211      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
   21212      * along a scrollable axis.</p>
   21213      *
   21214      * <p>If a nested scrolling child view would normally fling but it is at the edge of
   21215      * its own content, it can use this method to delegate the fling to its nested scrolling
   21216      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
   21217      *
   21218      * @param velocityX Horizontal fling velocity in pixels per second
   21219      * @param velocityY Vertical fling velocity in pixels per second
   21220      * @param consumed true if the child consumed the fling, false otherwise
   21221      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
   21222      */
   21223     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
   21224         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   21225             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
   21226         }
   21227         return false;
   21228     }
   21229 
   21230     /**
   21231      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
   21232      *
   21233      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
   21234      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
   21235      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
   21236      * before the child view consumes it. If this method returns <code>true</code>, a nested
   21237      * parent view consumed the fling and this view should not scroll as a result.</p>
   21238      *
   21239      * <p>For a better user experience, only one view in a nested scrolling chain should consume
   21240      * the fling at a time. If a parent view consumed the fling this method will return false.
   21241      * Custom view implementations should account for this in two ways:</p>
   21242      *
   21243      * <ul>
   21244      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
   21245      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
   21246      *     position regardless.</li>
   21247      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
   21248      *     even to settle back to a valid idle position.</li>
   21249      * </ul>
   21250      *
   21251      * <p>Views should also not offer fling velocities to nested parent views along an axis
   21252      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
   21253      * should not offer a horizontal fling velocity to its parents since scrolling along that
   21254      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
   21255      *
   21256      * @param velocityX Horizontal fling velocity in pixels per second
   21257      * @param velocityY Vertical fling velocity in pixels per second
   21258      * @return true if a nested scrolling parent consumed the fling
   21259      */
   21260     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
   21261         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   21262             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
   21263         }
   21264         return false;
   21265     }
   21266 
   21267     /**
   21268      * Gets a scale factor that determines the distance the view should scroll
   21269      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
   21270      * @return The vertical scroll scale factor.
   21271      * @hide
   21272      */
   21273     protected float getVerticalScrollFactor() {
   21274         if (mVerticalScrollFactor == 0) {
   21275             TypedValue outValue = new TypedValue();
   21276             if (!mContext.getTheme().resolveAttribute(
   21277                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
   21278                 throw new IllegalStateException(
   21279                         "Expected theme to define listPreferredItemHeight.");
   21280             }
   21281             mVerticalScrollFactor = outValue.getDimension(
   21282                     mContext.getResources().getDisplayMetrics());
   21283         }
   21284         return mVerticalScrollFactor;
   21285     }
   21286 
   21287     /**
   21288      * Gets a scale factor that determines the distance the view should scroll
   21289      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
   21290      * @return The horizontal scroll scale factor.
   21291      * @hide
   21292      */
   21293     protected float getHorizontalScrollFactor() {
   21294         // TODO: Should use something else.
   21295         return getVerticalScrollFactor();
   21296     }
   21297 
   21298     /**
   21299      * Return the value specifying the text direction or policy that was set with
   21300      * {@link #setTextDirection(int)}.
   21301      *
   21302      * @return the defined text direction. It can be one of:
   21303      *
   21304      * {@link #TEXT_DIRECTION_INHERIT},
   21305      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   21306      * {@link #TEXT_DIRECTION_ANY_RTL},
   21307      * {@link #TEXT_DIRECTION_LTR},
   21308      * {@link #TEXT_DIRECTION_RTL},
   21309      * {@link #TEXT_DIRECTION_LOCALE},
   21310      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   21311      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   21312      *
   21313      * @attr ref android.R.styleable#View_textDirection
   21314      *
   21315      * @hide
   21316      */
   21317     @ViewDebug.ExportedProperty(category = "text", mapping = {
   21318             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   21319             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   21320             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   21321             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   21322             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   21323             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   21324             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   21325             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   21326     })
   21327     public int getRawTextDirection() {
   21328         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   21329     }
   21330 
   21331     /**
   21332      * Set the text direction.
   21333      *
   21334      * @param textDirection the direction to set. Should be one of:
   21335      *
   21336      * {@link #TEXT_DIRECTION_INHERIT},
   21337      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   21338      * {@link #TEXT_DIRECTION_ANY_RTL},
   21339      * {@link #TEXT_DIRECTION_LTR},
   21340      * {@link #TEXT_DIRECTION_RTL},
   21341      * {@link #TEXT_DIRECTION_LOCALE}
   21342      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   21343      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
   21344      *
   21345      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
   21346      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
   21347      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
   21348      *
   21349      * @attr ref android.R.styleable#View_textDirection
   21350      */
   21351     public void setTextDirection(int textDirection) {
   21352         if (getRawTextDirection() != textDirection) {
   21353             // Reset the current text direction and the resolved one
   21354             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   21355             resetResolvedTextDirection();
   21356             // Set the new text direction
   21357             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
   21358             // Do resolution
   21359             resolveTextDirection();
   21360             // Notify change
   21361             onRtlPropertiesChanged(getLayoutDirection());
   21362             // Refresh
   21363             requestLayout();
   21364             invalidate(true);
   21365         }
   21366     }
   21367 
   21368     /**
   21369      * Return the resolved text direction.
   21370      *
   21371      * @return the resolved text direction. Returns one of:
   21372      *
   21373      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   21374      * {@link #TEXT_DIRECTION_ANY_RTL},
   21375      * {@link #TEXT_DIRECTION_LTR},
   21376      * {@link #TEXT_DIRECTION_RTL},
   21377      * {@link #TEXT_DIRECTION_LOCALE},
   21378      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   21379      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   21380      *
   21381      * @attr ref android.R.styleable#View_textDirection
   21382      */
   21383     @ViewDebug.ExportedProperty(category = "text", mapping = {
   21384             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   21385             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   21386             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   21387             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   21388             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   21389             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   21390             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   21391             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   21392     })
   21393     public int getTextDirection() {
   21394         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   21395     }
   21396 
   21397     /**
   21398      * Resolve the text direction.
   21399      *
   21400      * @return true if resolution has been done, false otherwise.
   21401      *
   21402      * @hide
   21403      */
   21404     public boolean resolveTextDirection() {
   21405         // Reset any previous text direction resolution
   21406         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   21407 
   21408         if (hasRtlSupport()) {
   21409             // Set resolved text direction flag depending on text direction flag
   21410             final int textDirection = getRawTextDirection();
   21411             switch(textDirection) {
   21412                 case TEXT_DIRECTION_INHERIT:
   21413                     if (!canResolveTextDirection()) {
   21414                         // We cannot do the resolution if there is no parent, so use the default one
   21415                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21416                         // Resolution will need to happen again later
   21417                         return false;
   21418                     }
   21419 
   21420                     // Parent has not yet resolved, so we still return the default
   21421                     try {
   21422                         if (!mParent.isTextDirectionResolved()) {
   21423                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21424                             // Resolution will need to happen again later
   21425                             return false;
   21426                         }
   21427                     } catch (AbstractMethodError e) {
   21428                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21429                                 " does not fully implement ViewParent", e);
   21430                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
   21431                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21432                         return true;
   21433                     }
   21434 
   21435                     // Set current resolved direction to the same value as the parent's one
   21436                     int parentResolvedDirection;
   21437                     try {
   21438                         parentResolvedDirection = mParent.getTextDirection();
   21439                     } catch (AbstractMethodError e) {
   21440                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21441                                 " does not fully implement ViewParent", e);
   21442                         parentResolvedDirection = TEXT_DIRECTION_LTR;
   21443                     }
   21444                     switch (parentResolvedDirection) {
   21445                         case TEXT_DIRECTION_FIRST_STRONG:
   21446                         case TEXT_DIRECTION_ANY_RTL:
   21447                         case TEXT_DIRECTION_LTR:
   21448                         case TEXT_DIRECTION_RTL:
   21449                         case TEXT_DIRECTION_LOCALE:
   21450                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
   21451                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
   21452                             mPrivateFlags2 |=
   21453                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   21454                             break;
   21455                         default:
   21456                             // Default resolved direction is "first strong" heuristic
   21457                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21458                     }
   21459                     break;
   21460                 case TEXT_DIRECTION_FIRST_STRONG:
   21461                 case TEXT_DIRECTION_ANY_RTL:
   21462                 case TEXT_DIRECTION_LTR:
   21463                 case TEXT_DIRECTION_RTL:
   21464                 case TEXT_DIRECTION_LOCALE:
   21465                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
   21466                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
   21467                     // Resolved direction is the same as text direction
   21468                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   21469                     break;
   21470                 default:
   21471                     // Default resolved direction is "first strong" heuristic
   21472                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21473             }
   21474         } else {
   21475             // Default resolved direction is "first strong" heuristic
   21476             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21477         }
   21478 
   21479         // Set to resolved
   21480         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
   21481         return true;
   21482     }
   21483 
   21484     /**
   21485      * Check if text direction resolution can be done.
   21486      *
   21487      * @return true if text direction resolution can be done otherwise return false.
   21488      */
   21489     public boolean canResolveTextDirection() {
   21490         switch (getRawTextDirection()) {
   21491             case TEXT_DIRECTION_INHERIT:
   21492                 if (mParent != null) {
   21493                     try {
   21494                         return mParent.canResolveTextDirection();
   21495                     } catch (AbstractMethodError e) {
   21496                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21497                                 " does not fully implement ViewParent", e);
   21498                     }
   21499                 }
   21500                 return false;
   21501 
   21502             default:
   21503                 return true;
   21504         }
   21505     }
   21506 
   21507     /**
   21508      * Reset resolved text direction. Text direction will be resolved during a call to
   21509      * {@link #onMeasure(int, int)}.
   21510      *
   21511      * @hide
   21512      */
   21513     public void resetResolvedTextDirection() {
   21514         // Reset any previous text direction resolution
   21515         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   21516         // Set to default value
   21517         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21518     }
   21519 
   21520     /**
   21521      * @return true if text direction is inherited.
   21522      *
   21523      * @hide
   21524      */
   21525     public boolean isTextDirectionInherited() {
   21526         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
   21527     }
   21528 
   21529     /**
   21530      * @return true if text direction is resolved.
   21531      */
   21532     public boolean isTextDirectionResolved() {
   21533         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
   21534     }
   21535 
   21536     /**
   21537      * Return the value specifying the text alignment or policy that was set with
   21538      * {@link #setTextAlignment(int)}.
   21539      *
   21540      * @return the defined text alignment. It can be one of:
   21541      *
   21542      * {@link #TEXT_ALIGNMENT_INHERIT},
   21543      * {@link #TEXT_ALIGNMENT_GRAVITY},
   21544      * {@link #TEXT_ALIGNMENT_CENTER},
   21545      * {@link #TEXT_ALIGNMENT_TEXT_START},
   21546      * {@link #TEXT_ALIGNMENT_TEXT_END},
   21547      * {@link #TEXT_ALIGNMENT_VIEW_START},
   21548      * {@link #TEXT_ALIGNMENT_VIEW_END}
   21549      *
   21550      * @attr ref android.R.styleable#View_textAlignment
   21551      *
   21552      * @hide
   21553      */
   21554     @ViewDebug.ExportedProperty(category = "text", mapping = {
   21555             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   21556             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   21557             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   21558             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   21559             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   21560             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   21561             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   21562     })
   21563     @TextAlignment
   21564     public int getRawTextAlignment() {
   21565         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   21566     }
   21567 
   21568     /**
   21569      * Set the text alignment.
   21570      *
   21571      * @param textAlignment The text alignment to set. Should be one of
   21572      *
   21573      * {@link #TEXT_ALIGNMENT_INHERIT},
   21574      * {@link #TEXT_ALIGNMENT_GRAVITY},
   21575      * {@link #TEXT_ALIGNMENT_CENTER},
   21576      * {@link #TEXT_ALIGNMENT_TEXT_START},
   21577      * {@link #TEXT_ALIGNMENT_TEXT_END},
   21578      * {@link #TEXT_ALIGNMENT_VIEW_START},
   21579      * {@link #TEXT_ALIGNMENT_VIEW_END}
   21580      *
   21581      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
   21582      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   21583      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
   21584      *
   21585      * @attr ref android.R.styleable#View_textAlignment
   21586      */
   21587     public void setTextAlignment(@TextAlignment int textAlignment) {
   21588         if (textAlignment != getRawTextAlignment()) {
   21589             // Reset the current and resolved text alignment
   21590             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   21591             resetResolvedTextAlignment();
   21592             // Set the new text alignment
   21593             mPrivateFlags2 |=
   21594                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
   21595             // Do resolution
   21596             resolveTextAlignment();
   21597             // Notify change
   21598             onRtlPropertiesChanged(getLayoutDirection());
   21599             // Refresh
   21600             requestLayout();
   21601             invalidate(true);
   21602         }
   21603     }
   21604 
   21605     /**
   21606      * Return the resolved text alignment.
   21607      *
   21608      * @return the resolved text alignment. Returns one of:
   21609      *
   21610      * {@link #TEXT_ALIGNMENT_GRAVITY},
   21611      * {@link #TEXT_ALIGNMENT_CENTER},
   21612      * {@link #TEXT_ALIGNMENT_TEXT_START},
   21613      * {@link #TEXT_ALIGNMENT_TEXT_END},
   21614      * {@link #TEXT_ALIGNMENT_VIEW_START},
   21615      * {@link #TEXT_ALIGNMENT_VIEW_END}
   21616      *
   21617      * @attr ref android.R.styleable#View_textAlignment
   21618      */
   21619     @ViewDebug.ExportedProperty(category = "text", mapping = {
   21620             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   21621             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   21622             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   21623             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   21624             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   21625             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   21626             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   21627     })
   21628     @TextAlignment
   21629     public int getTextAlignment() {
   21630         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
   21631                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   21632     }
   21633 
   21634     /**
   21635      * Resolve the text alignment.
   21636      *
   21637      * @return true if resolution has been done, false otherwise.
   21638      *
   21639      * @hide
   21640      */
   21641     public boolean resolveTextAlignment() {
   21642         // Reset any previous text alignment resolution
   21643         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   21644 
   21645         if (hasRtlSupport()) {
   21646             // Set resolved text alignment flag depending on text alignment flag
   21647             final int textAlignment = getRawTextAlignment();
   21648             switch (textAlignment) {
   21649                 case TEXT_ALIGNMENT_INHERIT:
   21650                     // Check if we can resolve the text alignment
   21651                     if (!canResolveTextAlignment()) {
   21652                         // We cannot do the resolution if there is no parent so use the default
   21653                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21654                         // Resolution will need to happen again later
   21655                         return false;
   21656                     }
   21657 
   21658                     // Parent has not yet resolved, so we still return the default
   21659                     try {
   21660                         if (!mParent.isTextAlignmentResolved()) {
   21661                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21662                             // Resolution will need to happen again later
   21663                             return false;
   21664                         }
   21665                     } catch (AbstractMethodError e) {
   21666                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21667                                 " does not fully implement ViewParent", e);
   21668                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   21669                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21670                         return true;
   21671                     }
   21672 
   21673                     int parentResolvedTextAlignment;
   21674                     try {
   21675                         parentResolvedTextAlignment = mParent.getTextAlignment();
   21676                     } catch (AbstractMethodError e) {
   21677                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21678                                 " does not fully implement ViewParent", e);
   21679                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
   21680                     }
   21681                     switch (parentResolvedTextAlignment) {
   21682                         case TEXT_ALIGNMENT_GRAVITY:
   21683                         case TEXT_ALIGNMENT_TEXT_START:
   21684                         case TEXT_ALIGNMENT_TEXT_END:
   21685                         case TEXT_ALIGNMENT_CENTER:
   21686                         case TEXT_ALIGNMENT_VIEW_START:
   21687                         case TEXT_ALIGNMENT_VIEW_END:
   21688                             // Resolved text alignment is the same as the parent resolved
   21689                             // text alignment
   21690                             mPrivateFlags2 |=
   21691                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   21692                             break;
   21693                         default:
   21694                             // Use default resolved text alignment
   21695                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21696                     }
   21697                     break;
   21698                 case TEXT_ALIGNMENT_GRAVITY:
   21699                 case TEXT_ALIGNMENT_TEXT_START:
   21700                 case TEXT_ALIGNMENT_TEXT_END:
   21701                 case TEXT_ALIGNMENT_CENTER:
   21702                 case TEXT_ALIGNMENT_VIEW_START:
   21703                 case TEXT_ALIGNMENT_VIEW_END:
   21704                     // Resolved text alignment is the same as text alignment
   21705                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   21706                     break;
   21707                 default:
   21708                     // Use default resolved text alignment
   21709                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21710             }
   21711         } else {
   21712             // Use default resolved text alignment
   21713             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21714         }
   21715 
   21716         // Set the resolved
   21717         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   21718         return true;
   21719     }
   21720 
   21721     /**
   21722      * Check if text alignment resolution can be done.
   21723      *
   21724      * @return true if text alignment resolution can be done otherwise return false.
   21725      */
   21726     public boolean canResolveTextAlignment() {
   21727         switch (getRawTextAlignment()) {
   21728             case TEXT_DIRECTION_INHERIT:
   21729                 if (mParent != null) {
   21730                     try {
   21731                         return mParent.canResolveTextAlignment();
   21732                     } catch (AbstractMethodError e) {
   21733                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21734                                 " does not fully implement ViewParent", e);
   21735                     }
   21736                 }
   21737                 return false;
   21738 
   21739             default:
   21740                 return true;
   21741         }
   21742     }
   21743 
   21744     /**
   21745      * Reset resolved text alignment. Text alignment will be resolved during a call to
   21746      * {@link #onMeasure(int, int)}.
   21747      *
   21748      * @hide
   21749      */
   21750     public void resetResolvedTextAlignment() {
   21751         // Reset any previous text alignment resolution
   21752         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   21753         // Set to default
   21754         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21755     }
   21756 
   21757     /**
   21758      * @return true if text alignment is inherited.
   21759      *
   21760      * @hide
   21761      */
   21762     public boolean isTextAlignmentInherited() {
   21763         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
   21764     }
   21765 
   21766     /**
   21767      * @return true if text alignment is resolved.
   21768      */
   21769     public boolean isTextAlignmentResolved() {
   21770         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   21771     }
   21772 
   21773     /**
   21774      * Generate a value suitable for use in {@link #setId(int)}.
   21775      * This value will not collide with ID values generated at build time by aapt for R.id.
   21776      *
   21777      * @return a generated ID value
   21778      */
   21779     public static int generateViewId() {
   21780         for (;;) {
   21781             final int result = sNextGeneratedId.get();
   21782             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
   21783             int newValue = result + 1;
   21784             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
   21785             if (sNextGeneratedId.compareAndSet(result, newValue)) {
   21786                 return result;
   21787             }
   21788         }
   21789     }
   21790 
   21791     /**
   21792      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
   21793      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
   21794      *                           a normal View or a ViewGroup with
   21795      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
   21796      * @hide
   21797      */
   21798     public void captureTransitioningViews(List<View> transitioningViews) {
   21799         if (getVisibility() == View.VISIBLE) {
   21800             transitioningViews.add(this);
   21801         }
   21802     }
   21803 
   21804     /**
   21805      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
   21806      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
   21807      * @hide
   21808      */
   21809     public void findNamedViews(Map<String, View> namedElements) {
   21810         if (getVisibility() == VISIBLE || mGhostView != null) {
   21811             String transitionName = getTransitionName();
   21812             if (transitionName != null) {
   21813                 namedElements.put(transitionName, this);
   21814             }
   21815         }
   21816     }
   21817 
   21818     /**
   21819      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
   21820      * The default implementation does not care the location or event types, but some subclasses
   21821      * may use it (such as WebViews).
   21822      * @param event The MotionEvent from a mouse
   21823      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
   21824      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
   21825      * @see PointerIcon
   21826      */
   21827     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
   21828         final float x = event.getX(pointerIndex);
   21829         final float y = event.getY(pointerIndex);
   21830         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
   21831             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
   21832         }
   21833         return mPointerIcon;
   21834     }
   21835 
   21836     /**
   21837      * Set the pointer icon for the current view.
   21838      * Passing {@code null} will restore the pointer icon to its default value.
   21839      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
   21840      */
   21841     public void setPointerIcon(PointerIcon pointerIcon) {
   21842         mPointerIcon = pointerIcon;
   21843         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
   21844             return;
   21845         }
   21846         try {
   21847             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
   21848         } catch (RemoteException e) {
   21849         }
   21850     }
   21851 
   21852     /**
   21853      * Gets the pointer icon for the current view.
   21854      */
   21855     public PointerIcon getPointerIcon() {
   21856         return mPointerIcon;
   21857     }
   21858 
   21859     //
   21860     // Properties
   21861     //
   21862     /**
   21863      * A Property wrapper around the <code>alpha</code> functionality handled by the
   21864      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
   21865      */
   21866     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
   21867         @Override
   21868         public void setValue(View object, float value) {
   21869             object.setAlpha(value);
   21870         }
   21871 
   21872         @Override
   21873         public Float get(View object) {
   21874             return object.getAlpha();
   21875         }
   21876     };
   21877 
   21878     /**
   21879      * A Property wrapper around the <code>translationX</code> functionality handled by the
   21880      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
   21881      */
   21882     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
   21883         @Override
   21884         public void setValue(View object, float value) {
   21885             object.setTranslationX(value);
   21886         }
   21887 
   21888                 @Override
   21889         public Float get(View object) {
   21890             return object.getTranslationX();
   21891         }
   21892     };
   21893 
   21894     /**
   21895      * A Property wrapper around the <code>translationY</code> functionality handled by the
   21896      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
   21897      */
   21898     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
   21899         @Override
   21900         public void setValue(View object, float value) {
   21901             object.setTranslationY(value);
   21902         }
   21903 
   21904         @Override
   21905         public Float get(View object) {
   21906             return object.getTranslationY();
   21907         }
   21908     };
   21909 
   21910     /**
   21911      * A Property wrapper around the <code>translationZ</code> functionality handled by the
   21912      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
   21913      */
   21914     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
   21915         @Override
   21916         public void setValue(View object, float value) {
   21917             object.setTranslationZ(value);
   21918         }
   21919 
   21920         @Override
   21921         public Float get(View object) {
   21922             return object.getTranslationZ();
   21923         }
   21924     };
   21925 
   21926     /**
   21927      * A Property wrapper around the <code>x</code> functionality handled by the
   21928      * {@link View#setX(float)} and {@link View#getX()} methods.
   21929      */
   21930     public static final Property<View, Float> X = new FloatProperty<View>("x") {
   21931         @Override
   21932         public void setValue(View object, float value) {
   21933             object.setX(value);
   21934         }
   21935 
   21936         @Override
   21937         public Float get(View object) {
   21938             return object.getX();
   21939         }
   21940     };
   21941 
   21942     /**
   21943      * A Property wrapper around the <code>y</code> functionality handled by the
   21944      * {@link View#setY(float)} and {@link View#getY()} methods.
   21945      */
   21946     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
   21947         @Override
   21948         public void setValue(View object, float value) {
   21949             object.setY(value);
   21950         }
   21951 
   21952         @Override
   21953         public Float get(View object) {
   21954             return object.getY();
   21955         }
   21956     };
   21957 
   21958     /**
   21959      * A Property wrapper around the <code>z</code> functionality handled by the
   21960      * {@link View#setZ(float)} and {@link View#getZ()} methods.
   21961      */
   21962     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
   21963         @Override
   21964         public void setValue(View object, float value) {
   21965             object.setZ(value);
   21966         }
   21967 
   21968         @Override
   21969         public Float get(View object) {
   21970             return object.getZ();
   21971         }
   21972     };
   21973 
   21974     /**
   21975      * A Property wrapper around the <code>rotation</code> functionality handled by the
   21976      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
   21977      */
   21978     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
   21979         @Override
   21980         public void setValue(View object, float value) {
   21981             object.setRotation(value);
   21982         }
   21983 
   21984         @Override
   21985         public Float get(View object) {
   21986             return object.getRotation();
   21987         }
   21988     };
   21989 
   21990     /**
   21991      * A Property wrapper around the <code>rotationX</code> functionality handled by the
   21992      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
   21993      */
   21994     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
   21995         @Override
   21996         public void setValue(View object, float value) {
   21997             object.setRotationX(value);
   21998         }
   21999 
   22000         @Override
   22001         public Float get(View object) {
   22002             return object.getRotationX();
   22003         }
   22004     };
   22005 
   22006     /**
   22007      * A Property wrapper around the <code>rotationY</code> functionality handled by the
   22008      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
   22009      */
   22010     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
   22011         @Override
   22012         public void setValue(View object, float value) {
   22013             object.setRotationY(value);
   22014         }
   22015 
   22016         @Override
   22017         public Float get(View object) {
   22018             return object.getRotationY();
   22019         }
   22020     };
   22021 
   22022     /**
   22023      * A Property wrapper around the <code>scaleX</code> functionality handled by the
   22024      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
   22025      */
   22026     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
   22027         @Override
   22028         public void setValue(View object, float value) {
   22029             object.setScaleX(value);
   22030         }
   22031 
   22032         @Override
   22033         public Float get(View object) {
   22034             return object.getScaleX();
   22035         }
   22036     };
   22037 
   22038     /**
   22039      * A Property wrapper around the <code>scaleY</code> functionality handled by the
   22040      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
   22041      */
   22042     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
   22043         @Override
   22044         public void setValue(View object, float value) {
   22045             object.setScaleY(value);
   22046         }
   22047 
   22048         @Override
   22049         public Float get(View object) {
   22050             return object.getScaleY();
   22051         }
   22052     };
   22053 
   22054     /**
   22055      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
   22056      * Each MeasureSpec represents a requirement for either the width or the height.
   22057      * A MeasureSpec is comprised of a size and a mode. There are three possible
   22058      * modes:
   22059      * <dl>
   22060      * <dt>UNSPECIFIED</dt>
   22061      * <dd>
   22062      * The parent has not imposed any constraint on the child. It can be whatever size
   22063      * it wants.
   22064      * </dd>
   22065      *
   22066      * <dt>EXACTLY</dt>
   22067      * <dd>
   22068      * The parent has determined an exact size for the child. The child is going to be
   22069      * given those bounds regardless of how big it wants to be.
   22070      * </dd>
   22071      *
   22072      * <dt>AT_MOST</dt>
   22073      * <dd>
   22074      * The child can be as large as it wants up to the specified size.
   22075      * </dd>
   22076      * </dl>
   22077      *
   22078      * MeasureSpecs are implemented as ints to reduce object allocation. This class
   22079      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
   22080      */
   22081     public static class MeasureSpec {
   22082         private static final int MODE_SHIFT = 30;
   22083         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
   22084 
   22085         /** @hide */
   22086         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
   22087         @Retention(RetentionPolicy.SOURCE)
   22088         public @interface MeasureSpecMode {}
   22089 
   22090         /**
   22091          * Measure specification mode: The parent has not imposed any constraint
   22092          * on the child. It can be whatever size it wants.
   22093          */
   22094         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
   22095 
   22096         /**
   22097          * Measure specification mode: The parent has determined an exact size
   22098          * for the child. The child is going to be given those bounds regardless
   22099          * of how big it wants to be.
   22100          */
   22101         public static final int EXACTLY     = 1 << MODE_SHIFT;
   22102 
   22103         /**
   22104          * Measure specification mode: The child can be as large as it wants up
   22105          * to the specified size.
   22106          */
   22107         public static final int AT_MOST     = 2 << MODE_SHIFT;
   22108 
   22109         /**
   22110          * Creates a measure specification based on the supplied size and mode.
   22111          *
   22112          * The mode must always be one of the following:
   22113          * <ul>
   22114          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
   22115          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
   22116          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
   22117          * </ul>
   22118          *
   22119          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
   22120          * implementation was such that the order of arguments did not matter
   22121          * and overflow in either value could impact the resulting MeasureSpec.
   22122          * {@link android.widget.RelativeLayout} was affected by this bug.
   22123          * Apps targeting API levels greater than 17 will get the fixed, more strict
   22124          * behavior.</p>
   22125          *
   22126          * @param size the size of the measure specification
   22127          * @param mode the mode of the measure specification
   22128          * @return the measure specification based on size and mode
   22129          */
   22130         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
   22131                                           @MeasureSpecMode int mode) {
   22132             if (sUseBrokenMakeMeasureSpec) {
   22133                 return size + mode;
   22134             } else {
   22135                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
   22136             }
   22137         }
   22138 
   22139         /**
   22140          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
   22141          * will automatically get a size of 0. Older apps expect this.
   22142          *
   22143          * @hide internal use only for compatibility with system widgets and older apps
   22144          */
   22145         public static int makeSafeMeasureSpec(int size, int mode) {
   22146             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
   22147                 return 0;
   22148             }
   22149             return makeMeasureSpec(size, mode);
   22150         }
   22151 
   22152         /**
   22153          * Extracts the mode from the supplied measure specification.
   22154          *
   22155          * @param measureSpec the measure specification to extract the mode from
   22156          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
   22157          *         {@link android.view.View.MeasureSpec#AT_MOST} or
   22158          *         {@link android.view.View.MeasureSpec#EXACTLY}
   22159          */
   22160         @MeasureSpecMode
   22161         public static int getMode(int measureSpec) {
   22162             //noinspection ResourceType
   22163             return (measureSpec & MODE_MASK);
   22164         }
   22165 
   22166         /**
   22167          * Extracts the size from the supplied measure specification.
   22168          *
   22169          * @param measureSpec the measure specification to extract the size from
   22170          * @return the size in pixels defined in the supplied measure specification
   22171          */
   22172         public static int getSize(int measureSpec) {
   22173             return (measureSpec & ~MODE_MASK);
   22174         }
   22175 
   22176         static int adjust(int measureSpec, int delta) {
   22177             final int mode = getMode(measureSpec);
   22178             int size = getSize(measureSpec);
   22179             if (mode == UNSPECIFIED) {
   22180                 // No need to adjust size for UNSPECIFIED mode.
   22181                 return makeMeasureSpec(size, UNSPECIFIED);
   22182             }
   22183             size += delta;
   22184             if (size < 0) {
   22185                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
   22186                         ") spec: " + toString(measureSpec) + " delta: " + delta);
   22187                 size = 0;
   22188             }
   22189             return makeMeasureSpec(size, mode);
   22190         }
   22191 
   22192         /**
   22193          * Returns a String representation of the specified measure
   22194          * specification.
   22195          *
   22196          * @param measureSpec the measure specification to convert to a String
   22197          * @return a String with the following format: "MeasureSpec: MODE SIZE"
   22198          */
   22199         public static String toString(int measureSpec) {
   22200             int mode = getMode(measureSpec);
   22201             int size = getSize(measureSpec);
   22202 
   22203             StringBuilder sb = new StringBuilder("MeasureSpec: ");
   22204 
   22205             if (mode == UNSPECIFIED)
   22206                 sb.append("UNSPECIFIED ");
   22207             else if (mode == EXACTLY)
   22208                 sb.append("EXACTLY ");
   22209             else if (mode == AT_MOST)
   22210                 sb.append("AT_MOST ");
   22211             else
   22212                 sb.append(mode).append(" ");
   22213 
   22214             sb.append(size);
   22215             return sb.toString();
   22216         }
   22217     }
   22218 
   22219     private final class CheckForLongPress implements Runnable {
   22220         private int mOriginalWindowAttachCount;
   22221         private float mX;
   22222         private float mY;
   22223 
   22224         @Override
   22225         public void run() {
   22226             if (isPressed() && (mParent != null)
   22227                     && mOriginalWindowAttachCount == mWindowAttachCount) {
   22228                 if (performLongClick(mX, mY)) {
   22229                     mHasPerformedLongPress = true;
   22230                 }
   22231             }
   22232         }
   22233 
   22234         public void setAnchor(float x, float y) {
   22235             mX = x;
   22236             mY = y;
   22237         }
   22238 
   22239         public void rememberWindowAttachCount() {
   22240             mOriginalWindowAttachCount = mWindowAttachCount;
   22241         }
   22242     }
   22243 
   22244     private final class CheckForTap implements Runnable {
   22245         public float x;
   22246         public float y;
   22247 
   22248         @Override
   22249         public void run() {
   22250             mPrivateFlags &= ~PFLAG_PREPRESSED;
   22251             setPressed(true, x, y);
   22252             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
   22253         }
   22254     }
   22255 
   22256     private final class PerformClick implements Runnable {
   22257         @Override
   22258         public void run() {
   22259             performClick();
   22260         }
   22261     }
   22262 
   22263     /**
   22264      * This method returns a ViewPropertyAnimator object, which can be used to animate
   22265      * specific properties on this View.
   22266      *
   22267      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
   22268      */
   22269     public ViewPropertyAnimator animate() {
   22270         if (mAnimator == null) {
   22271             mAnimator = new ViewPropertyAnimator(this);
   22272         }
   22273         return mAnimator;
   22274     }
   22275 
   22276     /**
   22277      * Sets the name of the View to be used to identify Views in Transitions.
   22278      * Names should be unique in the View hierarchy.
   22279      *
   22280      * @param transitionName The name of the View to uniquely identify it for Transitions.
   22281      */
   22282     public final void setTransitionName(String transitionName) {
   22283         mTransitionName = transitionName;
   22284     }
   22285 
   22286     /**
   22287      * Returns the name of the View to be used to identify Views in Transitions.
   22288      * Names should be unique in the View hierarchy.
   22289      *
   22290      * <p>This returns null if the View has not been given a name.</p>
   22291      *
   22292      * @return The name used of the View to be used to identify Views in Transitions or null
   22293      * if no name has been given.
   22294      */
   22295     @ViewDebug.ExportedProperty
   22296     public String getTransitionName() {
   22297         return mTransitionName;
   22298     }
   22299 
   22300     /**
   22301      * @hide
   22302      */
   22303     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
   22304         // Do nothing.
   22305     }
   22306 
   22307     /**
   22308      * Interface definition for a callback to be invoked when a hardware key event is
   22309      * dispatched to this view. The callback will be invoked before the key event is
   22310      * given to the view. This is only useful for hardware keyboards; a software input
   22311      * method has no obligation to trigger this listener.
   22312      */
   22313     public interface OnKeyListener {
   22314         /**
   22315          * Called when a hardware key is dispatched to a view. This allows listeners to
   22316          * get a chance to respond before the target view.
   22317          * <p>Key presses in software keyboards will generally NOT trigger this method,
   22318          * although some may elect to do so in some situations. Do not assume a
   22319          * software input method has to be key-based; even if it is, it may use key presses
   22320          * in a different way than you expect, so there is no way to reliably catch soft
   22321          * input key presses.
   22322          *
   22323          * @param v The view the key has been dispatched to.
   22324          * @param keyCode The code for the physical key that was pressed
   22325          * @param event The KeyEvent object containing full information about
   22326          *        the event.
   22327          * @return True if the listener has consumed the event, false otherwise.
   22328          */
   22329         boolean onKey(View v, int keyCode, KeyEvent event);
   22330     }
   22331 
   22332     /**
   22333      * Interface definition for a callback to be invoked when a touch event is
   22334      * dispatched to this view. The callback will be invoked before the touch
   22335      * event is given to the view.
   22336      */
   22337     public interface OnTouchListener {
   22338         /**
   22339          * Called when a touch event is dispatched to a view. This allows listeners to
   22340          * get a chance to respond before the target view.
   22341          *
   22342          * @param v The view the touch event has been dispatched to.
   22343          * @param event The MotionEvent object containing full information about
   22344          *        the event.
   22345          * @return True if the listener has consumed the event, false otherwise.
   22346          */
   22347         boolean onTouch(View v, MotionEvent event);
   22348     }
   22349 
   22350     /**
   22351      * Interface definition for a callback to be invoked when a hover event is
   22352      * dispatched to this view. The callback will be invoked before the hover
   22353      * event is given to the view.
   22354      */
   22355     public interface OnHoverListener {
   22356         /**
   22357          * Called when a hover event is dispatched to a view. This allows listeners to
   22358          * get a chance to respond before the target view.
   22359          *
   22360          * @param v The view the hover event has been dispatched to.
   22361          * @param event The MotionEvent object containing full information about
   22362          *        the event.
   22363          * @return True if the listener has consumed the event, false otherwise.
   22364          */
   22365         boolean onHover(View v, MotionEvent event);
   22366     }
   22367 
   22368     /**
   22369      * Interface definition for a callback to be invoked when a generic motion event is
   22370      * dispatched to this view. The callback will be invoked before the generic motion
   22371      * event is given to the view.
   22372      */
   22373     public interface OnGenericMotionListener {
   22374         /**
   22375          * Called when a generic motion event is dispatched to a view. This allows listeners to
   22376          * get a chance to respond before the target view.
   22377          *
   22378          * @param v The view the generic motion event has been dispatched to.
   22379          * @param event The MotionEvent object containing full information about
   22380          *        the event.
   22381          * @return True if the listener has consumed the event, false otherwise.
   22382          */
   22383         boolean onGenericMotion(View v, MotionEvent event);
   22384     }
   22385 
   22386     /**
   22387      * Interface definition for a callback to be invoked when a view has been clicked and held.
   22388      */
   22389     public interface OnLongClickListener {
   22390         /**
   22391          * Called when a view has been clicked and held.
   22392          *
   22393          * @param v The view that was clicked and held.
   22394          *
   22395          * @return true if the callback consumed the long click, false otherwise.
   22396          */
   22397         boolean onLongClick(View v);
   22398     }
   22399 
   22400     /**
   22401      * Interface definition for a callback to be invoked when a drag is being dispatched
   22402      * to this view.  The callback will be invoked before the hosting view's own
   22403      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
   22404      * onDrag(event) behavior, it should return 'false' from this callback.
   22405      *
   22406      * <div class="special reference">
   22407      * <h3>Developer Guides</h3>
   22408      * <p>For a guide to implementing drag and drop features, read the
   22409      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   22410      * </div>
   22411      */
   22412     public interface OnDragListener {
   22413         /**
   22414          * Called when a drag event is dispatched to a view. This allows listeners
   22415          * to get a chance to override base View behavior.
   22416          *
   22417          * @param v The View that received the drag event.
   22418          * @param event The {@link android.view.DragEvent} object for the drag event.
   22419          * @return {@code true} if the drag event was handled successfully, or {@code false}
   22420          * if the drag event was not handled. Note that {@code false} will trigger the View
   22421          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
   22422          */
   22423         boolean onDrag(View v, DragEvent event);
   22424     }
   22425 
   22426     /**
   22427      * Interface definition for a callback to be invoked when the focus state of
   22428      * a view changed.
   22429      */
   22430     public interface OnFocusChangeListener {
   22431         /**
   22432          * Called when the focus state of a view has changed.
   22433          *
   22434          * @param v The view whose state has changed.
   22435          * @param hasFocus The new focus state of v.
   22436          */
   22437         void onFocusChange(View v, boolean hasFocus);
   22438     }
   22439 
   22440     /**
   22441      * Interface definition for a callback to be invoked when a view is clicked.
   22442      */
   22443     public interface OnClickListener {
   22444         /**
   22445          * Called when a view has been clicked.
   22446          *
   22447          * @param v The view that was clicked.
   22448          */
   22449         void onClick(View v);
   22450     }
   22451 
   22452     /**
   22453      * Interface definition for a callback to be invoked when a view is context clicked.
   22454      */
   22455     public interface OnContextClickListener {
   22456         /**
   22457          * Called when a view is context clicked.
   22458          *
   22459          * @param v The view that has been context clicked.
   22460          * @return true if the callback consumed the context click, false otherwise.
   22461          */
   22462         boolean onContextClick(View v);
   22463     }
   22464 
   22465     /**
   22466      * Interface definition for a callback to be invoked when the context menu
   22467      * for this view is being built.
   22468      */
   22469     public interface OnCreateContextMenuListener {
   22470         /**
   22471          * Called when the context menu for this view is being built. It is not
   22472          * safe to hold onto the menu after this method returns.
   22473          *
   22474          * @param menu The context menu that is being built
   22475          * @param v The view for which the context menu is being built
   22476          * @param menuInfo Extra information about the item for which the
   22477          *            context menu should be shown. This information will vary
   22478          *            depending on the class of v.
   22479          */
   22480         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
   22481     }
   22482 
   22483     /**
   22484      * Interface definition for a callback to be invoked when the status bar changes
   22485      * visibility.  This reports <strong>global</strong> changes to the system UI
   22486      * state, not what the application is requesting.
   22487      *
   22488      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
   22489      */
   22490     public interface OnSystemUiVisibilityChangeListener {
   22491         /**
   22492          * Called when the status bar changes visibility because of a call to
   22493          * {@link View#setSystemUiVisibility(int)}.
   22494          *
   22495          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   22496          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
   22497          * This tells you the <strong>global</strong> state of these UI visibility
   22498          * flags, not what your app is currently applying.
   22499          */
   22500         public void onSystemUiVisibilityChange(int visibility);
   22501     }
   22502 
   22503     /**
   22504      * Interface definition for a callback to be invoked when this view is attached
   22505      * or detached from its window.
   22506      */
   22507     public interface OnAttachStateChangeListener {
   22508         /**
   22509          * Called when the view is attached to a window.
   22510          * @param v The view that was attached
   22511          */
   22512         public void onViewAttachedToWindow(View v);
   22513         /**
   22514          * Called when the view is detached from a window.
   22515          * @param v The view that was detached
   22516          */
   22517         public void onViewDetachedFromWindow(View v);
   22518     }
   22519 
   22520     /**
   22521      * Listener for applying window insets on a view in a custom way.
   22522      *
   22523      * <p>Apps may choose to implement this interface if they want to apply custom policy
   22524      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
   22525      * is set, its
   22526      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   22527      * method will be called instead of the View's own
   22528      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
   22529      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
   22530      * the View's normal behavior as part of its own.</p>
   22531      */
   22532     public interface OnApplyWindowInsetsListener {
   22533         /**
   22534          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
   22535          * on a View, this listener method will be called instead of the view's own
   22536          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   22537          *
   22538          * @param v The view applying window insets
   22539          * @param insets The insets to apply
   22540          * @return The insets supplied, minus any insets that were consumed
   22541          */
   22542         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
   22543     }
   22544 
   22545     private final class UnsetPressedState implements Runnable {
   22546         @Override
   22547         public void run() {
   22548             setPressed(false);
   22549         }
   22550     }
   22551 
   22552     /**
   22553      * Base class for derived classes that want to save and restore their own
   22554      * state in {@link android.view.View#onSaveInstanceState()}.
   22555      */
   22556     public static class BaseSavedState extends AbsSavedState {
   22557         String mStartActivityRequestWhoSaved;
   22558 
   22559         /**
   22560          * Constructor used when reading from a parcel. Reads the state of the superclass.
   22561          *
   22562          * @param source parcel to read from
   22563          */
   22564         public BaseSavedState(Parcel source) {
   22565             this(source, null);
   22566         }
   22567 
   22568         /**
   22569          * Constructor used when reading from a parcel using a given class loader.
   22570          * Reads the state of the superclass.
   22571          *
   22572          * @param source parcel to read from
   22573          * @param loader ClassLoader to use for reading
   22574          */
   22575         public BaseSavedState(Parcel source, ClassLoader loader) {
   22576             super(source, loader);
   22577             mStartActivityRequestWhoSaved = source.readString();
   22578         }
   22579 
   22580         /**
   22581          * Constructor called by derived classes when creating their SavedState objects
   22582          *
   22583          * @param superState The state of the superclass of this view
   22584          */
   22585         public BaseSavedState(Parcelable superState) {
   22586             super(superState);
   22587         }
   22588 
   22589         @Override
   22590         public void writeToParcel(Parcel out, int flags) {
   22591             super.writeToParcel(out, flags);
   22592             out.writeString(mStartActivityRequestWhoSaved);
   22593         }
   22594 
   22595         public static final Parcelable.Creator<BaseSavedState> CREATOR
   22596                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
   22597             @Override
   22598             public BaseSavedState createFromParcel(Parcel in) {
   22599                 return new BaseSavedState(in);
   22600             }
   22601 
   22602             @Override
   22603             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
   22604                 return new BaseSavedState(in, loader);
   22605             }
   22606 
   22607             @Override
   22608             public BaseSavedState[] newArray(int size) {
   22609                 return new BaseSavedState[size];
   22610             }
   22611         };
   22612     }
   22613 
   22614     /**
   22615      * A set of information given to a view when it is attached to its parent
   22616      * window.
   22617      */
   22618     final static class AttachInfo {
   22619         interface Callbacks {
   22620             void playSoundEffect(int effectId);
   22621             boolean performHapticFeedback(int effectId, boolean always);
   22622         }
   22623 
   22624         /**
   22625          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
   22626          * to a Handler. This class contains the target (View) to invalidate and
   22627          * the coordinates of the dirty rectangle.
   22628          *
   22629          * For performance purposes, this class also implements a pool of up to
   22630          * POOL_LIMIT objects that get reused. This reduces memory allocations
   22631          * whenever possible.
   22632          */
   22633         static class InvalidateInfo {
   22634             private static final int POOL_LIMIT = 10;
   22635 
   22636             private static final SynchronizedPool<InvalidateInfo> sPool =
   22637                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
   22638 
   22639             View target;
   22640 
   22641             int left;
   22642             int top;
   22643             int right;
   22644             int bottom;
   22645 
   22646             public static InvalidateInfo obtain() {
   22647                 InvalidateInfo instance = sPool.acquire();
   22648                 return (instance != null) ? instance : new InvalidateInfo();
   22649             }
   22650 
   22651             public void recycle() {
   22652                 target = null;
   22653                 sPool.release(this);
   22654             }
   22655         }
   22656 
   22657         final IWindowSession mSession;
   22658 
   22659         final IWindow mWindow;
   22660 
   22661         final IBinder mWindowToken;
   22662 
   22663         final Display mDisplay;
   22664 
   22665         final Callbacks mRootCallbacks;
   22666 
   22667         IWindowId mIWindowId;
   22668         WindowId mWindowId;
   22669 
   22670         /**
   22671          * The top view of the hierarchy.
   22672          */
   22673         View mRootView;
   22674 
   22675         IBinder mPanelParentWindowToken;
   22676 
   22677         boolean mHardwareAccelerated;
   22678         boolean mHardwareAccelerationRequested;
   22679         ThreadedRenderer mHardwareRenderer;
   22680         List<RenderNode> mPendingAnimatingRenderNodes;
   22681 
   22682         /**
   22683          * The state of the display to which the window is attached, as reported
   22684          * by {@link Display#getState()}.  Note that the display state constants
   22685          * declared by {@link Display} do not exactly line up with the screen state
   22686          * constants declared by {@link View} (there are more display states than
   22687          * screen states).
   22688          */
   22689         int mDisplayState = Display.STATE_UNKNOWN;
   22690 
   22691         /**
   22692          * Scale factor used by the compatibility mode
   22693          */
   22694         float mApplicationScale;
   22695 
   22696         /**
   22697          * Indicates whether the application is in compatibility mode
   22698          */
   22699         boolean mScalingRequired;
   22700 
   22701         /**
   22702          * Left position of this view's window
   22703          */
   22704         int mWindowLeft;
   22705 
   22706         /**
   22707          * Top position of this view's window
   22708          */
   22709         int mWindowTop;
   22710 
   22711         /**
   22712          * Indicates whether views need to use 32-bit drawing caches
   22713          */
   22714         boolean mUse32BitDrawingCache;
   22715 
   22716         /**
   22717          * For windows that are full-screen but using insets to layout inside
   22718          * of the screen areas, these are the current insets to appear inside
   22719          * the overscan area of the display.
   22720          */
   22721         final Rect mOverscanInsets = new Rect();
   22722 
   22723         /**
   22724          * For windows that are full-screen but using insets to layout inside
   22725          * of the screen decorations, these are the current insets for the
   22726          * content of the window.
   22727          */
   22728         final Rect mContentInsets = new Rect();
   22729 
   22730         /**
   22731          * For windows that are full-screen but using insets to layout inside
   22732          * of the screen decorations, these are the current insets for the
   22733          * actual visible parts of the window.
   22734          */
   22735         final Rect mVisibleInsets = new Rect();
   22736 
   22737         /**
   22738          * For windows that are full-screen but using insets to layout inside
   22739          * of the screen decorations, these are the current insets for the
   22740          * stable system windows.
   22741          */
   22742         final Rect mStableInsets = new Rect();
   22743 
   22744         /**
   22745          * For windows that include areas that are not covered by real surface these are the outsets
   22746          * for real surface.
   22747          */
   22748         final Rect mOutsets = new Rect();
   22749 
   22750         /**
   22751          * In multi-window we force show the navigation bar. Because we don't want that the surface
   22752          * size changes in this mode, we instead have a flag whether the navigation bar size should
   22753          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
   22754          */
   22755         boolean mAlwaysConsumeNavBar;
   22756 
   22757         /**
   22758          * The internal insets given by this window.  This value is
   22759          * supplied by the client (through
   22760          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
   22761          * be given to the window manager when changed to be used in laying
   22762          * out windows behind it.
   22763          */
   22764         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
   22765                 = new ViewTreeObserver.InternalInsetsInfo();
   22766 
   22767         /**
   22768          * Set to true when mGivenInternalInsets is non-empty.
   22769          */
   22770         boolean mHasNonEmptyGivenInternalInsets;
   22771 
   22772         /**
   22773          * All views in the window's hierarchy that serve as scroll containers,
   22774          * used to determine if the window can be resized or must be panned
   22775          * to adjust for a soft input area.
   22776          */
   22777         final ArrayList<View> mScrollContainers = new ArrayList<View>();
   22778 
   22779         final KeyEvent.DispatcherState mKeyDispatchState
   22780                 = new KeyEvent.DispatcherState();
   22781 
   22782         /**
   22783          * Indicates whether the view's window currently has the focus.
   22784          */
   22785         boolean mHasWindowFocus;
   22786 
   22787         /**
   22788          * The current visibility of the window.
   22789          */
   22790         int mWindowVisibility;
   22791 
   22792         /**
   22793          * Indicates the time at which drawing started to occur.
   22794          */
   22795         long mDrawingTime;
   22796 
   22797         /**
   22798          * Indicates whether or not ignoring the DIRTY_MASK flags.
   22799          */
   22800         boolean mIgnoreDirtyState;
   22801 
   22802         /**
   22803          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
   22804          * to avoid clearing that flag prematurely.
   22805          */
   22806         boolean mSetIgnoreDirtyState = false;
   22807 
   22808         /**
   22809          * Indicates whether the view's window is currently in touch mode.
   22810          */
   22811         boolean mInTouchMode;
   22812 
   22813         /**
   22814          * Indicates whether the view has requested unbuffered input dispatching for the current
   22815          * event stream.
   22816          */
   22817         boolean mUnbufferedDispatchRequested;
   22818 
   22819         /**
   22820          * Indicates that ViewAncestor should trigger a global layout change
   22821          * the next time it performs a traversal
   22822          */
   22823         boolean mRecomputeGlobalAttributes;
   22824 
   22825         /**
   22826          * Always report new attributes at next traversal.
   22827          */
   22828         boolean mForceReportNewAttributes;
   22829 
   22830         /**
   22831          * Set during a traveral if any views want to keep the screen on.
   22832          */
   22833         boolean mKeepScreenOn;
   22834 
   22835         /**
   22836          * Set during a traveral if the light center needs to be updated.
   22837          */
   22838         boolean mNeedsUpdateLightCenter;
   22839 
   22840         /**
   22841          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
   22842          */
   22843         int mSystemUiVisibility;
   22844 
   22845         /**
   22846          * Hack to force certain system UI visibility flags to be cleared.
   22847          */
   22848         int mDisabledSystemUiVisibility;
   22849 
   22850         /**
   22851          * Last global system UI visibility reported by the window manager.
   22852          */
   22853         int mGlobalSystemUiVisibility;
   22854 
   22855         /**
   22856          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
   22857          * attached.
   22858          */
   22859         boolean mHasSystemUiListeners;
   22860 
   22861         /**
   22862          * Set if the window has requested to extend into the overscan region
   22863          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
   22864          */
   22865         boolean mOverscanRequested;
   22866 
   22867         /**
   22868          * Set if the visibility of any views has changed.
   22869          */
   22870         boolean mViewVisibilityChanged;
   22871 
   22872         /**
   22873          * Set to true if a view has been scrolled.
   22874          */
   22875         boolean mViewScrollChanged;
   22876 
   22877         /**
   22878          * Set to true if high contrast mode enabled
   22879          */
   22880         boolean mHighContrastText;
   22881 
   22882         /**
   22883          * Set to true if a pointer event is currently being handled.
   22884          */
   22885         boolean mHandlingPointerEvent;
   22886 
   22887         /**
   22888          * Global to the view hierarchy used as a temporary for dealing with
   22889          * x/y points in the transparent region computations.
   22890          */
   22891         final int[] mTransparentLocation = new int[2];
   22892 
   22893         /**
   22894          * Global to the view hierarchy used as a temporary for dealing with
   22895          * x/y points in the ViewGroup.invalidateChild implementation.
   22896          */
   22897         final int[] mInvalidateChildLocation = new int[2];
   22898 
   22899         /**
   22900          * Global to the view hierarchy used as a temporary for dealng with
   22901          * computing absolute on-screen location.
   22902          */
   22903         final int[] mTmpLocation = new int[2];
   22904 
   22905         /**
   22906          * Global to the view hierarchy used as a temporary for dealing with
   22907          * x/y location when view is transformed.
   22908          */
   22909         final float[] mTmpTransformLocation = new float[2];
   22910 
   22911         /**
   22912          * The view tree observer used to dispatch global events like
   22913          * layout, pre-draw, touch mode change, etc.
   22914          */
   22915         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
   22916 
   22917         /**
   22918          * A Canvas used by the view hierarchy to perform bitmap caching.
   22919          */
   22920         Canvas mCanvas;
   22921 
   22922         /**
   22923          * The view root impl.
   22924          */
   22925         final ViewRootImpl mViewRootImpl;
   22926 
   22927         /**
   22928          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
   22929          * handler can be used to pump events in the UI events queue.
   22930          */
   22931         final Handler mHandler;
   22932 
   22933         /**
   22934          * Temporary for use in computing invalidate rectangles while
   22935          * calling up the hierarchy.
   22936          */
   22937         final Rect mTmpInvalRect = new Rect();
   22938 
   22939         /**
   22940          * Temporary for use in computing hit areas with transformed views
   22941          */
   22942         final RectF mTmpTransformRect = new RectF();
   22943 
   22944         /**
   22945          * Temporary for use in computing hit areas with transformed views
   22946          */
   22947         final RectF mTmpTransformRect1 = new RectF();
   22948 
   22949         /**
   22950          * Temporary list of rectanges.
   22951          */
   22952         final List<RectF> mTmpRectList = new ArrayList<>();
   22953 
   22954         /**
   22955          * Temporary for use in transforming invalidation rect
   22956          */
   22957         final Matrix mTmpMatrix = new Matrix();
   22958 
   22959         /**
   22960          * Temporary for use in transforming invalidation rect
   22961          */
   22962         final Transformation mTmpTransformation = new Transformation();
   22963 
   22964         /**
   22965          * Temporary for use in querying outlines from OutlineProviders
   22966          */
   22967         final Outline mTmpOutline = new Outline();
   22968 
   22969         /**
   22970          * Temporary list for use in collecting focusable descendents of a view.
   22971          */
   22972         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
   22973 
   22974         /**
   22975          * The id of the window for accessibility purposes.
   22976          */
   22977         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
   22978 
   22979         /**
   22980          * Flags related to accessibility processing.
   22981          *
   22982          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   22983          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
   22984          */
   22985         int mAccessibilityFetchFlags;
   22986 
   22987         /**
   22988          * The drawable for highlighting accessibility focus.
   22989          */
   22990         Drawable mAccessibilityFocusDrawable;
   22991 
   22992         /**
   22993          * Show where the margins, bounds and layout bounds are for each view.
   22994          */
   22995         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
   22996 
   22997         /**
   22998          * Point used to compute visible regions.
   22999          */
   23000         final Point mPoint = new Point();
   23001 
   23002         /**
   23003          * Used to track which View originated a requestLayout() call, used when
   23004          * requestLayout() is called during layout.
   23005          */
   23006         View mViewRequestingLayout;
   23007 
   23008         /**
   23009          * Used to track views that need (at least) a partial relayout at their current size
   23010          * during the next traversal.
   23011          */
   23012         List<View> mPartialLayoutViews = new ArrayList<>();
   23013 
   23014         /**
   23015          * Swapped with mPartialLayoutViews during layout to avoid concurrent
   23016          * modification. Lazily assigned during ViewRootImpl layout.
   23017          */
   23018         List<View> mEmptyPartialLayoutViews;
   23019 
   23020         /**
   23021          * Used to track the identity of the current drag operation.
   23022          */
   23023         IBinder mDragToken;
   23024 
   23025         /**
   23026          * The drag shadow surface for the current drag operation.
   23027          */
   23028         public Surface mDragSurface;
   23029 
   23030         /**
   23031          * Creates a new set of attachment information with the specified
   23032          * events handler and thread.
   23033          *
   23034          * @param handler the events handler the view must use
   23035          */
   23036         AttachInfo(IWindowSession session, IWindow window, Display display,
   23037                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
   23038             mSession = session;
   23039             mWindow = window;
   23040             mWindowToken = window.asBinder();
   23041             mDisplay = display;
   23042             mViewRootImpl = viewRootImpl;
   23043             mHandler = handler;
   23044             mRootCallbacks = effectPlayer;
   23045         }
   23046     }
   23047 
   23048     /**
   23049      * <p>ScrollabilityCache holds various fields used by a View when scrolling
   23050      * is supported. This avoids keeping too many unused fields in most
   23051      * instances of View.</p>
   23052      */
   23053     private static class ScrollabilityCache implements Runnable {
   23054 
   23055         /**
   23056          * Scrollbars are not visible
   23057          */
   23058         public static final int OFF = 0;
   23059 
   23060         /**
   23061          * Scrollbars are visible
   23062          */
   23063         public static final int ON = 1;
   23064 
   23065         /**
   23066          * Scrollbars are fading away
   23067          */
   23068         public static final int FADING = 2;
   23069 
   23070         public boolean fadeScrollBars;
   23071 
   23072         public int fadingEdgeLength;
   23073         public int scrollBarDefaultDelayBeforeFade;
   23074         public int scrollBarFadeDuration;
   23075 
   23076         public int scrollBarSize;
   23077         public ScrollBarDrawable scrollBar;
   23078         public float[] interpolatorValues;
   23079         public View host;
   23080 
   23081         public final Paint paint;
   23082         public final Matrix matrix;
   23083         public Shader shader;
   23084 
   23085         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
   23086 
   23087         private static final float[] OPAQUE = { 255 };
   23088         private static final float[] TRANSPARENT = { 0.0f };
   23089 
   23090         /**
   23091          * When fading should start. This time moves into the future every time
   23092          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
   23093          */
   23094         public long fadeStartTime;
   23095 
   23096 
   23097         /**
   23098          * The current state of the scrollbars: ON, OFF, or FADING
   23099          */
   23100         public int state = OFF;
   23101 
   23102         private int mLastColor;
   23103 
   23104         public final Rect mScrollBarBounds = new Rect();
   23105 
   23106         public static final int NOT_DRAGGING = 0;
   23107         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
   23108         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
   23109         public int mScrollBarDraggingState = NOT_DRAGGING;
   23110 
   23111         public float mScrollBarDraggingPos = 0;
   23112 
   23113         public ScrollabilityCache(ViewConfiguration configuration, View host) {
   23114             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
   23115             scrollBarSize = configuration.getScaledScrollBarSize();
   23116             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
   23117             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
   23118 
   23119             paint = new Paint();
   23120             matrix = new Matrix();
   23121             // use use a height of 1, and then wack the matrix each time we
   23122             // actually use it.
   23123             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   23124             paint.setShader(shader);
   23125             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   23126 
   23127             this.host = host;
   23128         }
   23129 
   23130         public void setFadeColor(int color) {
   23131             if (color != mLastColor) {
   23132                 mLastColor = color;
   23133 
   23134                 if (color != 0) {
   23135                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
   23136                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
   23137                     paint.setShader(shader);
   23138                     // Restore the default transfer mode (src_over)
   23139                     paint.setXfermode(null);
   23140                 } else {
   23141                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   23142                     paint.setShader(shader);
   23143                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   23144                 }
   23145             }
   23146         }
   23147 
   23148         public void run() {
   23149             long now = AnimationUtils.currentAnimationTimeMillis();
   23150             if (now >= fadeStartTime) {
   23151 
   23152                 // the animation fades the scrollbars out by changing
   23153                 // the opacity (alpha) from fully opaque to fully
   23154                 // transparent
   23155                 int nextFrame = (int) now;
   23156                 int framesCount = 0;
   23157 
   23158                 Interpolator interpolator = scrollBarInterpolator;
   23159 
   23160                 // Start opaque
   23161                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
   23162 
   23163                 // End transparent
   23164                 nextFrame += scrollBarFadeDuration;
   23165                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
   23166 
   23167                 state = FADING;
   23168 
   23169                 // Kick off the fade animation
   23170                 host.invalidate(true);
   23171             }
   23172         }
   23173     }
   23174 
   23175     /**
   23176      * Resuable callback for sending
   23177      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   23178      */
   23179     private class SendViewScrolledAccessibilityEvent implements Runnable {
   23180         public volatile boolean mIsPending;
   23181 
   23182         public void run() {
   23183             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
   23184             mIsPending = false;
   23185         }
   23186     }
   23187 
   23188     /**
   23189      * <p>
   23190      * This class represents a delegate that can be registered in a {@link View}
   23191      * to enhance accessibility support via composition rather via inheritance.
   23192      * It is specifically targeted to widget developers that extend basic View
   23193      * classes i.e. classes in package android.view, that would like their
   23194      * applications to be backwards compatible.
   23195      * </p>
   23196      * <div class="special reference">
   23197      * <h3>Developer Guides</h3>
   23198      * <p>For more information about making applications accessible, read the
   23199      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
   23200      * developer guide.</p>
   23201      * </div>
   23202      * <p>
   23203      * A scenario in which a developer would like to use an accessibility delegate
   23204      * is overriding a method introduced in a later API version then the minimal API
   23205      * version supported by the application. For example, the method
   23206      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
   23207      * in API version 4 when the accessibility APIs were first introduced. If a
   23208      * developer would like his application to run on API version 4 devices (assuming
   23209      * all other APIs used by the application are version 4 or lower) and take advantage
   23210      * of this method, instead of overriding the method which would break the application's
   23211      * backwards compatibility, he can override the corresponding method in this
   23212      * delegate and register the delegate in the target View if the API version of
   23213      * the system is high enough i.e. the API version is same or higher to the API
   23214      * version that introduced
   23215      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
   23216      * </p>
   23217      * <p>
   23218      * Here is an example implementation:
   23219      * </p>
   23220      * <code><pre><p>
   23221      * if (Build.VERSION.SDK_INT >= 14) {
   23222      *     // If the API version is equal of higher than the version in
   23223      *     // which onInitializeAccessibilityNodeInfo was introduced we
   23224      *     // register a delegate with a customized implementation.
   23225      *     View view = findViewById(R.id.view_id);
   23226      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
   23227      *         public void onInitializeAccessibilityNodeInfo(View host,
   23228      *                 AccessibilityNodeInfo info) {
   23229      *             // Let the default implementation populate the info.
   23230      *             super.onInitializeAccessibilityNodeInfo(host, info);
   23231      *             // Set some other information.
   23232      *             info.setEnabled(host.isEnabled());
   23233      *         }
   23234      *     });
   23235      * }
   23236      * </code></pre></p>
   23237      * <p>
   23238      * This delegate contains methods that correspond to the accessibility methods
   23239      * in View. If a delegate has been specified the implementation in View hands
   23240      * off handling to the corresponding method in this delegate. The default
   23241      * implementation the delegate methods behaves exactly as the corresponding
   23242      * method in View for the case of no accessibility delegate been set. Hence,
   23243      * to customize the behavior of a View method, clients can override only the
   23244      * corresponding delegate method without altering the behavior of the rest
   23245      * accessibility related methods of the host view.
   23246      * </p>
   23247      * <p>
   23248      * <strong>Note:</strong> On platform versions prior to
   23249      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
   23250      * views in the {@code android.widget.*} package are called <i>before</i>
   23251      * host methods. This prevents certain properties such as class name from
   23252      * being modified by overriding
   23253      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
   23254      * as any changes will be overwritten by the host class.
   23255      * <p>
   23256      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
   23257      * methods are called <i>after</i> host methods, which all properties to be
   23258      * modified without being overwritten by the host class.
   23259      */
   23260     public static class AccessibilityDelegate {
   23261 
   23262         /**
   23263          * Sends an accessibility event of the given type. If accessibility is not
   23264          * enabled this method has no effect.
   23265          * <p>
   23266          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
   23267          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
   23268          * been set.
   23269          * </p>
   23270          *
   23271          * @param host The View hosting the delegate.
   23272          * @param eventType The type of the event to send.
   23273          *
   23274          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
   23275          */
   23276         public void sendAccessibilityEvent(View host, int eventType) {
   23277             host.sendAccessibilityEventInternal(eventType);
   23278         }
   23279 
   23280         /**
   23281          * Performs the specified accessibility action on the view. For
   23282          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   23283          * <p>
   23284          * The default implementation behaves as
   23285          * {@link View#performAccessibilityAction(int, Bundle)
   23286          *  View#performAccessibilityAction(int, Bundle)} for the case of
   23287          *  no accessibility delegate been set.
   23288          * </p>
   23289          *
   23290          * @param action The action to perform.
   23291          * @return Whether the action was performed.
   23292          *
   23293          * @see View#performAccessibilityAction(int, Bundle)
   23294          *      View#performAccessibilityAction(int, Bundle)
   23295          */
   23296         public boolean performAccessibilityAction(View host, int action, Bundle args) {
   23297             return host.performAccessibilityActionInternal(action, args);
   23298         }
   23299 
   23300         /**
   23301          * Sends an accessibility event. This method behaves exactly as
   23302          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
   23303          * empty {@link AccessibilityEvent} and does not perform a check whether
   23304          * accessibility is enabled.
   23305          * <p>
   23306          * The default implementation behaves as
   23307          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   23308          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
   23309          * the case of no accessibility delegate been set.
   23310          * </p>
   23311          *
   23312          * @param host The View hosting the delegate.
   23313          * @param event The event to send.
   23314          *
   23315          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   23316          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   23317          */
   23318         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
   23319             host.sendAccessibilityEventUncheckedInternal(event);
   23320         }
   23321 
   23322         /**
   23323          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
   23324          * to its children for adding their text content to the event.
   23325          * <p>
   23326          * The default implementation behaves as
   23327          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   23328          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
   23329          * the case of no accessibility delegate been set.
   23330          * </p>
   23331          *
   23332          * @param host The View hosting the delegate.
   23333          * @param event The event.
   23334          * @return True if the event population was completed.
   23335          *
   23336          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   23337          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   23338          */
   23339         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   23340             return host.dispatchPopulateAccessibilityEventInternal(event);
   23341         }
   23342 
   23343         /**
   23344          * Gives a chance to the host View to populate the accessibility event with its
   23345          * text content.
   23346          * <p>
   23347          * The default implementation behaves as
   23348          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
   23349          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
   23350          * the case of no accessibility delegate been set.
   23351          * </p>
   23352          *
   23353          * @param host The View hosting the delegate.
   23354          * @param event The accessibility event which to populate.
   23355          *
   23356          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
   23357          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
   23358          */
   23359         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   23360             host.onPopulateAccessibilityEventInternal(event);
   23361         }
   23362 
   23363         /**
   23364          * Initializes an {@link AccessibilityEvent} with information about the
   23365          * the host View which is the event source.
   23366          * <p>
   23367          * The default implementation behaves as
   23368          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
   23369          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
   23370          * the case of no accessibility delegate been set.
   23371          * </p>
   23372          *
   23373          * @param host The View hosting the delegate.
   23374          * @param event The event to initialize.
   23375          *
   23376          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
   23377          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
   23378          */
   23379         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
   23380             host.onInitializeAccessibilityEventInternal(event);
   23381         }
   23382 
   23383         /**
   23384          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
   23385          * <p>
   23386          * The default implementation behaves as
   23387          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   23388          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
   23389          * the case of no accessibility delegate been set.
   23390          * </p>
   23391          *
   23392          * @param host The View hosting the delegate.
   23393          * @param info The instance to initialize.
   23394          *
   23395          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   23396          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   23397          */
   23398         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
   23399             host.onInitializeAccessibilityNodeInfoInternal(info);
   23400         }
   23401 
   23402         /**
   23403          * Called when a child of the host View has requested sending an
   23404          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
   23405          * to augment the event.
   23406          * <p>
   23407          * The default implementation behaves as
   23408          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   23409          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
   23410          * the case of no accessibility delegate been set.
   23411          * </p>
   23412          *
   23413          * @param host The View hosting the delegate.
   23414          * @param child The child which requests sending the event.
   23415          * @param event The event to be sent.
   23416          * @return True if the event should be sent
   23417          *
   23418          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   23419          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   23420          */
   23421         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
   23422                 AccessibilityEvent event) {
   23423             return host.onRequestSendAccessibilityEventInternal(child, event);
   23424         }
   23425 
   23426         /**
   23427          * Gets the provider for managing a virtual view hierarchy rooted at this View
   23428          * and reported to {@link android.accessibilityservice.AccessibilityService}s
   23429          * that explore the window content.
   23430          * <p>
   23431          * The default implementation behaves as
   23432          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
   23433          * the case of no accessibility delegate been set.
   23434          * </p>
   23435          *
   23436          * @return The provider.
   23437          *
   23438          * @see AccessibilityNodeProvider
   23439          */
   23440         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
   23441             return null;
   23442         }
   23443 
   23444         /**
   23445          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
   23446          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   23447          * This method is responsible for obtaining an accessibility node info from a
   23448          * pool of reusable instances and calling
   23449          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
   23450          * view to initialize the former.
   23451          * <p>
   23452          * <strong>Note:</strong> The client is responsible for recycling the obtained
   23453          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
   23454          * creation.
   23455          * </p>
   23456          * <p>
   23457          * The default implementation behaves as
   23458          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
   23459          * the case of no accessibility delegate been set.
   23460          * </p>
   23461          * @return A populated {@link AccessibilityNodeInfo}.
   23462          *
   23463          * @see AccessibilityNodeInfo
   23464          *
   23465          * @hide
   23466          */
   23467         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
   23468             return host.createAccessibilityNodeInfoInternal();
   23469         }
   23470     }
   23471 
   23472     private class MatchIdPredicate implements Predicate<View> {
   23473         public int mId;
   23474 
   23475         @Override
   23476         public boolean apply(View view) {
   23477             return (view.mID == mId);
   23478         }
   23479     }
   23480 
   23481     private class MatchLabelForPredicate implements Predicate<View> {
   23482         private int mLabeledId;
   23483 
   23484         @Override
   23485         public boolean apply(View view) {
   23486             return (view.mLabelForId == mLabeledId);
   23487         }
   23488     }
   23489 
   23490     private class SendViewStateChangedAccessibilityEvent implements Runnable {
   23491         private int mChangeTypes = 0;
   23492         private boolean mPosted;
   23493         private boolean mPostedWithDelay;
   23494         private long mLastEventTimeMillis;
   23495 
   23496         @Override
   23497         public void run() {
   23498             mPosted = false;
   23499             mPostedWithDelay = false;
   23500             mLastEventTimeMillis = SystemClock.uptimeMillis();
   23501             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   23502                 final AccessibilityEvent event = AccessibilityEvent.obtain();
   23503                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
   23504                 event.setContentChangeTypes(mChangeTypes);
   23505                 sendAccessibilityEventUnchecked(event);
   23506             }
   23507             mChangeTypes = 0;
   23508         }
   23509 
   23510         public void runOrPost(int changeType) {
   23511             mChangeTypes |= changeType;
   23512 
   23513             // If this is a live region or the child of a live region, collect
   23514             // all events from this frame and send them on the next frame.
   23515             if (inLiveRegion()) {
   23516                 // If we're already posted with a delay, remove that.
   23517                 if (mPostedWithDelay) {
   23518                     removeCallbacks(this);
   23519                     mPostedWithDelay = false;
   23520                 }
   23521                 // Only post if we're not already posted.
   23522                 if (!mPosted) {
   23523                     post(this);
   23524                     mPosted = true;
   23525                 }
   23526                 return;
   23527             }
   23528 
   23529             if (mPosted) {
   23530                 return;
   23531             }
   23532 
   23533             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
   23534             final long minEventIntevalMillis =
   23535                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
   23536             if (timeSinceLastMillis >= minEventIntevalMillis) {
   23537                 removeCallbacks(this);
   23538                 run();
   23539             } else {
   23540                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
   23541                 mPostedWithDelay = true;
   23542             }
   23543         }
   23544     }
   23545 
   23546     private boolean inLiveRegion() {
   23547         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
   23548             return true;
   23549         }
   23550 
   23551         ViewParent parent = getParent();
   23552         while (parent instanceof View) {
   23553             if (((View) parent).getAccessibilityLiveRegion()
   23554                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
   23555                 return true;
   23556             }
   23557             parent = parent.getParent();
   23558         }
   23559 
   23560         return false;
   23561     }
   23562 
   23563     /**
   23564      * Dump all private flags in readable format, useful for documentation and
   23565      * sanity checking.
   23566      */
   23567     private static void dumpFlags() {
   23568         final HashMap<String, String> found = Maps.newHashMap();
   23569         try {
   23570             for (Field field : View.class.getDeclaredFields()) {
   23571                 final int modifiers = field.getModifiers();
   23572                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
   23573                     if (field.getType().equals(int.class)) {
   23574                         final int value = field.getInt(null);
   23575                         dumpFlag(found, field.getName(), value);
   23576                     } else if (field.getType().equals(int[].class)) {
   23577                         final int[] values = (int[]) field.get(null);
   23578                         for (int i = 0; i < values.length; i++) {
   23579                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
   23580                         }
   23581                     }
   23582                 }
   23583             }
   23584         } catch (IllegalAccessException e) {
   23585             throw new RuntimeException(e);
   23586         }
   23587 
   23588         final ArrayList<String> keys = Lists.newArrayList();
   23589         keys.addAll(found.keySet());
   23590         Collections.sort(keys);
   23591         for (String key : keys) {
   23592             Log.d(VIEW_LOG_TAG, found.get(key));
   23593         }
   23594     }
   23595 
   23596     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
   23597         // Sort flags by prefix, then by bits, always keeping unique keys
   23598         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
   23599         final int prefix = name.indexOf('_');
   23600         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
   23601         final String output = bits + " " + name;
   23602         found.put(key, output);
   23603     }
   23604 
   23605     /** {@hide} */
   23606     public void encode(@NonNull ViewHierarchyEncoder stream) {
   23607         stream.beginObject(this);
   23608         encodeProperties(stream);
   23609         stream.endObject();
   23610     }
   23611 
   23612     /** {@hide} */
   23613     @CallSuper
   23614     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
   23615         Object resolveId = ViewDebug.resolveId(getContext(), mID);
   23616         if (resolveId instanceof String) {
   23617             stream.addProperty("id", (String) resolveId);
   23618         } else {
   23619             stream.addProperty("id", mID);
   23620         }
   23621 
   23622         stream.addProperty("misc:transformation.alpha",
   23623                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
   23624         stream.addProperty("misc:transitionName", getTransitionName());
   23625 
   23626         // layout
   23627         stream.addProperty("layout:left", mLeft);
   23628         stream.addProperty("layout:right", mRight);
   23629         stream.addProperty("layout:top", mTop);
   23630         stream.addProperty("layout:bottom", mBottom);
   23631         stream.addProperty("layout:width", getWidth());
   23632         stream.addProperty("layout:height", getHeight());
   23633         stream.addProperty("layout:layoutDirection", getLayoutDirection());
   23634         stream.addProperty("layout:layoutRtl", isLayoutRtl());
   23635         stream.addProperty("layout:hasTransientState", hasTransientState());
   23636         stream.addProperty("layout:baseline", getBaseline());
   23637 
   23638         // layout params
   23639         ViewGroup.LayoutParams layoutParams = getLayoutParams();
   23640         if (layoutParams != null) {
   23641             stream.addPropertyKey("layoutParams");
   23642             layoutParams.encode(stream);
   23643         }
   23644 
   23645         // scrolling
   23646         stream.addProperty("scrolling:scrollX", mScrollX);
   23647         stream.addProperty("scrolling:scrollY", mScrollY);
   23648 
   23649         // padding
   23650         stream.addProperty("padding:paddingLeft", mPaddingLeft);
   23651         stream.addProperty("padding:paddingRight", mPaddingRight);
   23652         stream.addProperty("padding:paddingTop", mPaddingTop);
   23653         stream.addProperty("padding:paddingBottom", mPaddingBottom);
   23654         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
   23655         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
   23656         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
   23657         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
   23658         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
   23659 
   23660         // measurement
   23661         stream.addProperty("measurement:minHeight", mMinHeight);
   23662         stream.addProperty("measurement:minWidth", mMinWidth);
   23663         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
   23664         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
   23665 
   23666         // drawing
   23667         stream.addProperty("drawing:elevation", getElevation());
   23668         stream.addProperty("drawing:translationX", getTranslationX());
   23669         stream.addProperty("drawing:translationY", getTranslationY());
   23670         stream.addProperty("drawing:translationZ", getTranslationZ());
   23671         stream.addProperty("drawing:rotation", getRotation());
   23672         stream.addProperty("drawing:rotationX", getRotationX());
   23673         stream.addProperty("drawing:rotationY", getRotationY());
   23674         stream.addProperty("drawing:scaleX", getScaleX());
   23675         stream.addProperty("drawing:scaleY", getScaleY());
   23676         stream.addProperty("drawing:pivotX", getPivotX());
   23677         stream.addProperty("drawing:pivotY", getPivotY());
   23678         stream.addProperty("drawing:opaque", isOpaque());
   23679         stream.addProperty("drawing:alpha", getAlpha());
   23680         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
   23681         stream.addProperty("drawing:shadow", hasShadow());
   23682         stream.addProperty("drawing:solidColor", getSolidColor());
   23683         stream.addProperty("drawing:layerType", mLayerType);
   23684         stream.addProperty("drawing:willNotDraw", willNotDraw());
   23685         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
   23686         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
   23687         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
   23688         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
   23689 
   23690         // focus
   23691         stream.addProperty("focus:hasFocus", hasFocus());
   23692         stream.addProperty("focus:isFocused", isFocused());
   23693         stream.addProperty("focus:isFocusable", isFocusable());
   23694         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
   23695 
   23696         stream.addProperty("misc:clickable", isClickable());
   23697         stream.addProperty("misc:pressed", isPressed());
   23698         stream.addProperty("misc:selected", isSelected());
   23699         stream.addProperty("misc:touchMode", isInTouchMode());
   23700         stream.addProperty("misc:hovered", isHovered());
   23701         stream.addProperty("misc:activated", isActivated());
   23702 
   23703         stream.addProperty("misc:visibility", getVisibility());
   23704         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
   23705         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
   23706 
   23707         stream.addProperty("misc:enabled", isEnabled());
   23708         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
   23709         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
   23710 
   23711         // theme attributes
   23712         Resources.Theme theme = getContext().getTheme();
   23713         if (theme != null) {
   23714             stream.addPropertyKey("theme");
   23715             theme.encode(stream);
   23716         }
   23717 
   23718         // view attribute information
   23719         int n = mAttributes != null ? mAttributes.length : 0;
   23720         stream.addProperty("meta:__attrCount__", n/2);
   23721         for (int i = 0; i < n; i += 2) {
   23722             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
   23723         }
   23724 
   23725         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
   23726 
   23727         // text
   23728         stream.addProperty("text:textDirection", getTextDirection());
   23729         stream.addProperty("text:textAlignment", getTextAlignment());
   23730 
   23731         // accessibility
   23732         CharSequence contentDescription = getContentDescription();
   23733         stream.addProperty("accessibility:contentDescription",
   23734                 contentDescription == null ? "" : contentDescription.toString());
   23735         stream.addProperty("accessibility:labelFor", getLabelFor());
   23736         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
   23737     }
   23738 }
   23739