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      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
    824      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
    825      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
    826      * check is implemented for backwards compatibility.
    827      *
    828      * {@hide}
    829      */
    830     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
    831 
    832     /**
    833      * Prior to N, when drag enters into child of a view that has already received an
    834      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
    835      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
    836      * false from its event handler for these events.
    837      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
    838      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
    839      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
    840      */
    841     static boolean sCascadedDragDrop;
    842 
    843     /**
    844      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
    845      * calling setFlags.
    846      */
    847     private static final int NOT_FOCUSABLE = 0x00000000;
    848 
    849     /**
    850      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
    851      * setFlags.
    852      */
    853     private static final int FOCUSABLE = 0x00000001;
    854 
    855     /**
    856      * Mask for use with setFlags indicating bits used for focus.
    857      */
    858     private static final int FOCUSABLE_MASK = 0x00000001;
    859 
    860     /**
    861      * This view will adjust its padding to fit sytem windows (e.g. status bar)
    862      */
    863     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
    864 
    865     /** @hide */
    866     @IntDef({VISIBLE, INVISIBLE, GONE})
    867     @Retention(RetentionPolicy.SOURCE)
    868     public @interface Visibility {}
    869 
    870     /**
    871      * This view is visible.
    872      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    873      * android:visibility}.
    874      */
    875     public static final int VISIBLE = 0x00000000;
    876 
    877     /**
    878      * This view is invisible, but it still takes up space for layout purposes.
    879      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    880      * android:visibility}.
    881      */
    882     public static final int INVISIBLE = 0x00000004;
    883 
    884     /**
    885      * This view is invisible, and it doesn't take any space for layout
    886      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    887      * android:visibility}.
    888      */
    889     public static final int GONE = 0x00000008;
    890 
    891     /**
    892      * Mask for use with setFlags indicating bits used for visibility.
    893      * {@hide}
    894      */
    895     static final int VISIBILITY_MASK = 0x0000000C;
    896 
    897     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
    898 
    899     /**
    900      * This view is enabled. Interpretation varies by subclass.
    901      * Use with ENABLED_MASK when calling setFlags.
    902      * {@hide}
    903      */
    904     static final int ENABLED = 0x00000000;
    905 
    906     /**
    907      * This view is disabled. Interpretation varies by subclass.
    908      * Use with ENABLED_MASK when calling setFlags.
    909      * {@hide}
    910      */
    911     static final int DISABLED = 0x00000020;
    912 
    913    /**
    914     * Mask for use with setFlags indicating bits used for indicating whether
    915     * this view is enabled
    916     * {@hide}
    917     */
    918     static final int ENABLED_MASK = 0x00000020;
    919 
    920     /**
    921      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
    922      * called and further optimizations will be performed. It is okay to have
    923      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
    924      * {@hide}
    925      */
    926     static final int WILL_NOT_DRAW = 0x00000080;
    927 
    928     /**
    929      * Mask for use with setFlags indicating bits used for indicating whether
    930      * this view is will draw
    931      * {@hide}
    932      */
    933     static final int DRAW_MASK = 0x00000080;
    934 
    935     /**
    936      * <p>This view doesn't show scrollbars.</p>
    937      * {@hide}
    938      */
    939     static final int SCROLLBARS_NONE = 0x00000000;
    940 
    941     /**
    942      * <p>This view shows horizontal scrollbars.</p>
    943      * {@hide}
    944      */
    945     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
    946 
    947     /**
    948      * <p>This view shows vertical scrollbars.</p>
    949      * {@hide}
    950      */
    951     static final int SCROLLBARS_VERTICAL = 0x00000200;
    952 
    953     /**
    954      * <p>Mask for use with setFlags indicating bits used for indicating which
    955      * scrollbars are enabled.</p>
    956      * {@hide}
    957      */
    958     static final int SCROLLBARS_MASK = 0x00000300;
    959 
    960     /**
    961      * Indicates that the view should filter touches when its window is obscured.
    962      * Refer to the class comments for more information about this security feature.
    963      * {@hide}
    964      */
    965     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
    966 
    967     /**
    968      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
    969      * that they are optional and should be skipped if the window has
    970      * requested system UI flags that ignore those insets for layout.
    971      */
    972     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
    973 
    974     /**
    975      * <p>This view doesn't show fading edges.</p>
    976      * {@hide}
    977      */
    978     static final int FADING_EDGE_NONE = 0x00000000;
    979 
    980     /**
    981      * <p>This view shows horizontal fading edges.</p>
    982      * {@hide}
    983      */
    984     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
    985 
    986     /**
    987      * <p>This view shows vertical fading edges.</p>
    988      * {@hide}
    989      */
    990     static final int FADING_EDGE_VERTICAL = 0x00002000;
    991 
    992     /**
    993      * <p>Mask for use with setFlags indicating bits used for indicating which
    994      * fading edges are enabled.</p>
    995      * {@hide}
    996      */
    997     static final int FADING_EDGE_MASK = 0x00003000;
    998 
    999     /**
   1000      * <p>Indicates this view can be clicked. When clickable, a View reacts
   1001      * to clicks by notifying the OnClickListener.<p>
   1002      * {@hide}
   1003      */
   1004     static final int CLICKABLE = 0x00004000;
   1005 
   1006     /**
   1007      * <p>Indicates this view is caching its drawing into a bitmap.</p>
   1008      * {@hide}
   1009      */
   1010     static final int DRAWING_CACHE_ENABLED = 0x00008000;
   1011 
   1012     /**
   1013      * <p>Indicates that no icicle should be saved for this view.<p>
   1014      * {@hide}
   1015      */
   1016     static final int SAVE_DISABLED = 0x000010000;
   1017 
   1018     /**
   1019      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
   1020      * property.</p>
   1021      * {@hide}
   1022      */
   1023     static final int SAVE_DISABLED_MASK = 0x000010000;
   1024 
   1025     /**
   1026      * <p>Indicates that no drawing cache should ever be created for this view.<p>
   1027      * {@hide}
   1028      */
   1029     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
   1030 
   1031     /**
   1032      * <p>Indicates this view can take / keep focus when int touch mode.</p>
   1033      * {@hide}
   1034      */
   1035     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
   1036 
   1037     /** @hide */
   1038     @Retention(RetentionPolicy.SOURCE)
   1039     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
   1040     public @interface DrawingCacheQuality {}
   1041 
   1042     /**
   1043      * <p>Enables low quality mode for the drawing cache.</p>
   1044      */
   1045     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
   1046 
   1047     /**
   1048      * <p>Enables high quality mode for the drawing cache.</p>
   1049      */
   1050     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
   1051 
   1052     /**
   1053      * <p>Enables automatic quality mode for the drawing cache.</p>
   1054      */
   1055     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
   1056 
   1057     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
   1058             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
   1059     };
   1060 
   1061     /**
   1062      * <p>Mask for use with setFlags indicating bits used for the cache
   1063      * quality property.</p>
   1064      * {@hide}
   1065      */
   1066     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
   1067 
   1068     /**
   1069      * <p>
   1070      * Indicates this view can be long clicked. When long clickable, a View
   1071      * reacts to long clicks by notifying the OnLongClickListener or showing a
   1072      * context menu.
   1073      * </p>
   1074      * {@hide}
   1075      */
   1076     static final int LONG_CLICKABLE = 0x00200000;
   1077 
   1078     /**
   1079      * <p>Indicates that this view gets its drawable states from its direct parent
   1080      * and ignores its original internal states.</p>
   1081      *
   1082      * @hide
   1083      */
   1084     static final int DUPLICATE_PARENT_STATE = 0x00400000;
   1085 
   1086     /**
   1087      * <p>
   1088      * Indicates this view can be context clicked. When context clickable, a View reacts to a
   1089      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
   1090      * OnContextClickListener.
   1091      * </p>
   1092      * {@hide}
   1093      */
   1094     static final int CONTEXT_CLICKABLE = 0x00800000;
   1095 
   1096 
   1097     /** @hide */
   1098     @IntDef({
   1099         SCROLLBARS_INSIDE_OVERLAY,
   1100         SCROLLBARS_INSIDE_INSET,
   1101         SCROLLBARS_OUTSIDE_OVERLAY,
   1102         SCROLLBARS_OUTSIDE_INSET
   1103     })
   1104     @Retention(RetentionPolicy.SOURCE)
   1105     public @interface ScrollBarStyle {}
   1106 
   1107     /**
   1108      * The scrollbar style to display the scrollbars inside the content area,
   1109      * without increasing the padding. The scrollbars will be overlaid with
   1110      * translucency on the view's content.
   1111      */
   1112     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
   1113 
   1114     /**
   1115      * The scrollbar style to display the scrollbars inside the padded area,
   1116      * increasing the padding of the view. The scrollbars will not overlap the
   1117      * content area of the view.
   1118      */
   1119     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
   1120 
   1121     /**
   1122      * The scrollbar style to display the scrollbars at the edge of the view,
   1123      * without increasing the padding. The scrollbars will be overlaid with
   1124      * translucency.
   1125      */
   1126     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
   1127 
   1128     /**
   1129      * The scrollbar style to display the scrollbars at the edge of the view,
   1130      * increasing the padding of the view. The scrollbars will only overlap the
   1131      * background, if any.
   1132      */
   1133     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
   1134 
   1135     /**
   1136      * Mask to check if the scrollbar style is overlay or inset.
   1137      * {@hide}
   1138      */
   1139     static final int SCROLLBARS_INSET_MASK = 0x01000000;
   1140 
   1141     /**
   1142      * Mask to check if the scrollbar style is inside or outside.
   1143      * {@hide}
   1144      */
   1145     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
   1146 
   1147     /**
   1148      * Mask for scrollbar style.
   1149      * {@hide}
   1150      */
   1151     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
   1152 
   1153     /**
   1154      * View flag indicating that the screen should remain on while the
   1155      * window containing this view is visible to the user.  This effectively
   1156      * takes care of automatically setting the WindowManager's
   1157      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
   1158      */
   1159     public static final int KEEP_SCREEN_ON = 0x04000000;
   1160 
   1161     /**
   1162      * View flag indicating whether this view should have sound effects enabled
   1163      * for events such as clicking and touching.
   1164      */
   1165     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
   1166 
   1167     /**
   1168      * View flag indicating whether this view should have haptic feedback
   1169      * enabled for events such as long presses.
   1170      */
   1171     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
   1172 
   1173     /**
   1174      * <p>Indicates that the view hierarchy should stop saving state when
   1175      * it reaches this view.  If state saving is initiated immediately at
   1176      * the view, it will be allowed.
   1177      * {@hide}
   1178      */
   1179     static final int PARENT_SAVE_DISABLED = 0x20000000;
   1180 
   1181     /**
   1182      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
   1183      * {@hide}
   1184      */
   1185     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
   1186 
   1187     /** @hide */
   1188     @IntDef(flag = true,
   1189             value = {
   1190                 FOCUSABLES_ALL,
   1191                 FOCUSABLES_TOUCH_MODE
   1192             })
   1193     @Retention(RetentionPolicy.SOURCE)
   1194     public @interface FocusableMode {}
   1195 
   1196     /**
   1197      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1198      * should add all focusable Views regardless if they are focusable in touch mode.
   1199      */
   1200     public static final int FOCUSABLES_ALL = 0x00000000;
   1201 
   1202     /**
   1203      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1204      * should add only Views focusable in touch mode.
   1205      */
   1206     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
   1207 
   1208     /** @hide */
   1209     @IntDef({
   1210             FOCUS_BACKWARD,
   1211             FOCUS_FORWARD,
   1212             FOCUS_LEFT,
   1213             FOCUS_UP,
   1214             FOCUS_RIGHT,
   1215             FOCUS_DOWN
   1216     })
   1217     @Retention(RetentionPolicy.SOURCE)
   1218     public @interface FocusDirection {}
   1219 
   1220     /** @hide */
   1221     @IntDef({
   1222             FOCUS_LEFT,
   1223             FOCUS_UP,
   1224             FOCUS_RIGHT,
   1225             FOCUS_DOWN
   1226     })
   1227     @Retention(RetentionPolicy.SOURCE)
   1228     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
   1229 
   1230     /**
   1231      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
   1232      * item.
   1233      */
   1234     public static final int FOCUS_BACKWARD = 0x00000001;
   1235 
   1236     /**
   1237      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
   1238      * item.
   1239      */
   1240     public static final int FOCUS_FORWARD = 0x00000002;
   1241 
   1242     /**
   1243      * Use with {@link #focusSearch(int)}. Move focus to the left.
   1244      */
   1245     public static final int FOCUS_LEFT = 0x00000011;
   1246 
   1247     /**
   1248      * Use with {@link #focusSearch(int)}. Move focus up.
   1249      */
   1250     public static final int FOCUS_UP = 0x00000021;
   1251 
   1252     /**
   1253      * Use with {@link #focusSearch(int)}. Move focus to the right.
   1254      */
   1255     public static final int FOCUS_RIGHT = 0x00000042;
   1256 
   1257     /**
   1258      * Use with {@link #focusSearch(int)}. Move focus down.
   1259      */
   1260     public static final int FOCUS_DOWN = 0x00000082;
   1261 
   1262     /**
   1263      * Bits of {@link #getMeasuredWidthAndState()} and
   1264      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
   1265      */
   1266     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
   1267 
   1268     /**
   1269      * Bits of {@link #getMeasuredWidthAndState()} and
   1270      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
   1271      */
   1272     public static final int MEASURED_STATE_MASK = 0xff000000;
   1273 
   1274     /**
   1275      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
   1276      * for functions that combine both width and height into a single int,
   1277      * such as {@link #getMeasuredState()} and the childState argument of
   1278      * {@link #resolveSizeAndState(int, int, int)}.
   1279      */
   1280     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
   1281 
   1282     /**
   1283      * Bit of {@link #getMeasuredWidthAndState()} and
   1284      * {@link #getMeasuredWidthAndState()} that indicates the measured size
   1285      * is smaller that the space the view would like to have.
   1286      */
   1287     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
   1288 
   1289     /**
   1290      * Base View state sets
   1291      */
   1292     // Singles
   1293     /**
   1294      * Indicates the view has no states set. States are used with
   1295      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1296      * view depending on its state.
   1297      *
   1298      * @see android.graphics.drawable.Drawable
   1299      * @see #getDrawableState()
   1300      */
   1301     protected static final int[] EMPTY_STATE_SET;
   1302     /**
   1303      * Indicates the view is enabled. States are used with
   1304      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1305      * view depending on its state.
   1306      *
   1307      * @see android.graphics.drawable.Drawable
   1308      * @see #getDrawableState()
   1309      */
   1310     protected static final int[] ENABLED_STATE_SET;
   1311     /**
   1312      * Indicates the view is focused. States are used with
   1313      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1314      * view depending on its state.
   1315      *
   1316      * @see android.graphics.drawable.Drawable
   1317      * @see #getDrawableState()
   1318      */
   1319     protected static final int[] FOCUSED_STATE_SET;
   1320     /**
   1321      * Indicates the view is selected. States are used with
   1322      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1323      * view depending on its state.
   1324      *
   1325      * @see android.graphics.drawable.Drawable
   1326      * @see #getDrawableState()
   1327      */
   1328     protected static final int[] SELECTED_STATE_SET;
   1329     /**
   1330      * Indicates the view is pressed. States are used with
   1331      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1332      * view depending on its state.
   1333      *
   1334      * @see android.graphics.drawable.Drawable
   1335      * @see #getDrawableState()
   1336      */
   1337     protected static final int[] PRESSED_STATE_SET;
   1338     /**
   1339      * Indicates the view's window has focus. States are used with
   1340      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1341      * view depending on its state.
   1342      *
   1343      * @see android.graphics.drawable.Drawable
   1344      * @see #getDrawableState()
   1345      */
   1346     protected static final int[] WINDOW_FOCUSED_STATE_SET;
   1347     // Doubles
   1348     /**
   1349      * Indicates the view is enabled and has the focus.
   1350      *
   1351      * @see #ENABLED_STATE_SET
   1352      * @see #FOCUSED_STATE_SET
   1353      */
   1354     protected static final int[] ENABLED_FOCUSED_STATE_SET;
   1355     /**
   1356      * Indicates the view is enabled and selected.
   1357      *
   1358      * @see #ENABLED_STATE_SET
   1359      * @see #SELECTED_STATE_SET
   1360      */
   1361     protected static final int[] ENABLED_SELECTED_STATE_SET;
   1362     /**
   1363      * Indicates the view is enabled and that its window has focus.
   1364      *
   1365      * @see #ENABLED_STATE_SET
   1366      * @see #WINDOW_FOCUSED_STATE_SET
   1367      */
   1368     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
   1369     /**
   1370      * Indicates the view is focused and selected.
   1371      *
   1372      * @see #FOCUSED_STATE_SET
   1373      * @see #SELECTED_STATE_SET
   1374      */
   1375     protected static final int[] FOCUSED_SELECTED_STATE_SET;
   1376     /**
   1377      * Indicates the view has the focus and that its window has the focus.
   1378      *
   1379      * @see #FOCUSED_STATE_SET
   1380      * @see #WINDOW_FOCUSED_STATE_SET
   1381      */
   1382     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1383     /**
   1384      * Indicates the view is selected and that its window has the focus.
   1385      *
   1386      * @see #SELECTED_STATE_SET
   1387      * @see #WINDOW_FOCUSED_STATE_SET
   1388      */
   1389     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
   1390     // Triples
   1391     /**
   1392      * Indicates the view is enabled, focused and selected.
   1393      *
   1394      * @see #ENABLED_STATE_SET
   1395      * @see #FOCUSED_STATE_SET
   1396      * @see #SELECTED_STATE_SET
   1397      */
   1398     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
   1399     /**
   1400      * Indicates the view is enabled, focused and its window has the focus.
   1401      *
   1402      * @see #ENABLED_STATE_SET
   1403      * @see #FOCUSED_STATE_SET
   1404      * @see #WINDOW_FOCUSED_STATE_SET
   1405      */
   1406     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1407     /**
   1408      * Indicates the view is enabled, selected and its window has the focus.
   1409      *
   1410      * @see #ENABLED_STATE_SET
   1411      * @see #SELECTED_STATE_SET
   1412      * @see #WINDOW_FOCUSED_STATE_SET
   1413      */
   1414     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1415     /**
   1416      * Indicates the view is focused, selected and its window has the focus.
   1417      *
   1418      * @see #FOCUSED_STATE_SET
   1419      * @see #SELECTED_STATE_SET
   1420      * @see #WINDOW_FOCUSED_STATE_SET
   1421      */
   1422     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1423     /**
   1424      * Indicates the view is enabled, focused, selected and its window
   1425      * has the focus.
   1426      *
   1427      * @see #ENABLED_STATE_SET
   1428      * @see #FOCUSED_STATE_SET
   1429      * @see #SELECTED_STATE_SET
   1430      * @see #WINDOW_FOCUSED_STATE_SET
   1431      */
   1432     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1433     /**
   1434      * Indicates the view is pressed and its window has the focus.
   1435      *
   1436      * @see #PRESSED_STATE_SET
   1437      * @see #WINDOW_FOCUSED_STATE_SET
   1438      */
   1439     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
   1440     /**
   1441      * Indicates the view is pressed and selected.
   1442      *
   1443      * @see #PRESSED_STATE_SET
   1444      * @see #SELECTED_STATE_SET
   1445      */
   1446     protected static final int[] PRESSED_SELECTED_STATE_SET;
   1447     /**
   1448      * Indicates the view is pressed, selected and its window has the focus.
   1449      *
   1450      * @see #PRESSED_STATE_SET
   1451      * @see #SELECTED_STATE_SET
   1452      * @see #WINDOW_FOCUSED_STATE_SET
   1453      */
   1454     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1455     /**
   1456      * Indicates the view is pressed and focused.
   1457      *
   1458      * @see #PRESSED_STATE_SET
   1459      * @see #FOCUSED_STATE_SET
   1460      */
   1461     protected static final int[] PRESSED_FOCUSED_STATE_SET;
   1462     /**
   1463      * Indicates the view is pressed, focused and its window has the focus.
   1464      *
   1465      * @see #PRESSED_STATE_SET
   1466      * @see #FOCUSED_STATE_SET
   1467      * @see #WINDOW_FOCUSED_STATE_SET
   1468      */
   1469     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1470     /**
   1471      * Indicates the view is pressed, focused and selected.
   1472      *
   1473      * @see #PRESSED_STATE_SET
   1474      * @see #SELECTED_STATE_SET
   1475      * @see #FOCUSED_STATE_SET
   1476      */
   1477     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
   1478     /**
   1479      * Indicates the view is pressed, focused, selected and its window has the focus.
   1480      *
   1481      * @see #PRESSED_STATE_SET
   1482      * @see #FOCUSED_STATE_SET
   1483      * @see #SELECTED_STATE_SET
   1484      * @see #WINDOW_FOCUSED_STATE_SET
   1485      */
   1486     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1487     /**
   1488      * Indicates the view is pressed and enabled.
   1489      *
   1490      * @see #PRESSED_STATE_SET
   1491      * @see #ENABLED_STATE_SET
   1492      */
   1493     protected static final int[] PRESSED_ENABLED_STATE_SET;
   1494     /**
   1495      * Indicates the view is pressed, enabled and its window has the focus.
   1496      *
   1497      * @see #PRESSED_STATE_SET
   1498      * @see #ENABLED_STATE_SET
   1499      * @see #WINDOW_FOCUSED_STATE_SET
   1500      */
   1501     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
   1502     /**
   1503      * Indicates the view is pressed, enabled and selected.
   1504      *
   1505      * @see #PRESSED_STATE_SET
   1506      * @see #ENABLED_STATE_SET
   1507      * @see #SELECTED_STATE_SET
   1508      */
   1509     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
   1510     /**
   1511      * Indicates the view is pressed, enabled, selected and its window has the
   1512      * focus.
   1513      *
   1514      * @see #PRESSED_STATE_SET
   1515      * @see #ENABLED_STATE_SET
   1516      * @see #SELECTED_STATE_SET
   1517      * @see #WINDOW_FOCUSED_STATE_SET
   1518      */
   1519     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1520     /**
   1521      * Indicates the view is pressed, enabled and focused.
   1522      *
   1523      * @see #PRESSED_STATE_SET
   1524      * @see #ENABLED_STATE_SET
   1525      * @see #FOCUSED_STATE_SET
   1526      */
   1527     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
   1528     /**
   1529      * Indicates the view is pressed, enabled, focused and its window has the
   1530      * focus.
   1531      *
   1532      * @see #PRESSED_STATE_SET
   1533      * @see #ENABLED_STATE_SET
   1534      * @see #FOCUSED_STATE_SET
   1535      * @see #WINDOW_FOCUSED_STATE_SET
   1536      */
   1537     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1538     /**
   1539      * Indicates the view is pressed, enabled, focused and selected.
   1540      *
   1541      * @see #PRESSED_STATE_SET
   1542      * @see #ENABLED_STATE_SET
   1543      * @see #SELECTED_STATE_SET
   1544      * @see #FOCUSED_STATE_SET
   1545      */
   1546     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
   1547     /**
   1548      * Indicates the view is pressed, enabled, focused, selected and its window
   1549      * has the focus.
   1550      *
   1551      * @see #PRESSED_STATE_SET
   1552      * @see #ENABLED_STATE_SET
   1553      * @see #SELECTED_STATE_SET
   1554      * @see #FOCUSED_STATE_SET
   1555      * @see #WINDOW_FOCUSED_STATE_SET
   1556      */
   1557     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1558 
   1559     static {
   1560         EMPTY_STATE_SET = StateSet.get(0);
   1561 
   1562         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
   1563 
   1564         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
   1565         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1566                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
   1567 
   1568         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
   1569         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1570                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
   1571         FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1572                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
   1573         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1574                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1575                         | StateSet.VIEW_STATE_FOCUSED);
   1576 
   1577         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
   1578         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1579                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   1580         ENABLED_SELECTED_STATE_SET = StateSet.get(
   1581                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
   1582         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1583                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1584                         | StateSet.VIEW_STATE_ENABLED);
   1585         ENABLED_FOCUSED_STATE_SET = StateSet.get(
   1586                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   1587         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1588                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1589                         | StateSet.VIEW_STATE_ENABLED);
   1590         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1591                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1592                         | StateSet.VIEW_STATE_ENABLED);
   1593         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1594                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1595                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
   1596 
   1597         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
   1598         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1599                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1600         PRESSED_SELECTED_STATE_SET = StateSet.get(
   1601                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
   1602         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1603                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1604                         | StateSet.VIEW_STATE_PRESSED);
   1605         PRESSED_FOCUSED_STATE_SET = StateSet.get(
   1606                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1607         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1608                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1609                         | StateSet.VIEW_STATE_PRESSED);
   1610         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1611                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1612                         | StateSet.VIEW_STATE_PRESSED);
   1613         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1614                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1615                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1616         PRESSED_ENABLED_STATE_SET = StateSet.get(
   1617                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1618         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1619                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
   1620                         | StateSet.VIEW_STATE_PRESSED);
   1621         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
   1622                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
   1623                         | StateSet.VIEW_STATE_PRESSED);
   1624         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1625                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1626                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1627         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
   1628                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
   1629                         | StateSet.VIEW_STATE_PRESSED);
   1630         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1631                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1632                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1633         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1634                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1635                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1636         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1637                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1638                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
   1639                         | StateSet.VIEW_STATE_PRESSED);
   1640     }
   1641 
   1642     /**
   1643      * Accessibility event types that are dispatched for text population.
   1644      */
   1645     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
   1646             AccessibilityEvent.TYPE_VIEW_CLICKED
   1647             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   1648             | AccessibilityEvent.TYPE_VIEW_SELECTED
   1649             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   1650             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   1651             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   1652             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   1653             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   1654             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
   1655             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
   1656             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
   1657 
   1658     /**
   1659      * Temporary Rect currently for use in setBackground().  This will probably
   1660      * be extended in the future to hold our own class with more than just
   1661      * a Rect. :)
   1662      */
   1663     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
   1664 
   1665     /**
   1666      * Map used to store views' tags.
   1667      */
   1668     private SparseArray<Object> mKeyedTags;
   1669 
   1670     /**
   1671      * The next available accessibility id.
   1672      */
   1673     private static int sNextAccessibilityViewId;
   1674 
   1675     /**
   1676      * The animation currently associated with this view.
   1677      * @hide
   1678      */
   1679     protected Animation mCurrentAnimation = null;
   1680 
   1681     /**
   1682      * Width as measured during measure pass.
   1683      * {@hide}
   1684      */
   1685     @ViewDebug.ExportedProperty(category = "measurement")
   1686     int mMeasuredWidth;
   1687 
   1688     /**
   1689      * Height as measured during measure pass.
   1690      * {@hide}
   1691      */
   1692     @ViewDebug.ExportedProperty(category = "measurement")
   1693     int mMeasuredHeight;
   1694 
   1695     /**
   1696      * Flag to indicate that this view was marked INVALIDATED, or had its display list
   1697      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
   1698      * its display list. This flag, used only when hw accelerated, allows us to clear the
   1699      * flag while retaining this information until it's needed (at getDisplayList() time and
   1700      * in drawChild(), when we decide to draw a view's children's display lists into our own).
   1701      *
   1702      * {@hide}
   1703      */
   1704     boolean mRecreateDisplayList = false;
   1705 
   1706     /**
   1707      * The view's identifier.
   1708      * {@hide}
   1709      *
   1710      * @see #setId(int)
   1711      * @see #getId()
   1712      */
   1713     @IdRes
   1714     @ViewDebug.ExportedProperty(resolveId = true)
   1715     int mID = NO_ID;
   1716 
   1717     /**
   1718      * The stable ID of this view for accessibility purposes.
   1719      */
   1720     int mAccessibilityViewId = NO_ID;
   1721 
   1722     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   1723 
   1724     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
   1725 
   1726     /**
   1727      * The view's tag.
   1728      * {@hide}
   1729      *
   1730      * @see #setTag(Object)
   1731      * @see #getTag()
   1732      */
   1733     protected Object mTag = null;
   1734 
   1735     // for mPrivateFlags:
   1736     /** {@hide} */
   1737     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
   1738     /** {@hide} */
   1739     static final int PFLAG_FOCUSED                     = 0x00000002;
   1740     /** {@hide} */
   1741     static final int PFLAG_SELECTED                    = 0x00000004;
   1742     /** {@hide} */
   1743     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
   1744     /** {@hide} */
   1745     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
   1746     /** {@hide} */
   1747     static final int PFLAG_DRAWN                       = 0x00000020;
   1748     /**
   1749      * When this flag is set, this view is running an animation on behalf of its
   1750      * children and should therefore not cancel invalidate requests, even if they
   1751      * lie outside of this view's bounds.
   1752      *
   1753      * {@hide}
   1754      */
   1755     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
   1756     /** {@hide} */
   1757     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
   1758     /** {@hide} */
   1759     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
   1760     /** {@hide} */
   1761     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
   1762     /** {@hide} */
   1763     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
   1764     /** {@hide} */
   1765     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
   1766     /** {@hide} */
   1767     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
   1768 
   1769     private static final int PFLAG_PRESSED             = 0x00004000;
   1770 
   1771     /** {@hide} */
   1772     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
   1773     /**
   1774      * Flag used to indicate that this view should be drawn once more (and only once
   1775      * more) after its animation has completed.
   1776      * {@hide}
   1777      */
   1778     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
   1779 
   1780     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
   1781 
   1782     /**
   1783      * Indicates that the View returned true when onSetAlpha() was called and that
   1784      * the alpha must be restored.
   1785      * {@hide}
   1786      */
   1787     static final int PFLAG_ALPHA_SET                   = 0x00040000;
   1788 
   1789     /**
   1790      * Set by {@link #setScrollContainer(boolean)}.
   1791      */
   1792     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
   1793 
   1794     /**
   1795      * Set by {@link #setScrollContainer(boolean)}.
   1796      */
   1797     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
   1798 
   1799     /**
   1800      * View flag indicating whether this view was invalidated (fully or partially.)
   1801      *
   1802      * @hide
   1803      */
   1804     static final int PFLAG_DIRTY                       = 0x00200000;
   1805 
   1806     /**
   1807      * View flag indicating whether this view was invalidated by an opaque
   1808      * invalidate request.
   1809      *
   1810      * @hide
   1811      */
   1812     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
   1813 
   1814     /**
   1815      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
   1816      *
   1817      * @hide
   1818      */
   1819     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
   1820 
   1821     /**
   1822      * Indicates whether the background is opaque.
   1823      *
   1824      * @hide
   1825      */
   1826     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
   1827 
   1828     /**
   1829      * Indicates whether the scrollbars are opaque.
   1830      *
   1831      * @hide
   1832      */
   1833     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
   1834 
   1835     /**
   1836      * Indicates whether the view is opaque.
   1837      *
   1838      * @hide
   1839      */
   1840     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
   1841 
   1842     /**
   1843      * Indicates a prepressed state;
   1844      * the short time between ACTION_DOWN and recognizing
   1845      * a 'real' press. Prepressed is used to recognize quick taps
   1846      * even when they are shorter than ViewConfiguration.getTapTimeout().
   1847      *
   1848      * @hide
   1849      */
   1850     private static final int PFLAG_PREPRESSED          = 0x02000000;
   1851 
   1852     /**
   1853      * Indicates whether the view is temporarily detached.
   1854      *
   1855      * @hide
   1856      */
   1857     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
   1858 
   1859     /**
   1860      * Indicates that we should awaken scroll bars once attached
   1861      *
   1862      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
   1863      * during window attachment and it is no longer needed. Feel free to repurpose it.
   1864      *
   1865      * @hide
   1866      */
   1867     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
   1868 
   1869     /**
   1870      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
   1871      * @hide
   1872      */
   1873     private static final int PFLAG_HOVERED             = 0x10000000;
   1874 
   1875     /**
   1876      * no longer needed, should be reused
   1877      */
   1878     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
   1879 
   1880     /** {@hide} */
   1881     static final int PFLAG_ACTIVATED                   = 0x40000000;
   1882 
   1883     /**
   1884      * Indicates that this view was specifically invalidated, not just dirtied because some
   1885      * child view was invalidated. The flag is used to determine when we need to recreate
   1886      * a view's display list (as opposed to just returning a reference to its existing
   1887      * display list).
   1888      *
   1889      * @hide
   1890      */
   1891     static final int PFLAG_INVALIDATED                 = 0x80000000;
   1892 
   1893     /**
   1894      * Masks for mPrivateFlags2, as generated by dumpFlags():
   1895      *
   1896      * |-------|-------|-------|-------|
   1897      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
   1898      *                                1  PFLAG2_DRAG_HOVERED
   1899      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
   1900      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
   1901      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
   1902      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
   1903      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
   1904      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
   1905      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
   1906      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
   1907      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
   1908      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
   1909      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
   1910      *                         111       PFLAG2_TEXT_DIRECTION_MASK
   1911      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
   1912      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
   1913      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
   1914      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
   1915      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
   1916      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
   1917      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
   1918      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
   1919      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
   1920      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
   1921      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
   1922      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
   1923      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
   1924      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
   1925      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
   1926      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
   1927      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
   1928      *     1                             PFLAG2_VIEW_QUICK_REJECTED
   1929      *    1                              PFLAG2_PADDING_RESOLVED
   1930      *   1                               PFLAG2_DRAWABLE_RESOLVED
   1931      *  1                                PFLAG2_HAS_TRANSIENT_STATE
   1932      * |-------|-------|-------|-------|
   1933      */
   1934 
   1935     /**
   1936      * Indicates that this view has reported that it can accept the current drag's content.
   1937      * Cleared when the drag operation concludes.
   1938      * @hide
   1939      */
   1940     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
   1941 
   1942     /**
   1943      * Indicates that this view is currently directly under the drag location in a
   1944      * drag-and-drop operation involving content that it can accept.  Cleared when
   1945      * the drag exits the view, or when the drag operation concludes.
   1946      * @hide
   1947      */
   1948     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
   1949 
   1950     /** @hide */
   1951     @IntDef({
   1952         LAYOUT_DIRECTION_LTR,
   1953         LAYOUT_DIRECTION_RTL,
   1954         LAYOUT_DIRECTION_INHERIT,
   1955         LAYOUT_DIRECTION_LOCALE
   1956     })
   1957     @Retention(RetentionPolicy.SOURCE)
   1958     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
   1959     public @interface LayoutDir {}
   1960 
   1961     /** @hide */
   1962     @IntDef({
   1963         LAYOUT_DIRECTION_LTR,
   1964         LAYOUT_DIRECTION_RTL
   1965     })
   1966     @Retention(RetentionPolicy.SOURCE)
   1967     public @interface ResolvedLayoutDir {}
   1968 
   1969     /**
   1970      * A flag to indicate that the layout direction of this view has not been defined yet.
   1971      * @hide
   1972      */
   1973     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
   1974 
   1975     /**
   1976      * Horizontal layout direction of this view is from Left to Right.
   1977      * Use with {@link #setLayoutDirection}.
   1978      */
   1979     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
   1980 
   1981     /**
   1982      * Horizontal layout direction of this view is from Right to Left.
   1983      * Use with {@link #setLayoutDirection}.
   1984      */
   1985     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
   1986 
   1987     /**
   1988      * Horizontal layout direction of this view is inherited from its parent.
   1989      * Use with {@link #setLayoutDirection}.
   1990      */
   1991     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
   1992 
   1993     /**
   1994      * Horizontal layout direction of this view is from deduced from the default language
   1995      * script for the locale. Use with {@link #setLayoutDirection}.
   1996      */
   1997     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
   1998 
   1999     /**
   2000      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2001      * @hide
   2002      */
   2003     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
   2004 
   2005     /**
   2006      * Mask for use with private flags indicating bits used for horizontal layout direction.
   2007      * @hide
   2008      */
   2009     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2010 
   2011     /**
   2012      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
   2013      * right-to-left direction.
   2014      * @hide
   2015      */
   2016     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2017 
   2018     /**
   2019      * Indicates whether the view horizontal layout direction has been resolved.
   2020      * @hide
   2021      */
   2022     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2023 
   2024     /**
   2025      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
   2026      * @hide
   2027      */
   2028     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
   2029             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2030 
   2031     /*
   2032      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
   2033      * flag value.
   2034      * @hide
   2035      */
   2036     private static final int[] LAYOUT_DIRECTION_FLAGS = {
   2037             LAYOUT_DIRECTION_LTR,
   2038             LAYOUT_DIRECTION_RTL,
   2039             LAYOUT_DIRECTION_INHERIT,
   2040             LAYOUT_DIRECTION_LOCALE
   2041     };
   2042 
   2043     /**
   2044      * Default horizontal layout direction.
   2045      */
   2046     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
   2047 
   2048     /**
   2049      * Default horizontal layout direction.
   2050      * @hide
   2051      */
   2052     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
   2053 
   2054     /**
   2055      * Text direction is inherited through {@link ViewGroup}
   2056      */
   2057     public static final int TEXT_DIRECTION_INHERIT = 0;
   2058 
   2059     /**
   2060      * Text direction is using "first strong algorithm". The first strong directional character
   2061      * determines the paragraph direction. If there is no strong directional character, the
   2062      * paragraph direction is the view's resolved layout direction.
   2063      */
   2064     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
   2065 
   2066     /**
   2067      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
   2068      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
   2069      * If there are neither, the paragraph direction is the view's resolved layout direction.
   2070      */
   2071     public static final int TEXT_DIRECTION_ANY_RTL = 2;
   2072 
   2073     /**
   2074      * Text direction is forced to LTR.
   2075      */
   2076     public static final int TEXT_DIRECTION_LTR = 3;
   2077 
   2078     /**
   2079      * Text direction is forced to RTL.
   2080      */
   2081     public static final int TEXT_DIRECTION_RTL = 4;
   2082 
   2083     /**
   2084      * Text direction is coming from the system Locale.
   2085      */
   2086     public static final int TEXT_DIRECTION_LOCALE = 5;
   2087 
   2088     /**
   2089      * Text direction is using "first strong algorithm". The first strong directional character
   2090      * determines the paragraph direction. If there is no strong directional character, the
   2091      * paragraph direction is LTR.
   2092      */
   2093     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
   2094 
   2095     /**
   2096      * Text direction is using "first strong algorithm". The first strong directional character
   2097      * determines the paragraph direction. If there is no strong directional character, the
   2098      * paragraph direction is RTL.
   2099      */
   2100     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
   2101 
   2102     /**
   2103      * Default text direction is inherited
   2104      */
   2105     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
   2106 
   2107     /**
   2108      * Default resolved text direction
   2109      * @hide
   2110      */
   2111     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
   2112 
   2113     /**
   2114      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
   2115      * @hide
   2116      */
   2117     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
   2118 
   2119     /**
   2120      * Mask for use with private flags indicating bits used for text direction.
   2121      * @hide
   2122      */
   2123     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
   2124             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2125 
   2126     /**
   2127      * Array of text direction flags for mapping attribute "textDirection" to correct
   2128      * flag value.
   2129      * @hide
   2130      */
   2131     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
   2132             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2133             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2134             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2135             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2136             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2137             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2138             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2139             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
   2140     };
   2141 
   2142     /**
   2143      * Indicates whether the view text direction has been resolved.
   2144      * @hide
   2145      */
   2146     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
   2147             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2148 
   2149     /**
   2150      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2151      * @hide
   2152      */
   2153     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
   2154 
   2155     /**
   2156      * Mask for use with private flags indicating bits used for resolved text direction.
   2157      * @hide
   2158      */
   2159     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
   2160             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2161 
   2162     /**
   2163      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
   2164      * @hide
   2165      */
   2166     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
   2167             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2168 
   2169     /** @hide */
   2170     @IntDef({
   2171         TEXT_ALIGNMENT_INHERIT,
   2172         TEXT_ALIGNMENT_GRAVITY,
   2173         TEXT_ALIGNMENT_CENTER,
   2174         TEXT_ALIGNMENT_TEXT_START,
   2175         TEXT_ALIGNMENT_TEXT_END,
   2176         TEXT_ALIGNMENT_VIEW_START,
   2177         TEXT_ALIGNMENT_VIEW_END
   2178     })
   2179     @Retention(RetentionPolicy.SOURCE)
   2180     public @interface TextAlignment {}
   2181 
   2182     /**
   2183      * Default text alignment. The text alignment of this View is inherited from its parent.
   2184      * Use with {@link #setTextAlignment(int)}
   2185      */
   2186     public static final int TEXT_ALIGNMENT_INHERIT = 0;
   2187 
   2188     /**
   2189      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
   2190      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraphs text direction.
   2191      *
   2192      * Use with {@link #setTextAlignment(int)}
   2193      */
   2194     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
   2195 
   2196     /**
   2197      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
   2198      *
   2199      * Use with {@link #setTextAlignment(int)}
   2200      */
   2201     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
   2202 
   2203     /**
   2204      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
   2205      *
   2206      * Use with {@link #setTextAlignment(int)}
   2207      */
   2208     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
   2209 
   2210     /**
   2211      * Center the paragraph, e.g. ALIGN_CENTER.
   2212      *
   2213      * Use with {@link #setTextAlignment(int)}
   2214      */
   2215     public static final int TEXT_ALIGNMENT_CENTER = 4;
   2216 
   2217     /**
   2218      * Align to the start of the view, which is ALIGN_LEFT if the views resolved
   2219      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
   2220      *
   2221      * Use with {@link #setTextAlignment(int)}
   2222      */
   2223     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
   2224 
   2225     /**
   2226      * Align to the end of the view, which is ALIGN_RIGHT if the views resolved
   2227      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
   2228      *
   2229      * Use with {@link #setTextAlignment(int)}
   2230      */
   2231     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
   2232 
   2233     /**
   2234      * Default text alignment is inherited
   2235      */
   2236     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2237 
   2238     /**
   2239      * Default resolved text alignment
   2240      * @hide
   2241      */
   2242     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2243 
   2244     /**
   2245       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2246       * @hide
   2247       */
   2248     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
   2249 
   2250     /**
   2251       * Mask for use with private flags indicating bits used for text alignment.
   2252       * @hide
   2253       */
   2254     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2255 
   2256     /**
   2257      * Array of text direction flags for mapping attribute "textAlignment" to correct
   2258      * flag value.
   2259      * @hide
   2260      */
   2261     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
   2262             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2263             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2264             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2265             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2266             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2267             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2268             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
   2269     };
   2270 
   2271     /**
   2272      * Indicates whether the view text alignment has been resolved.
   2273      * @hide
   2274      */
   2275     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2276 
   2277     /**
   2278      * Bit shift to get the resolved text alignment.
   2279      * @hide
   2280      */
   2281     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
   2282 
   2283     /**
   2284      * Mask for use with private flags indicating bits used for text alignment.
   2285      * @hide
   2286      */
   2287     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
   2288             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2289 
   2290     /**
   2291      * Indicates whether if the view text alignment has been resolved to gravity
   2292      */
   2293     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
   2294             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2295 
   2296     // Accessiblity constants for mPrivateFlags2
   2297 
   2298     /**
   2299      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2300      * "importantForAccessibility" attribute.
   2301      */
   2302     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
   2303 
   2304     /**
   2305      * Automatically determine whether a view is important for accessibility.
   2306      */
   2307     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
   2308 
   2309     /**
   2310      * The view is important for accessibility.
   2311      */
   2312     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
   2313 
   2314     /**
   2315      * The view is not important for accessibility.
   2316      */
   2317     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
   2318 
   2319     /**
   2320      * The view is not important for accessibility, nor are any of its
   2321      * descendant views.
   2322      */
   2323     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
   2324 
   2325     /**
   2326      * The default whether the view is important for accessibility.
   2327      */
   2328     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   2329 
   2330     /**
   2331      * Mask for obtainig the bits which specify how to determine
   2332      * whether a view is important for accessibility.
   2333      */
   2334     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
   2335         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
   2336         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
   2337         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   2338 
   2339     /**
   2340      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2341      * "accessibilityLiveRegion" attribute.
   2342      */
   2343     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
   2344 
   2345     /**
   2346      * Live region mode specifying that accessibility services should not
   2347      * automatically announce changes to this view. This is the default live
   2348      * region mode for most views.
   2349      * <p>
   2350      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2351      */
   2352     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
   2353 
   2354     /**
   2355      * Live region mode specifying that accessibility services should announce
   2356      * changes to this view.
   2357      * <p>
   2358      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2359      */
   2360     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
   2361 
   2362     /**
   2363      * Live region mode specifying that accessibility services should interrupt
   2364      * ongoing speech to immediately announce changes to this view.
   2365      * <p>
   2366      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2367      */
   2368     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
   2369 
   2370     /**
   2371      * The default whether the view is important for accessibility.
   2372      */
   2373     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
   2374 
   2375     /**
   2376      * Mask for obtaining the bits which specify a view's accessibility live
   2377      * region mode.
   2378      */
   2379     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
   2380             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
   2381             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   2382 
   2383     /**
   2384      * Flag indicating whether a view has accessibility focus.
   2385      */
   2386     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
   2387 
   2388     /**
   2389      * Flag whether the accessibility state of the subtree rooted at this view changed.
   2390      */
   2391     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
   2392 
   2393     /**
   2394      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
   2395      * is used to check whether later changes to the view's transform should invalidate the
   2396      * view to force the quickReject test to run again.
   2397      */
   2398     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
   2399 
   2400     /**
   2401      * Flag indicating that start/end padding has been resolved into left/right padding
   2402      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
   2403      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
   2404      * during measurement. In some special cases this is required such as when an adapter-based
   2405      * view measures prospective children without attaching them to a window.
   2406      */
   2407     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
   2408 
   2409     /**
   2410      * Flag indicating that the start/end drawables has been resolved into left/right ones.
   2411      */
   2412     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
   2413 
   2414     /**
   2415      * Indicates that the view is tracking some sort of transient state
   2416      * that the app should not need to be aware of, but that the framework
   2417      * should take special care to preserve.
   2418      */
   2419     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
   2420 
   2421     /**
   2422      * Group of bits indicating that RTL properties resolution is done.
   2423      */
   2424     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
   2425             PFLAG2_TEXT_DIRECTION_RESOLVED |
   2426             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   2427             PFLAG2_PADDING_RESOLVED |
   2428             PFLAG2_DRAWABLE_RESOLVED;
   2429 
   2430     // There are a couple of flags left in mPrivateFlags2
   2431 
   2432     /* End of masks for mPrivateFlags2 */
   2433 
   2434     /**
   2435      * Masks for mPrivateFlags3, as generated by dumpFlags():
   2436      *
   2437      * |-------|-------|-------|-------|
   2438      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
   2439      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
   2440      *                               1   PFLAG3_IS_LAID_OUT
   2441      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
   2442      *                             1     PFLAG3_CALLED_SUPER
   2443      *                            1      PFLAG3_APPLYING_INSETS
   2444      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
   2445      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
   2446      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
   2447      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
   2448      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
   2449      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
   2450      *                     1             PFLAG3_SCROLL_INDICATOR_START
   2451      *                    1              PFLAG3_SCROLL_INDICATOR_END
   2452      *                   1               PFLAG3_ASSIST_BLOCKED
   2453      *                  1                PFLAG3_POINTER_ICON_NULL
   2454      *                 1                 PFLAG3_POINTER_ICON_VALUE_START
   2455      *           11111111                PFLAG3_POINTER_ICON_MASK
   2456      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
   2457      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
   2458      *        1                          PFLAG3_TEMPORARY_DETACH
   2459      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
   2460      * |-------|-------|-------|-------|
   2461      */
   2462 
   2463     /**
   2464      * Flag indicating that view has a transform animation set on it. This is used to track whether
   2465      * an animation is cleared between successive frames, in order to tell the associated
   2466      * DisplayList to clear its animation matrix.
   2467      */
   2468     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
   2469 
   2470     /**
   2471      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
   2472      * animation is cleared between successive frames, in order to tell the associated
   2473      * DisplayList to restore its alpha value.
   2474      */
   2475     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
   2476 
   2477     /**
   2478      * Flag indicating that the view has been through at least one layout since it
   2479      * was last attached to a window.
   2480      */
   2481     static final int PFLAG3_IS_LAID_OUT = 0x4;
   2482 
   2483     /**
   2484      * Flag indicating that a call to measure() was skipped and should be done
   2485      * instead when layout() is invoked.
   2486      */
   2487     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
   2488 
   2489     /**
   2490      * Flag indicating that an overridden method correctly called down to
   2491      * the superclass implementation as required by the API spec.
   2492      */
   2493     static final int PFLAG3_CALLED_SUPER = 0x10;
   2494 
   2495     /**
   2496      * Flag indicating that we're in the process of applying window insets.
   2497      */
   2498     static final int PFLAG3_APPLYING_INSETS = 0x20;
   2499 
   2500     /**
   2501      * Flag indicating that we're in the process of fitting system windows using the old method.
   2502      */
   2503     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
   2504 
   2505     /**
   2506      * Flag indicating that nested scrolling is enabled for this view.
   2507      * The view will optionally cooperate with views up its parent chain to allow for
   2508      * integrated nested scrolling along the same axis.
   2509      */
   2510     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
   2511 
   2512     /**
   2513      * Flag indicating that the bottom scroll indicator should be displayed
   2514      * when this view can scroll up.
   2515      */
   2516     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
   2517 
   2518     /**
   2519      * Flag indicating that the bottom scroll indicator should be displayed
   2520      * when this view can scroll down.
   2521      */
   2522     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
   2523 
   2524     /**
   2525      * Flag indicating that the left scroll indicator should be displayed
   2526      * when this view can scroll left.
   2527      */
   2528     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
   2529 
   2530     /**
   2531      * Flag indicating that the right scroll indicator should be displayed
   2532      * when this view can scroll right.
   2533      */
   2534     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
   2535 
   2536     /**
   2537      * Flag indicating that the start scroll indicator should be displayed
   2538      * when this view can scroll in the start direction.
   2539      */
   2540     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
   2541 
   2542     /**
   2543      * Flag indicating that the end scroll indicator should be displayed
   2544      * when this view can scroll in the end direction.
   2545      */
   2546     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
   2547 
   2548     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
   2549 
   2550     static final int SCROLL_INDICATORS_NONE = 0x0000;
   2551 
   2552     /**
   2553      * Mask for use with setFlags indicating bits used for indicating which
   2554      * scroll indicators are enabled.
   2555      */
   2556     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
   2557             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
   2558             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
   2559             | PFLAG3_SCROLL_INDICATOR_END;
   2560 
   2561     /**
   2562      * Left-shift required to translate between public scroll indicator flags
   2563      * and internal PFLAGS3 flags. When used as a right-shift, translates
   2564      * PFLAGS3 flags to public flags.
   2565      */
   2566     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
   2567 
   2568     /** @hide */
   2569     @Retention(RetentionPolicy.SOURCE)
   2570     @IntDef(flag = true,
   2571             value = {
   2572                     SCROLL_INDICATOR_TOP,
   2573                     SCROLL_INDICATOR_BOTTOM,
   2574                     SCROLL_INDICATOR_LEFT,
   2575                     SCROLL_INDICATOR_RIGHT,
   2576                     SCROLL_INDICATOR_START,
   2577                     SCROLL_INDICATOR_END,
   2578             })
   2579     public @interface ScrollIndicators {}
   2580 
   2581     /**
   2582      * Scroll indicator direction for the top edge of the view.
   2583      *
   2584      * @see #setScrollIndicators(int)
   2585      * @see #setScrollIndicators(int, int)
   2586      * @see #getScrollIndicators()
   2587      */
   2588     public static final int SCROLL_INDICATOR_TOP =
   2589             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2590 
   2591     /**
   2592      * Scroll indicator direction for the bottom edge of the view.
   2593      *
   2594      * @see #setScrollIndicators(int)
   2595      * @see #setScrollIndicators(int, int)
   2596      * @see #getScrollIndicators()
   2597      */
   2598     public static final int SCROLL_INDICATOR_BOTTOM =
   2599             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2600 
   2601     /**
   2602      * Scroll indicator direction for the left edge of the view.
   2603      *
   2604      * @see #setScrollIndicators(int)
   2605      * @see #setScrollIndicators(int, int)
   2606      * @see #getScrollIndicators()
   2607      */
   2608     public static final int SCROLL_INDICATOR_LEFT =
   2609             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2610 
   2611     /**
   2612      * Scroll indicator direction for the right edge of the view.
   2613      *
   2614      * @see #setScrollIndicators(int)
   2615      * @see #setScrollIndicators(int, int)
   2616      * @see #getScrollIndicators()
   2617      */
   2618     public static final int SCROLL_INDICATOR_RIGHT =
   2619             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2620 
   2621     /**
   2622      * Scroll indicator direction for the starting edge of the view.
   2623      * <p>
   2624      * Resolved according to the view's layout direction, see
   2625      * {@link #getLayoutDirection()} for more information.
   2626      *
   2627      * @see #setScrollIndicators(int)
   2628      * @see #setScrollIndicators(int, int)
   2629      * @see #getScrollIndicators()
   2630      */
   2631     public static final int SCROLL_INDICATOR_START =
   2632             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2633 
   2634     /**
   2635      * Scroll indicator direction for the ending edge of the view.
   2636      * <p>
   2637      * Resolved according to the view's layout direction, see
   2638      * {@link #getLayoutDirection()} for more information.
   2639      *
   2640      * @see #setScrollIndicators(int)
   2641      * @see #setScrollIndicators(int, int)
   2642      * @see #getScrollIndicators()
   2643      */
   2644     public static final int SCROLL_INDICATOR_END =
   2645             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2646 
   2647     /**
   2648      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
   2649      * into this view.<p>
   2650      */
   2651     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
   2652 
   2653     /**
   2654      * The mask for use with private flags indicating bits used for pointer icon shapes.
   2655      */
   2656     static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
   2657 
   2658     /**
   2659      * Left-shift used for pointer icon shape values in private flags.
   2660      */
   2661     static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
   2662 
   2663     /**
   2664      * Value indicating no specific pointer icons.
   2665      */
   2666     private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
   2667 
   2668     /**
   2669      * Value indicating {@link PointerIcon.TYPE_NULL}.
   2670      */
   2671     private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
   2672 
   2673     /**
   2674      * The base value for other pointer icon shapes.
   2675      */
   2676     private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
   2677 
   2678     /**
   2679      * Whether this view has rendered elements that overlap (see {@link
   2680      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
   2681      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
   2682      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
   2683      * determined by whatever {@link #hasOverlappingRendering()} returns.
   2684      */
   2685     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
   2686 
   2687     /**
   2688      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
   2689      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
   2690      */
   2691     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
   2692 
   2693     /**
   2694      * Flag indicating that the view is temporarily detached from the parent view.
   2695      *
   2696      * @see #onStartTemporaryDetach()
   2697      * @see #onFinishTemporaryDetach()
   2698      */
   2699     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
   2700 
   2701     /**
   2702      * Flag indicating that the view does not wish to be revealed within its parent
   2703      * hierarchy when it gains focus. Expressed in the negative since the historical
   2704      * default behavior is to reveal on focus; this flag suppresses that behavior.
   2705      *
   2706      * @see #setRevealOnFocusHint(boolean)
   2707      * @see #getRevealOnFocusHint()
   2708      */
   2709     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
   2710 
   2711     /* End of masks for mPrivateFlags3 */
   2712 
   2713     /**
   2714      * Always allow a user to over-scroll this view, provided it is a
   2715      * view that can scroll.
   2716      *
   2717      * @see #getOverScrollMode()
   2718      * @see #setOverScrollMode(int)
   2719      */
   2720     public static final int OVER_SCROLL_ALWAYS = 0;
   2721 
   2722     /**
   2723      * Allow a user to over-scroll this view only if the content is large
   2724      * enough to meaningfully scroll, provided it is a view that can scroll.
   2725      *
   2726      * @see #getOverScrollMode()
   2727      * @see #setOverScrollMode(int)
   2728      */
   2729     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
   2730 
   2731     /**
   2732      * Never allow a user to over-scroll this view.
   2733      *
   2734      * @see #getOverScrollMode()
   2735      * @see #setOverScrollMode(int)
   2736      */
   2737     public static final int OVER_SCROLL_NEVER = 2;
   2738 
   2739     /**
   2740      * Special constant for {@link #setSystemUiVisibility(int)}: View has
   2741      * requested the system UI (status bar) to be visible (the default).
   2742      *
   2743      * @see #setSystemUiVisibility(int)
   2744      */
   2745     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
   2746 
   2747     /**
   2748      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
   2749      * system UI to enter an unobtrusive "low profile" mode.
   2750      *
   2751      * <p>This is for use in games, book readers, video players, or any other
   2752      * "immersive" application where the usual system chrome is deemed too distracting.
   2753      *
   2754      * <p>In low profile mode, the status bar and/or navigation icons may dim.
   2755      *
   2756      * @see #setSystemUiVisibility(int)
   2757      */
   2758     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
   2759 
   2760     /**
   2761      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
   2762      * system navigation be temporarily hidden.
   2763      *
   2764      * <p>This is an even less obtrusive state than that called for by
   2765      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
   2766      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
   2767      * those to disappear. This is useful (in conjunction with the
   2768      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
   2769      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
   2770      * window flags) for displaying content using every last pixel on the display.
   2771      *
   2772      * <p>There is a limitation: because navigation controls are so important, the least user
   2773      * interaction will cause them to reappear immediately.  When this happens, both
   2774      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
   2775      * so that both elements reappear at the same time.
   2776      *
   2777      * @see #setSystemUiVisibility(int)
   2778      */
   2779     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
   2780 
   2781     /**
   2782      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
   2783      * into the normal fullscreen mode so that its content can take over the screen
   2784      * while still allowing the user to interact with the application.
   2785      *
   2786      * <p>This has the same visual effect as
   2787      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
   2788      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
   2789      * meaning that non-critical screen decorations (such as the status bar) will be
   2790      * hidden while the user is in the View's window, focusing the experience on
   2791      * that content.  Unlike the window flag, if you are using ActionBar in
   2792      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   2793      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
   2794      * hide the action bar.
   2795      *
   2796      * <p>This approach to going fullscreen is best used over the window flag when
   2797      * it is a transient state -- that is, the application does this at certain
   2798      * points in its user interaction where it wants to allow the user to focus
   2799      * on content, but not as a continuous state.  For situations where the application
   2800      * would like to simply stay full screen the entire time (such as a game that
   2801      * wants to take over the screen), the
   2802      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
   2803      * is usually a better approach.  The state set here will be removed by the system
   2804      * in various situations (such as the user moving to another application) like
   2805      * the other system UI states.
   2806      *
   2807      * <p>When using this flag, the application should provide some easy facility
   2808      * for the user to go out of it.  A common example would be in an e-book
   2809      * reader, where tapping on the screen brings back whatever screen and UI
   2810      * decorations that had been hidden while the user was immersed in reading
   2811      * the book.
   2812      *
   2813      * @see #setSystemUiVisibility(int)
   2814      */
   2815     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
   2816 
   2817     /**
   2818      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
   2819      * flags, we would like a stable view of the content insets given to
   2820      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
   2821      * will always represent the worst case that the application can expect
   2822      * as a continuous state.  In the stock Android UI this is the space for
   2823      * the system bar, nav bar, and status bar, but not more transient elements
   2824      * such as an input method.
   2825      *
   2826      * The stable layout your UI sees is based on the system UI modes you can
   2827      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   2828      * then you will get a stable layout for changes of the
   2829      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
   2830      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
   2831      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
   2832      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
   2833      * with a stable layout.  (Note that you should avoid using
   2834      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
   2835      *
   2836      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
   2837      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
   2838      * then a hidden status bar will be considered a "stable" state for purposes
   2839      * here.  This allows your UI to continually hide the status bar, while still
   2840      * using the system UI flags to hide the action bar while still retaining
   2841      * a stable layout.  Note that changing the window fullscreen flag will never
   2842      * provide a stable layout for a clean transition.
   2843      *
   2844      * <p>If you are using ActionBar in
   2845      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   2846      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
   2847      * insets it adds to those given to the application.
   2848      */
   2849     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
   2850 
   2851     /**
   2852      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   2853      * to be laid out as if it has requested
   2854      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
   2855      * allows it to avoid artifacts when switching in and out of that mode, at
   2856      * the expense that some of its user interface may be covered by screen
   2857      * decorations when they are shown.  You can perform layout of your inner
   2858      * UI elements to account for the navigation system UI through the
   2859      * {@link #fitSystemWindows(Rect)} method.
   2860      */
   2861     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
   2862 
   2863     /**
   2864      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   2865      * to be laid out as if it has requested
   2866      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
   2867      * allows it to avoid artifacts when switching in and out of that mode, at
   2868      * the expense that some of its user interface may be covered by screen
   2869      * decorations when they are shown.  You can perform layout of your inner
   2870      * UI elements to account for non-fullscreen system UI through the
   2871      * {@link #fitSystemWindows(Rect)} method.
   2872      */
   2873     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
   2874 
   2875     /**
   2876      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   2877      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
   2878      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
   2879      * user interaction.
   2880      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
   2881      * has an effect when used in combination with that flag.</p>
   2882      */
   2883     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
   2884 
   2885     /**
   2886      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   2887      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
   2888      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
   2889      * experience while also hiding the system bars.  If this flag is not set,
   2890      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
   2891      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
   2892      * if the user swipes from the top of the screen.
   2893      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
   2894      * system gestures, such as swiping from the top of the screen.  These transient system bars
   2895      * will overlay apps content, may have some degree of transparency, and will automatically
   2896      * hide after a short timeout.
   2897      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
   2898      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
   2899      * with one or both of those flags.</p>
   2900      */
   2901     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
   2902 
   2903     /**
   2904      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
   2905      * is compatible with light status bar backgrounds.
   2906      *
   2907      * <p>For this to take effect, the window must request
   2908      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
   2909      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
   2910      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
   2911      *         FLAG_TRANSLUCENT_STATUS}.
   2912      *
   2913      * @see android.R.attr#windowLightStatusBar
   2914      */
   2915     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
   2916 
   2917     /**
   2918      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
   2919      */
   2920     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
   2921 
   2922     /**
   2923      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
   2924      */
   2925     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
   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 make the status bar not expandable.  Unless you also
   2934      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
   2935      */
   2936     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
   2937 
   2938     /**
   2939      * @hide
   2940      *
   2941      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2942      * out of the public fields to keep the undefined bits out of the developer's way.
   2943      *
   2944      * Flag to hide notification icons and scrolling ticker text.
   2945      */
   2946     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
   2947 
   2948     /**
   2949      * @hide
   2950      *
   2951      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2952      * out of the public fields to keep the undefined bits out of the developer's way.
   2953      *
   2954      * Flag to disable incoming notification alerts.  This will not block
   2955      * icons, but it will block sound, vibrating and other visual or aural notifications.
   2956      */
   2957     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
   2958 
   2959     /**
   2960      * @hide
   2961      *
   2962      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2963      * out of the public fields to keep the undefined bits out of the developer's way.
   2964      *
   2965      * Flag to hide only the scrolling ticker.  Note that
   2966      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
   2967      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
   2968      */
   2969     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
   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 the center system info area.
   2978      */
   2979     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
   2980 
   2981     /**
   2982      * @hide
   2983      *
   2984      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2985      * out of the public fields to keep the undefined bits out of the developer's way.
   2986      *
   2987      * Flag to hide only the home button.  Don't use this
   2988      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   2989      */
   2990     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
   2991 
   2992     /**
   2993      * @hide
   2994      *
   2995      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2996      * out of the public fields to keep the undefined bits out of the developer's way.
   2997      *
   2998      * Flag to hide only the back button. Don't use this
   2999      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3000      */
   3001     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
   3002 
   3003     /**
   3004      * @hide
   3005      *
   3006      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3007      * out of the public fields to keep the undefined bits out of the developer's way.
   3008      *
   3009      * Flag to hide only the clock.  You might use this if your activity has
   3010      * its own clock making the status bar's clock redundant.
   3011      */
   3012     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
   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 hide only the recent apps button. Don't use this
   3021      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3022      */
   3023     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
   3024 
   3025     /**
   3026      * @hide
   3027      *
   3028      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3029      * out of the public fields to keep the undefined bits out of the developer's way.
   3030      *
   3031      * Flag to disable the global search gesture. Don't use this
   3032      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3033      */
   3034     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
   3035 
   3036     /**
   3037      * @hide
   3038      *
   3039      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3040      * out of the public fields to keep the undefined bits out of the developer's way.
   3041      *
   3042      * Flag to specify that the status bar is displayed in transient mode.
   3043      */
   3044     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
   3045 
   3046     /**
   3047      * @hide
   3048      *
   3049      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3050      * out of the public fields to keep the undefined bits out of the developer's way.
   3051      *
   3052      * Flag to specify that the navigation bar is displayed in transient mode.
   3053      */
   3054     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
   3055 
   3056     /**
   3057      * @hide
   3058      *
   3059      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3060      * out of the public fields to keep the undefined bits out of the developer's way.
   3061      *
   3062      * Flag to specify that the hidden status bar would like to be shown.
   3063      */
   3064     public static final int STATUS_BAR_UNHIDE = 0x10000000;
   3065 
   3066     /**
   3067      * @hide
   3068      *
   3069      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3070      * out of the public fields to keep the undefined bits out of the developer's way.
   3071      *
   3072      * Flag to specify that the hidden navigation bar would like to be shown.
   3073      */
   3074     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
   3075 
   3076     /**
   3077      * @hide
   3078      *
   3079      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3080      * out of the public fields to keep the undefined bits out of the developer's way.
   3081      *
   3082      * Flag to specify that the status bar is displayed in translucent mode.
   3083      */
   3084     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
   3085 
   3086     /**
   3087      * @hide
   3088      *
   3089      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3090      * out of the public fields to keep the undefined bits out of the developer's way.
   3091      *
   3092      * Flag to specify that the navigation bar is displayed in translucent mode.
   3093      */
   3094     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
   3095 
   3096     /**
   3097      * @hide
   3098      *
   3099      * Makes navigation bar transparent (but not the status bar).
   3100      */
   3101     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
   3102 
   3103     /**
   3104      * @hide
   3105      *
   3106      * Makes status bar transparent (but not the navigation bar).
   3107      */
   3108     public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
   3109 
   3110     /**
   3111      * @hide
   3112      *
   3113      * Makes both status bar and navigation bar transparent.
   3114      */
   3115     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
   3116             | STATUS_BAR_TRANSPARENT;
   3117 
   3118     /**
   3119      * @hide
   3120      */
   3121     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
   3122 
   3123     /**
   3124      * These are the system UI flags that can be cleared by events outside
   3125      * of an application.  Currently this is just the ability to tap on the
   3126      * screen while hiding the navigation bar to have it return.
   3127      * @hide
   3128      */
   3129     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
   3130             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
   3131             | SYSTEM_UI_FLAG_FULLSCREEN;
   3132 
   3133     /**
   3134      * Flags that can impact the layout in relation to system UI.
   3135      */
   3136     public static final int SYSTEM_UI_LAYOUT_FLAGS =
   3137             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
   3138             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
   3139 
   3140     /** @hide */
   3141     @IntDef(flag = true,
   3142             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
   3143     @Retention(RetentionPolicy.SOURCE)
   3144     public @interface FindViewFlags {}
   3145 
   3146     /**
   3147      * Find views that render the specified text.
   3148      *
   3149      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3150      */
   3151     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
   3152 
   3153     /**
   3154      * Find find views that contain the specified content description.
   3155      *
   3156      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3157      */
   3158     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
   3159 
   3160     /**
   3161      * Find views that contain {@link AccessibilityNodeProvider}. Such
   3162      * a View is a root of virtual view hierarchy and may contain the searched
   3163      * text. If this flag is set Views with providers are automatically
   3164      * added and it is a responsibility of the client to call the APIs of
   3165      * the provider to determine whether the virtual tree rooted at this View
   3166      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
   3167      * representing the virtual views with this text.
   3168      *
   3169      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3170      *
   3171      * @hide
   3172      */
   3173     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
   3174 
   3175     /**
   3176      * The undefined cursor position.
   3177      *
   3178      * @hide
   3179      */
   3180     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
   3181 
   3182     /**
   3183      * Indicates that the screen has changed state and is now off.
   3184      *
   3185      * @see #onScreenStateChanged(int)
   3186      */
   3187     public static final int SCREEN_STATE_OFF = 0x0;
   3188 
   3189     /**
   3190      * Indicates that the screen has changed state and is now on.
   3191      *
   3192      * @see #onScreenStateChanged(int)
   3193      */
   3194     public static final int SCREEN_STATE_ON = 0x1;
   3195 
   3196     /**
   3197      * Indicates no axis of view scrolling.
   3198      */
   3199     public static final int SCROLL_AXIS_NONE = 0;
   3200 
   3201     /**
   3202      * Indicates scrolling along the horizontal axis.
   3203      */
   3204     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
   3205 
   3206     /**
   3207      * Indicates scrolling along the vertical axis.
   3208      */
   3209     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
   3210 
   3211     /**
   3212      * Controls the over-scroll mode for this view.
   3213      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
   3214      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
   3215      * and {@link #OVER_SCROLL_NEVER}.
   3216      */
   3217     private int mOverScrollMode;
   3218 
   3219     /**
   3220      * The parent this view is attached to.
   3221      * {@hide}
   3222      *
   3223      * @see #getParent()
   3224      */
   3225     protected ViewParent mParent;
   3226 
   3227     /**
   3228      * {@hide}
   3229      */
   3230     AttachInfo mAttachInfo;
   3231 
   3232     /**
   3233      * {@hide}
   3234      */
   3235     @ViewDebug.ExportedProperty(flagMapping = {
   3236         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
   3237                 name = "FORCE_LAYOUT"),
   3238         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
   3239                 name = "LAYOUT_REQUIRED"),
   3240         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
   3241             name = "DRAWING_CACHE_INVALID", outputIf = false),
   3242         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
   3243         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
   3244         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
   3245         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
   3246     }, formatToHexString = true)
   3247     int mPrivateFlags;
   3248     int mPrivateFlags2;
   3249     int mPrivateFlags3;
   3250 
   3251     /**
   3252      * This view's request for the visibility of the status bar.
   3253      * @hide
   3254      */
   3255     @ViewDebug.ExportedProperty(flagMapping = {
   3256         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
   3257                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
   3258                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
   3259         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3260                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3261                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
   3262         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
   3263                                 equals = SYSTEM_UI_FLAG_VISIBLE,
   3264                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
   3265     }, formatToHexString = true)
   3266     int mSystemUiVisibility;
   3267 
   3268     /**
   3269      * Reference count for transient state.
   3270      * @see #setHasTransientState(boolean)
   3271      */
   3272     int mTransientStateCount = 0;
   3273 
   3274     /**
   3275      * Count of how many windows this view has been attached to.
   3276      */
   3277     int mWindowAttachCount;
   3278 
   3279     /**
   3280      * The layout parameters associated with this view and used by the parent
   3281      * {@link android.view.ViewGroup} to determine how this view should be
   3282      * laid out.
   3283      * {@hide}
   3284      */
   3285     protected ViewGroup.LayoutParams mLayoutParams;
   3286 
   3287     /**
   3288      * The view flags hold various views states.
   3289      * {@hide}
   3290      */
   3291     @ViewDebug.ExportedProperty(formatToHexString = true)
   3292     int mViewFlags;
   3293 
   3294     static class TransformationInfo {
   3295         /**
   3296          * The transform matrix for the View. This transform is calculated internally
   3297          * based on the translation, rotation, and scale properties.
   3298          *
   3299          * Do *not* use this variable directly; instead call getMatrix(), which will
   3300          * load the value from the View's RenderNode.
   3301          */
   3302         private final Matrix mMatrix = new Matrix();
   3303 
   3304         /**
   3305          * The inverse transform matrix for the View. This transform is calculated
   3306          * internally based on the translation, rotation, and scale properties.
   3307          *
   3308          * Do *not* use this variable directly; instead call getInverseMatrix(),
   3309          * which will load the value from the View's RenderNode.
   3310          */
   3311         private Matrix mInverseMatrix;
   3312 
   3313         /**
   3314          * The opacity of the View. This is a value from 0 to 1, where 0 means
   3315          * completely transparent and 1 means completely opaque.
   3316          */
   3317         @ViewDebug.ExportedProperty
   3318         float mAlpha = 1f;
   3319 
   3320         /**
   3321          * The opacity of the view as manipulated by the Fade transition. This is a hidden
   3322          * property only used by transitions, which is composited with the other alpha
   3323          * values to calculate the final visual alpha value.
   3324          */
   3325         float mTransitionAlpha = 1f;
   3326     }
   3327 
   3328     TransformationInfo mTransformationInfo;
   3329 
   3330     /**
   3331      * Current clip bounds. to which all drawing of this view are constrained.
   3332      */
   3333     Rect mClipBounds = null;
   3334 
   3335     private boolean mLastIsOpaque;
   3336 
   3337     /**
   3338      * The distance in pixels from the left edge of this view's parent
   3339      * to the left edge of this view.
   3340      * {@hide}
   3341      */
   3342     @ViewDebug.ExportedProperty(category = "layout")
   3343     protected int mLeft;
   3344     /**
   3345      * The distance in pixels from the left edge of this view's parent
   3346      * to the right edge of this view.
   3347      * {@hide}
   3348      */
   3349     @ViewDebug.ExportedProperty(category = "layout")
   3350     protected int mRight;
   3351     /**
   3352      * The distance in pixels from the top edge of this view's parent
   3353      * to the top edge of this view.
   3354      * {@hide}
   3355      */
   3356     @ViewDebug.ExportedProperty(category = "layout")
   3357     protected int mTop;
   3358     /**
   3359      * The distance in pixels from the top edge of this view's parent
   3360      * to the bottom edge of this view.
   3361      * {@hide}
   3362      */
   3363     @ViewDebug.ExportedProperty(category = "layout")
   3364     protected int mBottom;
   3365 
   3366     /**
   3367      * The offset, in pixels, by which the content of this view is scrolled
   3368      * horizontally.
   3369      * {@hide}
   3370      */
   3371     @ViewDebug.ExportedProperty(category = "scrolling")
   3372     protected int mScrollX;
   3373     /**
   3374      * The offset, in pixels, by which the content of this view is scrolled
   3375      * vertically.
   3376      * {@hide}
   3377      */
   3378     @ViewDebug.ExportedProperty(category = "scrolling")
   3379     protected int mScrollY;
   3380 
   3381     /**
   3382      * The left padding in pixels, that is the distance in pixels between the
   3383      * left edge of this view and the left edge of its content.
   3384      * {@hide}
   3385      */
   3386     @ViewDebug.ExportedProperty(category = "padding")
   3387     protected int mPaddingLeft = 0;
   3388     /**
   3389      * The right padding in pixels, that is the distance in pixels between the
   3390      * right edge of this view and the right edge of its content.
   3391      * {@hide}
   3392      */
   3393     @ViewDebug.ExportedProperty(category = "padding")
   3394     protected int mPaddingRight = 0;
   3395     /**
   3396      * The top padding in pixels, that is the distance in pixels between the
   3397      * top edge of this view and the top edge of its content.
   3398      * {@hide}
   3399      */
   3400     @ViewDebug.ExportedProperty(category = "padding")
   3401     protected int mPaddingTop;
   3402     /**
   3403      * The bottom padding in pixels, that is the distance in pixels between the
   3404      * bottom edge of this view and the bottom edge of its content.
   3405      * {@hide}
   3406      */
   3407     @ViewDebug.ExportedProperty(category = "padding")
   3408     protected int mPaddingBottom;
   3409 
   3410     /**
   3411      * The layout insets in pixels, that is the distance in pixels between the
   3412      * visible edges of this view its bounds.
   3413      */
   3414     private Insets mLayoutInsets;
   3415 
   3416     /**
   3417      * Briefly describes the view and is primarily used for accessibility support.
   3418      */
   3419     private CharSequence mContentDescription;
   3420 
   3421     /**
   3422      * Specifies the id of a view for which this view serves as a label for
   3423      * accessibility purposes.
   3424      */
   3425     private int mLabelForId = View.NO_ID;
   3426 
   3427     /**
   3428      * Predicate for matching labeled view id with its label for
   3429      * accessibility purposes.
   3430      */
   3431     private MatchLabelForPredicate mMatchLabelForPredicate;
   3432 
   3433     /**
   3434      * Specifies a view before which this one is visited in accessibility traversal.
   3435      */
   3436     private int mAccessibilityTraversalBeforeId = NO_ID;
   3437 
   3438     /**
   3439      * Specifies a view after which this one is visited in accessibility traversal.
   3440      */
   3441     private int mAccessibilityTraversalAfterId = NO_ID;
   3442 
   3443     /**
   3444      * Predicate for matching a view by its id.
   3445      */
   3446     private MatchIdPredicate mMatchIdPredicate;
   3447 
   3448     /**
   3449      * Cache the paddingRight set by the user to append to the scrollbar's size.
   3450      *
   3451      * @hide
   3452      */
   3453     @ViewDebug.ExportedProperty(category = "padding")
   3454     protected int mUserPaddingRight;
   3455 
   3456     /**
   3457      * Cache the paddingBottom set by the user to append to the scrollbar's size.
   3458      *
   3459      * @hide
   3460      */
   3461     @ViewDebug.ExportedProperty(category = "padding")
   3462     protected int mUserPaddingBottom;
   3463 
   3464     /**
   3465      * Cache the paddingLeft set by the user to append to the scrollbar's size.
   3466      *
   3467      * @hide
   3468      */
   3469     @ViewDebug.ExportedProperty(category = "padding")
   3470     protected int mUserPaddingLeft;
   3471 
   3472     /**
   3473      * Cache the paddingStart set by the user to append to the scrollbar's size.
   3474      *
   3475      */
   3476     @ViewDebug.ExportedProperty(category = "padding")
   3477     int mUserPaddingStart;
   3478 
   3479     /**
   3480      * Cache the paddingEnd set by the user to append to the scrollbar's size.
   3481      *
   3482      */
   3483     @ViewDebug.ExportedProperty(category = "padding")
   3484     int mUserPaddingEnd;
   3485 
   3486     /**
   3487      * Cache initial left padding.
   3488      *
   3489      * @hide
   3490      */
   3491     int mUserPaddingLeftInitial;
   3492 
   3493     /**
   3494      * Cache initial right padding.
   3495      *
   3496      * @hide
   3497      */
   3498     int mUserPaddingRightInitial;
   3499 
   3500     /**
   3501      * Default undefined padding
   3502      */
   3503     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
   3504 
   3505     /**
   3506      * Cache if a left padding has been defined
   3507      */
   3508     private boolean mLeftPaddingDefined = false;
   3509 
   3510     /**
   3511      * Cache if a right padding has been defined
   3512      */
   3513     private boolean mRightPaddingDefined = false;
   3514 
   3515     /**
   3516      * @hide
   3517      */
   3518     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
   3519     /**
   3520      * @hide
   3521      */
   3522     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
   3523 
   3524     private LongSparseLongArray mMeasureCache;
   3525 
   3526     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
   3527     private Drawable mBackground;
   3528     private TintInfo mBackgroundTint;
   3529 
   3530     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
   3531     private ForegroundInfo mForegroundInfo;
   3532 
   3533     private Drawable mScrollIndicatorDrawable;
   3534 
   3535     /**
   3536      * RenderNode used for backgrounds.
   3537      * <p>
   3538      * When non-null and valid, this is expected to contain an up-to-date copy
   3539      * of the background drawable. It is cleared on temporary detach, and reset
   3540      * on cleanup.
   3541      */
   3542     private RenderNode mBackgroundRenderNode;
   3543 
   3544     private int mBackgroundResource;
   3545     private boolean mBackgroundSizeChanged;
   3546 
   3547     private String mTransitionName;
   3548 
   3549     static class TintInfo {
   3550         ColorStateList mTintList;
   3551         PorterDuff.Mode mTintMode;
   3552         boolean mHasTintMode;
   3553         boolean mHasTintList;
   3554     }
   3555 
   3556     private static class ForegroundInfo {
   3557         private Drawable mDrawable;
   3558         private TintInfo mTintInfo;
   3559         private int mGravity = Gravity.FILL;
   3560         private boolean mInsidePadding = true;
   3561         private boolean mBoundsChanged = true;
   3562         private final Rect mSelfBounds = new Rect();
   3563         private final Rect mOverlayBounds = new Rect();
   3564     }
   3565 
   3566     static class ListenerInfo {
   3567         /**
   3568          * Listener used to dispatch focus change events.
   3569          * This field should be made private, so it is hidden from the SDK.
   3570          * {@hide}
   3571          */
   3572         protected OnFocusChangeListener mOnFocusChangeListener;
   3573 
   3574         /**
   3575          * Listeners for layout change events.
   3576          */
   3577         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
   3578 
   3579         protected OnScrollChangeListener mOnScrollChangeListener;
   3580 
   3581         /**
   3582          * Listeners for attach events.
   3583          */
   3584         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
   3585 
   3586         /**
   3587          * Listener used to dispatch click events.
   3588          * This field should be made private, so it is hidden from the SDK.
   3589          * {@hide}
   3590          */
   3591         public OnClickListener mOnClickListener;
   3592 
   3593         /**
   3594          * Listener used to dispatch long click events.
   3595          * This field should be made private, so it is hidden from the SDK.
   3596          * {@hide}
   3597          */
   3598         protected OnLongClickListener mOnLongClickListener;
   3599 
   3600         /**
   3601          * Listener used to dispatch context click events. This field should be made private, so it
   3602          * is hidden from the SDK.
   3603          * {@hide}
   3604          */
   3605         protected OnContextClickListener mOnContextClickListener;
   3606 
   3607         /**
   3608          * Listener used to build the context menu.
   3609          * This field should be made private, so it is hidden from the SDK.
   3610          * {@hide}
   3611          */
   3612         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
   3613 
   3614         private OnKeyListener mOnKeyListener;
   3615 
   3616         private OnTouchListener mOnTouchListener;
   3617 
   3618         private OnHoverListener mOnHoverListener;
   3619 
   3620         private OnGenericMotionListener mOnGenericMotionListener;
   3621 
   3622         private OnDragListener mOnDragListener;
   3623 
   3624         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
   3625 
   3626         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
   3627     }
   3628 
   3629     ListenerInfo mListenerInfo;
   3630 
   3631     // Temporary values used to hold (x,y) coordinates when delegating from the
   3632     // two-arg performLongClick() method to the legacy no-arg version.
   3633     private float mLongClickX = Float.NaN;
   3634     private float mLongClickY = Float.NaN;
   3635 
   3636     /**
   3637      * The application environment this view lives in.
   3638      * This field should be made private, so it is hidden from the SDK.
   3639      * {@hide}
   3640      */
   3641     @ViewDebug.ExportedProperty(deepExport = true)
   3642     protected Context mContext;
   3643 
   3644     private final Resources mResources;
   3645 
   3646     private ScrollabilityCache mScrollCache;
   3647 
   3648     private int[] mDrawableState = null;
   3649 
   3650     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
   3651 
   3652     /**
   3653      * Animator that automatically runs based on state changes.
   3654      */
   3655     private StateListAnimator mStateListAnimator;
   3656 
   3657     /**
   3658      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
   3659      * the user may specify which view to go to next.
   3660      */
   3661     private int mNextFocusLeftId = View.NO_ID;
   3662 
   3663     /**
   3664      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
   3665      * the user may specify which view to go to next.
   3666      */
   3667     private int mNextFocusRightId = View.NO_ID;
   3668 
   3669     /**
   3670      * When this view has focus and the next focus is {@link #FOCUS_UP},
   3671      * the user may specify which view to go to next.
   3672      */
   3673     private int mNextFocusUpId = View.NO_ID;
   3674 
   3675     /**
   3676      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
   3677      * the user may specify which view to go to next.
   3678      */
   3679     private int mNextFocusDownId = View.NO_ID;
   3680 
   3681     /**
   3682      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
   3683      * the user may specify which view to go to next.
   3684      */
   3685     int mNextFocusForwardId = View.NO_ID;
   3686 
   3687     private CheckForLongPress mPendingCheckForLongPress;
   3688     private CheckForTap mPendingCheckForTap = null;
   3689     private PerformClick mPerformClick;
   3690     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
   3691 
   3692     private UnsetPressedState mUnsetPressedState;
   3693 
   3694     /**
   3695      * Whether the long press's action has been invoked.  The tap's action is invoked on the
   3696      * up event while a long press is invoked as soon as the long press duration is reached, so
   3697      * a long press could be performed before the tap is checked, in which case the tap's action
   3698      * should not be invoked.
   3699      */
   3700     private boolean mHasPerformedLongPress;
   3701 
   3702     /**
   3703      * Whether a context click button is currently pressed down. This is true when the stylus is
   3704      * touching the screen and the primary button has been pressed, or if a mouse's right button is
   3705      * pressed. This is false once the button is released or if the stylus has been lifted.
   3706      */
   3707     private boolean mInContextButtonPress;
   3708 
   3709     /**
   3710      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
   3711      * true after a stylus button press has occured, when the next up event should not be recognized
   3712      * as a tap.
   3713      */
   3714     private boolean mIgnoreNextUpEvent;
   3715 
   3716     /**
   3717      * The minimum height of the view. We'll try our best to have the height
   3718      * of this view to at least this amount.
   3719      */
   3720     @ViewDebug.ExportedProperty(category = "measurement")
   3721     private int mMinHeight;
   3722 
   3723     /**
   3724      * The minimum width of the view. We'll try our best to have the width
   3725      * of this view to at least this amount.
   3726      */
   3727     @ViewDebug.ExportedProperty(category = "measurement")
   3728     private int mMinWidth;
   3729 
   3730     /**
   3731      * The delegate to handle touch events that are physically in this view
   3732      * but should be handled by another view.
   3733      */
   3734     private TouchDelegate mTouchDelegate = null;
   3735 
   3736     /**
   3737      * Solid color to use as a background when creating the drawing cache. Enables
   3738      * the cache to use 16 bit bitmaps instead of 32 bit.
   3739      */
   3740     private int mDrawingCacheBackgroundColor = 0;
   3741 
   3742     /**
   3743      * Special tree observer used when mAttachInfo is null.
   3744      */
   3745     private ViewTreeObserver mFloatingTreeObserver;
   3746 
   3747     /**
   3748      * Cache the touch slop from the context that created the view.
   3749      */
   3750     private int mTouchSlop;
   3751 
   3752     /**
   3753      * Object that handles automatic animation of view properties.
   3754      */
   3755     private ViewPropertyAnimator mAnimator = null;
   3756 
   3757     /**
   3758      * List of registered FrameMetricsObservers.
   3759      */
   3760     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
   3761 
   3762     /**
   3763      * Flag indicating that a drag can cross window boundaries.  When
   3764      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
   3765      * with this flag set, all visible applications with targetSdkVersion >=
   3766      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
   3767      * in the drag operation and receive the dragged content.
   3768      *
   3769      * <p>If this is the only flag set, then the drag recipient will only have access to text data
   3770      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
   3771      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
   3772      */
   3773     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
   3774 
   3775     /**
   3776      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
   3777      * request read access to the content URI(s) contained in the {@link ClipData} object.
   3778      * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
   3779      */
   3780     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
   3781 
   3782     /**
   3783      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
   3784      * request write access to the content URI(s) contained in the {@link ClipData} object.
   3785      * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
   3786      */
   3787     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
   3788 
   3789     /**
   3790      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
   3791      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
   3792      * reboots until explicitly revoked with
   3793      * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
   3794      * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
   3795      */
   3796     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
   3797             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
   3798 
   3799     /**
   3800      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
   3801      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
   3802      * match against the original granted URI.
   3803      * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
   3804      */
   3805     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
   3806             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
   3807 
   3808     /**
   3809      * Flag indicating that the drag shadow will be opaque.  When
   3810      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
   3811      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
   3812      */
   3813     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
   3814 
   3815     /**
   3816      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
   3817      */
   3818     private float mVerticalScrollFactor;
   3819 
   3820     /**
   3821      * Position of the vertical scroll bar.
   3822      */
   3823     private int mVerticalScrollbarPosition;
   3824 
   3825     /**
   3826      * Position the scroll bar at the default position as determined by the system.
   3827      */
   3828     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
   3829 
   3830     /**
   3831      * Position the scroll bar along the left edge.
   3832      */
   3833     public static final int SCROLLBAR_POSITION_LEFT = 1;
   3834 
   3835     /**
   3836      * Position the scroll bar along the right edge.
   3837      */
   3838     public static final int SCROLLBAR_POSITION_RIGHT = 2;
   3839 
   3840     /**
   3841      * Indicates that the view does not have a layer.
   3842      *
   3843      * @see #getLayerType()
   3844      * @see #setLayerType(int, android.graphics.Paint)
   3845      * @see #LAYER_TYPE_SOFTWARE
   3846      * @see #LAYER_TYPE_HARDWARE
   3847      */
   3848     public static final int LAYER_TYPE_NONE = 0;
   3849 
   3850     /**
   3851      * <p>Indicates that the view has a software layer. A software layer is backed
   3852      * by a bitmap and causes the view to be rendered using Android's software
   3853      * rendering pipeline, even if hardware acceleration is enabled.</p>
   3854      *
   3855      * <p>Software layers have various usages:</p>
   3856      * <p>When the application is not using hardware acceleration, a software layer
   3857      * is useful to apply a specific color filter and/or blending mode and/or
   3858      * translucency to a view and all its children.</p>
   3859      * <p>When the application is using hardware acceleration, a software layer
   3860      * is useful to render drawing primitives not supported by the hardware
   3861      * accelerated pipeline. It can also be used to cache a complex view tree
   3862      * into a texture and reduce the complexity of drawing operations. For instance,
   3863      * when animating a complex view tree with a translation, a software layer can
   3864      * be used to render the view tree only once.</p>
   3865      * <p>Software layers should be avoided when the affected view tree updates
   3866      * often. Every update will require to re-render the software layer, which can
   3867      * potentially be slow (particularly when hardware acceleration is turned on
   3868      * since the layer will have to be uploaded into a hardware texture after every
   3869      * update.)</p>
   3870      *
   3871      * @see #getLayerType()
   3872      * @see #setLayerType(int, android.graphics.Paint)
   3873      * @see #LAYER_TYPE_NONE
   3874      * @see #LAYER_TYPE_HARDWARE
   3875      */
   3876     public static final int LAYER_TYPE_SOFTWARE = 1;
   3877 
   3878     /**
   3879      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
   3880      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
   3881      * OpenGL hardware) and causes the view to be rendered using Android's hardware
   3882      * rendering pipeline, but only if hardware acceleration is turned on for the
   3883      * view hierarchy. When hardware acceleration is turned off, hardware layers
   3884      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
   3885      *
   3886      * <p>A hardware layer is useful to apply a specific color filter and/or
   3887      * blending mode and/or translucency to a view and all its children.</p>
   3888      * <p>A hardware layer can be used to cache a complex view tree into a
   3889      * texture and reduce the complexity of drawing operations. For instance,
   3890      * when animating a complex view tree with a translation, a hardware layer can
   3891      * be used to render the view tree only once.</p>
   3892      * <p>A hardware layer can also be used to increase the rendering quality when
   3893      * rotation transformations are applied on a view. It can also be used to
   3894      * prevent potential clipping issues when applying 3D transforms on a view.</p>
   3895      *
   3896      * @see #getLayerType()
   3897      * @see #setLayerType(int, android.graphics.Paint)
   3898      * @see #LAYER_TYPE_NONE
   3899      * @see #LAYER_TYPE_SOFTWARE
   3900      */
   3901     public static final int LAYER_TYPE_HARDWARE = 2;
   3902 
   3903     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
   3904             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
   3905             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
   3906             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
   3907     })
   3908     int mLayerType = LAYER_TYPE_NONE;
   3909     Paint mLayerPaint;
   3910 
   3911     /**
   3912      * Set to true when drawing cache is enabled and cannot be created.
   3913      *
   3914      * @hide
   3915      */
   3916     public boolean mCachingFailed;
   3917     private Bitmap mDrawingCache;
   3918     private Bitmap mUnscaledDrawingCache;
   3919 
   3920     /**
   3921      * RenderNode holding View properties, potentially holding a DisplayList of View content.
   3922      * <p>
   3923      * When non-null and valid, this is expected to contain an up-to-date copy
   3924      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
   3925      * cleanup.
   3926      */
   3927     final RenderNode mRenderNode;
   3928 
   3929     /**
   3930      * Set to true when the view is sending hover accessibility events because it
   3931      * is the innermost hovered view.
   3932      */
   3933     private boolean mSendingHoverAccessibilityEvents;
   3934 
   3935     /**
   3936      * Delegate for injecting accessibility functionality.
   3937      */
   3938     AccessibilityDelegate mAccessibilityDelegate;
   3939 
   3940     /**
   3941      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
   3942      * and add/remove objects to/from the overlay directly through the Overlay methods.
   3943      */
   3944     ViewOverlay mOverlay;
   3945 
   3946     /**
   3947      * The currently active parent view for receiving delegated nested scrolling events.
   3948      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
   3949      * by {@link #stopNestedScroll()} at the same point where we clear
   3950      * requestDisallowInterceptTouchEvent.
   3951      */
   3952     private ViewParent mNestedScrollingParent;
   3953 
   3954     /**
   3955      * Consistency verifier for debugging purposes.
   3956      * @hide
   3957      */
   3958     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
   3959             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
   3960                     new InputEventConsistencyVerifier(this, 0) : null;
   3961 
   3962     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
   3963 
   3964     private int[] mTempNestedScrollConsumed;
   3965 
   3966     /**
   3967      * An overlay is going to draw this View instead of being drawn as part of this
   3968      * View's parent. mGhostView is the View in the Overlay that must be invalidated
   3969      * when this view is invalidated.
   3970      */
   3971     GhostView mGhostView;
   3972 
   3973     /**
   3974      * Holds pairs of adjacent attribute data: attribute name followed by its value.
   3975      * @hide
   3976      */
   3977     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
   3978     public String[] mAttributes;
   3979 
   3980     /**
   3981      * Maps a Resource id to its name.
   3982      */
   3983     private static SparseArray<String> mAttributeMap;
   3984 
   3985     /**
   3986      * Queue of pending runnables. Used to postpone calls to post() until this
   3987      * view is attached and has a handler.
   3988      */
   3989     private HandlerActionQueue mRunQueue;
   3990 
   3991     /**
   3992      * The pointer icon when the mouse hovers on this view. The default is null.
   3993      */
   3994     private PointerIcon mPointerIcon;
   3995 
   3996     /**
   3997      * @hide
   3998      */
   3999     String mStartActivityRequestWho;
   4000 
   4001     @Nullable
   4002     private RoundScrollbarRenderer mRoundScrollbarRenderer;
   4003 
   4004     /**
   4005      * Simple constructor to use when creating a view from code.
   4006      *
   4007      * @param context The Context the view is running in, through which it can
   4008      *        access the current theme, resources, etc.
   4009      */
   4010     public View(Context context) {
   4011         mContext = context;
   4012         mResources = context != null ? context.getResources() : null;
   4013         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
   4014         // Set some flags defaults
   4015         mPrivateFlags2 =
   4016                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
   4017                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
   4018                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
   4019                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
   4020                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
   4021                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
   4022         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
   4023         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
   4024         mUserPaddingStart = UNDEFINED_PADDING;
   4025         mUserPaddingEnd = UNDEFINED_PADDING;
   4026         mRenderNode = RenderNode.create(getClass().getName(), this);
   4027 
   4028         if (!sCompatibilityDone && context != null) {
   4029             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   4030 
   4031             // Older apps may need this compatibility hack for measurement.
   4032             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
   4033 
   4034             // Older apps expect onMeasure() to always be called on a layout pass, regardless
   4035             // of whether a layout was requested on that View.
   4036             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
   4037 
   4038             Canvas.sCompatibilityRestore = targetSdkVersion < M;
   4039 
   4040             // In M and newer, our widgets can pass a "hint" value in the size
   4041             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
   4042             // know what the expected parent size is going to be, so e.g. list items can size
   4043             // themselves at 1/3 the size of their container. It breaks older apps though,
   4044             // specifically apps that use some popular open source libraries.
   4045             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
   4046 
   4047             // Old versions of the platform would give different results from
   4048             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
   4049             // modes, so we always need to run an additional EXACTLY pass.
   4050             sAlwaysRemeasureExactly = targetSdkVersion <= M;
   4051 
   4052             // Prior to N, layout params could change without requiring a
   4053             // subsequent call to setLayoutParams() and they would usually
   4054             // work. Partial layout breaks this assumption.
   4055             sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
   4056 
   4057             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
   4058             // On N+, we throw, but that breaks compatibility with apps that use these methods.
   4059             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
   4060 
   4061             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
   4062             // in apps so we target check it to avoid breaking existing apps.
   4063             sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
   4064 
   4065             sCascadedDragDrop = targetSdkVersion < N;
   4066 
   4067             sCompatibilityDone = true;
   4068         }
   4069     }
   4070 
   4071     /**
   4072      * Constructor that is called when inflating a view from XML. This is called
   4073      * when a view is being constructed from an XML file, supplying attributes
   4074      * that were specified in the XML file. This version uses a default style of
   4075      * 0, so the only attribute values applied are those in the Context's Theme
   4076      * and the given AttributeSet.
   4077      *
   4078      * <p>
   4079      * The method onFinishInflate() will be called after all children have been
   4080      * added.
   4081      *
   4082      * @param context The Context the view is running in, through which it can
   4083      *        access the current theme, resources, etc.
   4084      * @param attrs The attributes of the XML tag that is inflating the view.
   4085      * @see #View(Context, AttributeSet, int)
   4086      */
   4087     public View(Context context, @Nullable AttributeSet attrs) {
   4088         this(context, attrs, 0);
   4089     }
   4090 
   4091     /**
   4092      * Perform inflation from XML and apply a class-specific base style from a
   4093      * theme attribute. This constructor of View allows subclasses to use their
   4094      * own base style when they are inflating. For example, a Button class's
   4095      * constructor would call this version of the super class constructor and
   4096      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
   4097      * allows the theme's button style to modify all of the base view attributes
   4098      * (in particular its background) as well as the Button class's attributes.
   4099      *
   4100      * @param context The Context the view is running in, through which it can
   4101      *        access the current theme, resources, etc.
   4102      * @param attrs The attributes of the XML tag that is inflating the view.
   4103      * @param defStyleAttr An attribute in the current theme that contains a
   4104      *        reference to a style resource that supplies default values for
   4105      *        the view. Can be 0 to not look for defaults.
   4106      * @see #View(Context, AttributeSet)
   4107      */
   4108     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
   4109         this(context, attrs, defStyleAttr, 0);
   4110     }
   4111 
   4112     /**
   4113      * Perform inflation from XML and apply a class-specific base style from a
   4114      * theme attribute or style resource. This constructor of View allows
   4115      * subclasses to use their own base style when they are inflating.
   4116      * <p>
   4117      * When determining the final value of a particular attribute, there are
   4118      * four inputs that come into play:
   4119      * <ol>
   4120      * <li>Any attribute values in the given AttributeSet.
   4121      * <li>The style resource specified in the AttributeSet (named "style").
   4122      * <li>The default style specified by <var>defStyleAttr</var>.
   4123      * <li>The default style specified by <var>defStyleRes</var>.
   4124      * <li>The base values in this theme.
   4125      * </ol>
   4126      * <p>
   4127      * Each of these inputs is considered in-order, with the first listed taking
   4128      * precedence over the following ones. In other words, if in the
   4129      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
   4130      * , then the button's text will <em>always</em> be black, regardless of
   4131      * what is specified in any of the styles.
   4132      *
   4133      * @param context The Context the view is running in, through which it can
   4134      *        access the current theme, resources, etc.
   4135      * @param attrs The attributes of the XML tag that is inflating the view.
   4136      * @param defStyleAttr An attribute in the current theme that contains a
   4137      *        reference to a style resource that supplies default values for
   4138      *        the view. Can be 0 to not look for defaults.
   4139      * @param defStyleRes A resource identifier of a style resource that
   4140      *        supplies default values for the view, used only if
   4141      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
   4142      *        to not look for defaults.
   4143      * @see #View(Context, AttributeSet, int)
   4144      */
   4145     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
   4146         this(context);
   4147 
   4148         final TypedArray a = context.obtainStyledAttributes(
   4149                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
   4150 
   4151         if (mDebugViewAttributes) {
   4152             saveAttributeData(attrs, a);
   4153         }
   4154 
   4155         Drawable background = null;
   4156 
   4157         int leftPadding = -1;
   4158         int topPadding = -1;
   4159         int rightPadding = -1;
   4160         int bottomPadding = -1;
   4161         int startPadding = UNDEFINED_PADDING;
   4162         int endPadding = UNDEFINED_PADDING;
   4163 
   4164         int padding = -1;
   4165 
   4166         int viewFlagValues = 0;
   4167         int viewFlagMasks = 0;
   4168 
   4169         boolean setScrollContainer = false;
   4170 
   4171         int x = 0;
   4172         int y = 0;
   4173 
   4174         float tx = 0;
   4175         float ty = 0;
   4176         float tz = 0;
   4177         float elevation = 0;
   4178         float rotation = 0;
   4179         float rotationX = 0;
   4180         float rotationY = 0;
   4181         float sx = 1f;
   4182         float sy = 1f;
   4183         boolean transformSet = false;
   4184 
   4185         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
   4186         int overScrollMode = mOverScrollMode;
   4187         boolean initializeScrollbars = false;
   4188         boolean initializeScrollIndicators = false;
   4189 
   4190         boolean startPaddingDefined = false;
   4191         boolean endPaddingDefined = false;
   4192         boolean leftPaddingDefined = false;
   4193         boolean rightPaddingDefined = false;
   4194 
   4195         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   4196 
   4197         final int N = a.getIndexCount();
   4198         for (int i = 0; i < N; i++) {
   4199             int attr = a.getIndex(i);
   4200             switch (attr) {
   4201                 case com.android.internal.R.styleable.View_background:
   4202                     background = a.getDrawable(attr);
   4203                     break;
   4204                 case com.android.internal.R.styleable.View_padding:
   4205                     padding = a.getDimensionPixelSize(attr, -1);
   4206                     mUserPaddingLeftInitial = padding;
   4207                     mUserPaddingRightInitial = padding;
   4208                     leftPaddingDefined = true;
   4209                     rightPaddingDefined = true;
   4210                     break;
   4211                  case com.android.internal.R.styleable.View_paddingLeft:
   4212                     leftPadding = a.getDimensionPixelSize(attr, -1);
   4213                     mUserPaddingLeftInitial = leftPadding;
   4214                     leftPaddingDefined = true;
   4215                     break;
   4216                 case com.android.internal.R.styleable.View_paddingTop:
   4217                     topPadding = a.getDimensionPixelSize(attr, -1);
   4218                     break;
   4219                 case com.android.internal.R.styleable.View_paddingRight:
   4220                     rightPadding = a.getDimensionPixelSize(attr, -1);
   4221                     mUserPaddingRightInitial = rightPadding;
   4222                     rightPaddingDefined = true;
   4223                     break;
   4224                 case com.android.internal.R.styleable.View_paddingBottom:
   4225                     bottomPadding = a.getDimensionPixelSize(attr, -1);
   4226                     break;
   4227                 case com.android.internal.R.styleable.View_paddingStart:
   4228                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   4229                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
   4230                     break;
   4231                 case com.android.internal.R.styleable.View_paddingEnd:
   4232                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   4233                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
   4234                     break;
   4235                 case com.android.internal.R.styleable.View_scrollX:
   4236                     x = a.getDimensionPixelOffset(attr, 0);
   4237                     break;
   4238                 case com.android.internal.R.styleable.View_scrollY:
   4239                     y = a.getDimensionPixelOffset(attr, 0);
   4240                     break;
   4241                 case com.android.internal.R.styleable.View_alpha:
   4242                     setAlpha(a.getFloat(attr, 1f));
   4243                     break;
   4244                 case com.android.internal.R.styleable.View_transformPivotX:
   4245                     setPivotX(a.getDimension(attr, 0));
   4246                     break;
   4247                 case com.android.internal.R.styleable.View_transformPivotY:
   4248                     setPivotY(a.getDimension(attr, 0));
   4249                     break;
   4250                 case com.android.internal.R.styleable.View_translationX:
   4251                     tx = a.getDimension(attr, 0);
   4252                     transformSet = true;
   4253                     break;
   4254                 case com.android.internal.R.styleable.View_translationY:
   4255                     ty = a.getDimension(attr, 0);
   4256                     transformSet = true;
   4257                     break;
   4258                 case com.android.internal.R.styleable.View_translationZ:
   4259                     tz = a.getDimension(attr, 0);
   4260                     transformSet = true;
   4261                     break;
   4262                 case com.android.internal.R.styleable.View_elevation:
   4263                     elevation = a.getDimension(attr, 0);
   4264                     transformSet = true;
   4265                     break;
   4266                 case com.android.internal.R.styleable.View_rotation:
   4267                     rotation = a.getFloat(attr, 0);
   4268                     transformSet = true;
   4269                     break;
   4270                 case com.android.internal.R.styleable.View_rotationX:
   4271                     rotationX = a.getFloat(attr, 0);
   4272                     transformSet = true;
   4273                     break;
   4274                 case com.android.internal.R.styleable.View_rotationY:
   4275                     rotationY = a.getFloat(attr, 0);
   4276                     transformSet = true;
   4277                     break;
   4278                 case com.android.internal.R.styleable.View_scaleX:
   4279                     sx = a.getFloat(attr, 1f);
   4280                     transformSet = true;
   4281                     break;
   4282                 case com.android.internal.R.styleable.View_scaleY:
   4283                     sy = a.getFloat(attr, 1f);
   4284                     transformSet = true;
   4285                     break;
   4286                 case com.android.internal.R.styleable.View_id:
   4287                     mID = a.getResourceId(attr, NO_ID);
   4288                     break;
   4289                 case com.android.internal.R.styleable.View_tag:
   4290                     mTag = a.getText(attr);
   4291                     break;
   4292                 case com.android.internal.R.styleable.View_fitsSystemWindows:
   4293                     if (a.getBoolean(attr, false)) {
   4294                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
   4295                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
   4296                     }
   4297                     break;
   4298                 case com.android.internal.R.styleable.View_focusable:
   4299                     if (a.getBoolean(attr, false)) {
   4300                         viewFlagValues |= FOCUSABLE;
   4301                         viewFlagMasks |= FOCUSABLE_MASK;
   4302                     }
   4303                     break;
   4304                 case com.android.internal.R.styleable.View_focusableInTouchMode:
   4305                     if (a.getBoolean(attr, false)) {
   4306                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
   4307                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
   4308                     }
   4309                     break;
   4310                 case com.android.internal.R.styleable.View_clickable:
   4311                     if (a.getBoolean(attr, false)) {
   4312                         viewFlagValues |= CLICKABLE;
   4313                         viewFlagMasks |= CLICKABLE;
   4314                     }
   4315                     break;
   4316                 case com.android.internal.R.styleable.View_longClickable:
   4317                     if (a.getBoolean(attr, false)) {
   4318                         viewFlagValues |= LONG_CLICKABLE;
   4319                         viewFlagMasks |= LONG_CLICKABLE;
   4320                     }
   4321                     break;
   4322                 case com.android.internal.R.styleable.View_contextClickable:
   4323                     if (a.getBoolean(attr, false)) {
   4324                         viewFlagValues |= CONTEXT_CLICKABLE;
   4325                         viewFlagMasks |= CONTEXT_CLICKABLE;
   4326                     }
   4327                     break;
   4328                 case com.android.internal.R.styleable.View_saveEnabled:
   4329                     if (!a.getBoolean(attr, true)) {
   4330                         viewFlagValues |= SAVE_DISABLED;
   4331                         viewFlagMasks |= SAVE_DISABLED_MASK;
   4332                     }
   4333                     break;
   4334                 case com.android.internal.R.styleable.View_duplicateParentState:
   4335                     if (a.getBoolean(attr, false)) {
   4336                         viewFlagValues |= DUPLICATE_PARENT_STATE;
   4337                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
   4338                     }
   4339                     break;
   4340                 case com.android.internal.R.styleable.View_visibility:
   4341                     final int visibility = a.getInt(attr, 0);
   4342                     if (visibility != 0) {
   4343                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
   4344                         viewFlagMasks |= VISIBILITY_MASK;
   4345                     }
   4346                     break;
   4347                 case com.android.internal.R.styleable.View_layoutDirection:
   4348                     // Clear any layout direction flags (included resolved bits) already set
   4349                     mPrivateFlags2 &=
   4350                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
   4351                     // Set the layout direction flags depending on the value of the attribute
   4352                     final int layoutDirection = a.getInt(attr, -1);
   4353                     final int value = (layoutDirection != -1) ?
   4354                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
   4355                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
   4356                     break;
   4357                 case com.android.internal.R.styleable.View_drawingCacheQuality:
   4358                     final int cacheQuality = a.getInt(attr, 0);
   4359                     if (cacheQuality != 0) {
   4360                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
   4361                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
   4362                     }
   4363                     break;
   4364                 case com.android.internal.R.styleable.View_contentDescription:
   4365                     setContentDescription(a.getString(attr));
   4366                     break;
   4367                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
   4368                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
   4369                     break;
   4370                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
   4371                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
   4372                     break;
   4373                 case com.android.internal.R.styleable.View_labelFor:
   4374                     setLabelFor(a.getResourceId(attr, NO_ID));
   4375                     break;
   4376                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
   4377                     if (!a.getBoolean(attr, true)) {
   4378                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
   4379                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
   4380                     }
   4381                     break;
   4382                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
   4383                     if (!a.getBoolean(attr, true)) {
   4384                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
   4385                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
   4386                     }
   4387                     break;
   4388                 case R.styleable.View_scrollbars:
   4389                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
   4390                     if (scrollbars != SCROLLBARS_NONE) {
   4391                         viewFlagValues |= scrollbars;
   4392                         viewFlagMasks |= SCROLLBARS_MASK;
   4393                         initializeScrollbars = true;
   4394                     }
   4395                     break;
   4396                 //noinspection deprecation
   4397                 case R.styleable.View_fadingEdge:
   4398                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
   4399                         // Ignore the attribute starting with ICS
   4400                         break;
   4401                     }
   4402                     // With builds < ICS, fall through and apply fading edges
   4403                 case R.styleable.View_requiresFadingEdge:
   4404                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
   4405                     if (fadingEdge != FADING_EDGE_NONE) {
   4406                         viewFlagValues |= fadingEdge;
   4407                         viewFlagMasks |= FADING_EDGE_MASK;
   4408                         initializeFadingEdgeInternal(a);
   4409                     }
   4410                     break;
   4411                 case R.styleable.View_scrollbarStyle:
   4412                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
   4413                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   4414                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
   4415                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
   4416                     }
   4417                     break;
   4418                 case R.styleable.View_isScrollContainer:
   4419                     setScrollContainer = true;
   4420                     if (a.getBoolean(attr, false)) {
   4421                         setScrollContainer(true);
   4422                     }
   4423                     break;
   4424                 case com.android.internal.R.styleable.View_keepScreenOn:
   4425                     if (a.getBoolean(attr, false)) {
   4426                         viewFlagValues |= KEEP_SCREEN_ON;
   4427                         viewFlagMasks |= KEEP_SCREEN_ON;
   4428                     }
   4429                     break;
   4430                 case R.styleable.View_filterTouchesWhenObscured:
   4431                     if (a.getBoolean(attr, false)) {
   4432                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
   4433                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
   4434                     }
   4435                     break;
   4436                 case R.styleable.View_nextFocusLeft:
   4437                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
   4438                     break;
   4439                 case R.styleable.View_nextFocusRight:
   4440                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
   4441                     break;
   4442                 case R.styleable.View_nextFocusUp:
   4443                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
   4444                     break;
   4445                 case R.styleable.View_nextFocusDown:
   4446                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
   4447                     break;
   4448                 case R.styleable.View_nextFocusForward:
   4449                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
   4450                     break;
   4451                 case R.styleable.View_minWidth:
   4452                     mMinWidth = a.getDimensionPixelSize(attr, 0);
   4453                     break;
   4454                 case R.styleable.View_minHeight:
   4455                     mMinHeight = a.getDimensionPixelSize(attr, 0);
   4456                     break;
   4457                 case R.styleable.View_onClick:
   4458                     if (context.isRestricted()) {
   4459                         throw new IllegalStateException("The android:onClick attribute cannot "
   4460                                 + "be used within a restricted context");
   4461                     }
   4462 
   4463                     final String handlerName = a.getString(attr);
   4464                     if (handlerName != null) {
   4465                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
   4466                     }
   4467                     break;
   4468                 case R.styleable.View_overScrollMode:
   4469                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
   4470                     break;
   4471                 case R.styleable.View_verticalScrollbarPosition:
   4472                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
   4473                     break;
   4474                 case R.styleable.View_layerType:
   4475                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
   4476                     break;
   4477                 case R.styleable.View_textDirection:
   4478                     // Clear any text direction flag already set
   4479                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   4480                     // Set the text direction flags depending on the value of the attribute
   4481                     final int textDirection = a.getInt(attr, -1);
   4482                     if (textDirection != -1) {
   4483                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
   4484                     }
   4485                     break;
   4486                 case R.styleable.View_textAlignment:
   4487                     // Clear any text alignment flag already set
   4488                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   4489                     // Set the text alignment flag depending on the value of the attribute
   4490                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
   4491                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
   4492                     break;
   4493                 case R.styleable.View_importantForAccessibility:
   4494                     setImportantForAccessibility(a.getInt(attr,
   4495                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
   4496                     break;
   4497                 case R.styleable.View_accessibilityLiveRegion:
   4498                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
   4499                     break;
   4500                 case R.styleable.View_transitionName:
   4501                     setTransitionName(a.getString(attr));
   4502                     break;
   4503                 case R.styleable.View_nestedScrollingEnabled:
   4504                     setNestedScrollingEnabled(a.getBoolean(attr, false));
   4505                     break;
   4506                 case R.styleable.View_stateListAnimator:
   4507                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
   4508                             a.getResourceId(attr, 0)));
   4509                     break;
   4510                 case R.styleable.View_backgroundTint:
   4511                     // This will get applied later during setBackground().
   4512                     if (mBackgroundTint == null) {
   4513                         mBackgroundTint = new TintInfo();
   4514                     }
   4515                     mBackgroundTint.mTintList = a.getColorStateList(
   4516                             R.styleable.View_backgroundTint);
   4517                     mBackgroundTint.mHasTintList = true;
   4518                     break;
   4519                 case R.styleable.View_backgroundTintMode:
   4520                     // This will get applied later during setBackground().
   4521                     if (mBackgroundTint == null) {
   4522                         mBackgroundTint = new TintInfo();
   4523                     }
   4524                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
   4525                             R.styleable.View_backgroundTintMode, -1), null);
   4526                     mBackgroundTint.mHasTintMode = true;
   4527                     break;
   4528                 case R.styleable.View_outlineProvider:
   4529                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
   4530                             PROVIDER_BACKGROUND));
   4531                     break;
   4532                 case R.styleable.View_foreground:
   4533                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4534                         setForeground(a.getDrawable(attr));
   4535                     }
   4536                     break;
   4537                 case R.styleable.View_foregroundGravity:
   4538                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4539                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
   4540                     }
   4541                     break;
   4542                 case R.styleable.View_foregroundTintMode:
   4543                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4544                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
   4545                     }
   4546                     break;
   4547                 case R.styleable.View_foregroundTint:
   4548                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4549                         setForegroundTintList(a.getColorStateList(attr));
   4550                     }
   4551                     break;
   4552                 case R.styleable.View_foregroundInsidePadding:
   4553                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4554                         if (mForegroundInfo == null) {
   4555                             mForegroundInfo = new ForegroundInfo();
   4556                         }
   4557                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
   4558                                 mForegroundInfo.mInsidePadding);
   4559                     }
   4560                     break;
   4561                 case R.styleable.View_scrollIndicators:
   4562                     final int scrollIndicators =
   4563                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
   4564                                     & SCROLL_INDICATORS_PFLAG3_MASK;
   4565                     if (scrollIndicators != 0) {
   4566                         mPrivateFlags3 |= scrollIndicators;
   4567                         initializeScrollIndicators = true;
   4568                     }
   4569                     break;
   4570                 case R.styleable.View_pointerIcon:
   4571                     final int resourceId = a.getResourceId(attr, 0);
   4572                     if (resourceId != 0) {
   4573                         setPointerIcon(PointerIcon.load(
   4574                                 context.getResources(), resourceId));
   4575                     } else {
   4576                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
   4577                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
   4578                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
   4579                         }
   4580                     }
   4581                     break;
   4582                 case R.styleable.View_forceHasOverlappingRendering:
   4583                     if (a.peekValue(attr) != null) {
   4584                         forceHasOverlappingRendering(a.getBoolean(attr, true));
   4585                     }
   4586                     break;
   4587 
   4588             }
   4589         }
   4590 
   4591         setOverScrollMode(overScrollMode);
   4592 
   4593         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
   4594         // the resolved layout direction). Those cached values will be used later during padding
   4595         // resolution.
   4596         mUserPaddingStart = startPadding;
   4597         mUserPaddingEnd = endPadding;
   4598 
   4599         if (background != null) {
   4600             setBackground(background);
   4601         }
   4602 
   4603         // setBackground above will record that padding is currently provided by the background.
   4604         // If we have padding specified via xml, record that here instead and use it.
   4605         mLeftPaddingDefined = leftPaddingDefined;
   4606         mRightPaddingDefined = rightPaddingDefined;
   4607 
   4608         if (padding >= 0) {
   4609             leftPadding = padding;
   4610             topPadding = padding;
   4611             rightPadding = padding;
   4612             bottomPadding = padding;
   4613             mUserPaddingLeftInitial = padding;
   4614             mUserPaddingRightInitial = padding;
   4615         }
   4616 
   4617         if (isRtlCompatibilityMode()) {
   4618             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
   4619             // left / right padding are used if defined (meaning here nothing to do). If they are not
   4620             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
   4621             // start / end and resolve them as left / right (layout direction is not taken into account).
   4622             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   4623             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   4624             // defined.
   4625             if (!mLeftPaddingDefined && startPaddingDefined) {
   4626                 leftPadding = startPadding;
   4627             }
   4628             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
   4629             if (!mRightPaddingDefined && endPaddingDefined) {
   4630                 rightPadding = endPadding;
   4631             }
   4632             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
   4633         } else {
   4634             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
   4635             // values defined. Otherwise, left /right values are used.
   4636             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   4637             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   4638             // defined.
   4639             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
   4640 
   4641             if (mLeftPaddingDefined && !hasRelativePadding) {
   4642                 mUserPaddingLeftInitial = leftPadding;
   4643             }
   4644             if (mRightPaddingDefined && !hasRelativePadding) {
   4645                 mUserPaddingRightInitial = rightPadding;
   4646             }
   4647         }
   4648 
   4649         internalSetPadding(
   4650                 mUserPaddingLeftInitial,
   4651                 topPadding >= 0 ? topPadding : mPaddingTop,
   4652                 mUserPaddingRightInitial,
   4653                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
   4654 
   4655         if (viewFlagMasks != 0) {
   4656             setFlags(viewFlagValues, viewFlagMasks);
   4657         }
   4658 
   4659         if (initializeScrollbars) {
   4660             initializeScrollbarsInternal(a);
   4661         }
   4662 
   4663         if (initializeScrollIndicators) {
   4664             initializeScrollIndicatorsInternal();
   4665         }
   4666 
   4667         a.recycle();
   4668 
   4669         // Needs to be called after mViewFlags is set
   4670         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   4671             recomputePadding();
   4672         }
   4673 
   4674         if (x != 0 || y != 0) {
   4675             scrollTo(x, y);
   4676         }
   4677 
   4678         if (transformSet) {
   4679             setTranslationX(tx);
   4680             setTranslationY(ty);
   4681             setTranslationZ(tz);
   4682             setElevation(elevation);
   4683             setRotation(rotation);
   4684             setRotationX(rotationX);
   4685             setRotationY(rotationY);
   4686             setScaleX(sx);
   4687             setScaleY(sy);
   4688         }
   4689 
   4690         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
   4691             setScrollContainer(true);
   4692         }
   4693 
   4694         computeOpaqueFlags();
   4695     }
   4696 
   4697     /**
   4698      * An implementation of OnClickListener that attempts to lazily load a
   4699      * named click handling method from a parent or ancestor context.
   4700      */
   4701     private static class DeclaredOnClickListener implements OnClickListener {
   4702         private final View mHostView;
   4703         private final String mMethodName;
   4704 
   4705         private Method mResolvedMethod;
   4706         private Context mResolvedContext;
   4707 
   4708         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
   4709             mHostView = hostView;
   4710             mMethodName = methodName;
   4711         }
   4712 
   4713         @Override
   4714         public void onClick(@NonNull View v) {
   4715             if (mResolvedMethod == null) {
   4716                 resolveMethod(mHostView.getContext(), mMethodName);
   4717             }
   4718 
   4719             try {
   4720                 mResolvedMethod.invoke(mResolvedContext, v);
   4721             } catch (IllegalAccessException e) {
   4722                 throw new IllegalStateException(
   4723                         "Could not execute non-public method for android:onClick", e);
   4724             } catch (InvocationTargetException e) {
   4725                 throw new IllegalStateException(
   4726                         "Could not execute method for android:onClick", e);
   4727             }
   4728         }
   4729 
   4730         @NonNull
   4731         private void resolveMethod(@Nullable Context context, @NonNull String name) {
   4732             while (context != null) {
   4733                 try {
   4734                     if (!context.isRestricted()) {
   4735                         final Method method = context.getClass().getMethod(mMethodName, View.class);
   4736                         if (method != null) {
   4737                             mResolvedMethod = method;
   4738                             mResolvedContext = context;
   4739                             return;
   4740                         }
   4741                     }
   4742                 } catch (NoSuchMethodException e) {
   4743                     // Failed to find method, keep searching up the hierarchy.
   4744                 }
   4745 
   4746                 if (context instanceof ContextWrapper) {
   4747                     context = ((ContextWrapper) context).getBaseContext();
   4748                 } else {
   4749                     // Can't search up the hierarchy, null out and fail.
   4750                     context = null;
   4751                 }
   4752             }
   4753 
   4754             final int id = mHostView.getId();
   4755             final String idText = id == NO_ID ? "" : " with id '"
   4756                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
   4757             throw new IllegalStateException("Could not find method " + mMethodName
   4758                     + "(View) in a parent or ancestor Context for android:onClick "
   4759                     + "attribute defined on view " + mHostView.getClass() + idText);
   4760         }
   4761     }
   4762 
   4763     /**
   4764      * Non-public constructor for use in testing
   4765      */
   4766     View() {
   4767         mResources = null;
   4768         mRenderNode = RenderNode.create(getClass().getName(), this);
   4769     }
   4770 
   4771     private static SparseArray<String> getAttributeMap() {
   4772         if (mAttributeMap == null) {
   4773             mAttributeMap = new SparseArray<>();
   4774         }
   4775         return mAttributeMap;
   4776     }
   4777 
   4778     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
   4779         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
   4780         final int indexCount = t.getIndexCount();
   4781         final String[] attributes = new String[(attrsCount + indexCount) * 2];
   4782 
   4783         int i = 0;
   4784 
   4785         // Store raw XML attributes.
   4786         for (int j = 0; j < attrsCount; ++j) {
   4787             attributes[i] = attrs.getAttributeName(j);
   4788             attributes[i + 1] = attrs.getAttributeValue(j);
   4789             i += 2;
   4790         }
   4791 
   4792         // Store resolved styleable attributes.
   4793         final Resources res = t.getResources();
   4794         final SparseArray<String> attributeMap = getAttributeMap();
   4795         for (int j = 0; j < indexCount; ++j) {
   4796             final int index = t.getIndex(j);
   4797             if (!t.hasValueOrEmpty(index)) {
   4798                 // Value is undefined. Skip it.
   4799                 continue;
   4800             }
   4801 
   4802             final int resourceId = t.getResourceId(index, 0);
   4803             if (resourceId == 0) {
   4804                 // Value is not a reference. Skip it.
   4805                 continue;
   4806             }
   4807 
   4808             String resourceName = attributeMap.get(resourceId);
   4809             if (resourceName == null) {
   4810                 try {
   4811                     resourceName = res.getResourceName(resourceId);
   4812                 } catch (Resources.NotFoundException e) {
   4813                     resourceName = "0x" + Integer.toHexString(resourceId);
   4814                 }
   4815                 attributeMap.put(resourceId, resourceName);
   4816             }
   4817 
   4818             attributes[i] = resourceName;
   4819             attributes[i + 1] = t.getString(index);
   4820             i += 2;
   4821         }
   4822 
   4823         // Trim to fit contents.
   4824         final String[] trimmed = new String[i];
   4825         System.arraycopy(attributes, 0, trimmed, 0, i);
   4826         mAttributes = trimmed;
   4827     }
   4828 
   4829     public String toString() {
   4830         StringBuilder out = new StringBuilder(128);
   4831         out.append(getClass().getName());
   4832         out.append('{');
   4833         out.append(Integer.toHexString(System.identityHashCode(this)));
   4834         out.append(' ');
   4835         switch (mViewFlags&VISIBILITY_MASK) {
   4836             case VISIBLE: out.append('V'); break;
   4837             case INVISIBLE: out.append('I'); break;
   4838             case GONE: out.append('G'); break;
   4839             default: out.append('.'); break;
   4840         }
   4841         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
   4842         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
   4843         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
   4844         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
   4845         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
   4846         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
   4847         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
   4848         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
   4849         out.append(' ');
   4850         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
   4851         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
   4852         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
   4853         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
   4854             out.append('p');
   4855         } else {
   4856             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
   4857         }
   4858         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
   4859         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
   4860         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
   4861         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
   4862         out.append(' ');
   4863         out.append(mLeft);
   4864         out.append(',');
   4865         out.append(mTop);
   4866         out.append('-');
   4867         out.append(mRight);
   4868         out.append(',');
   4869         out.append(mBottom);
   4870         final int id = getId();
   4871         if (id != NO_ID) {
   4872             out.append(" #");
   4873             out.append(Integer.toHexString(id));
   4874             final Resources r = mResources;
   4875             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
   4876                 try {
   4877                     String pkgname;
   4878                     switch (id&0xff000000) {
   4879                         case 0x7f000000:
   4880                             pkgname="app";
   4881                             break;
   4882                         case 0x01000000:
   4883                             pkgname="android";
   4884                             break;
   4885                         default:
   4886                             pkgname = r.getResourcePackageName(id);
   4887                             break;
   4888                     }
   4889                     String typename = r.getResourceTypeName(id);
   4890                     String entryname = r.getResourceEntryName(id);
   4891                     out.append(" ");
   4892                     out.append(pkgname);
   4893                     out.append(":");
   4894                     out.append(typename);
   4895                     out.append("/");
   4896                     out.append(entryname);
   4897                 } catch (Resources.NotFoundException e) {
   4898                 }
   4899             }
   4900         }
   4901         out.append("}");
   4902         return out.toString();
   4903     }
   4904 
   4905     /**
   4906      * <p>
   4907      * Initializes the fading edges from a given set of styled attributes. This
   4908      * method should be called by subclasses that need fading edges and when an
   4909      * instance of these subclasses is created programmatically rather than
   4910      * being inflated from XML. This method is automatically called when the XML
   4911      * is inflated.
   4912      * </p>
   4913      *
   4914      * @param a the styled attributes set to initialize the fading edges from
   4915      *
   4916      * @removed
   4917      */
   4918     protected void initializeFadingEdge(TypedArray a) {
   4919         // This method probably shouldn't have been included in the SDK to begin with.
   4920         // It relies on 'a' having been initialized using an attribute filter array that is
   4921         // not publicly available to the SDK. The old method has been renamed
   4922         // to initializeFadingEdgeInternal and hidden for framework use only;
   4923         // this one initializes using defaults to make it safe to call for apps.
   4924 
   4925         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   4926 
   4927         initializeFadingEdgeInternal(arr);
   4928 
   4929         arr.recycle();
   4930     }
   4931 
   4932     /**
   4933      * <p>
   4934      * Initializes the fading edges from a given set of styled attributes. This
   4935      * method should be called by subclasses that need fading edges and when an
   4936      * instance of these subclasses is created programmatically rather than
   4937      * being inflated from XML. This method is automatically called when the XML
   4938      * is inflated.
   4939      * </p>
   4940      *
   4941      * @param a the styled attributes set to initialize the fading edges from
   4942      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
   4943      */
   4944     protected void initializeFadingEdgeInternal(TypedArray a) {
   4945         initScrollCache();
   4946 
   4947         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
   4948                 R.styleable.View_fadingEdgeLength,
   4949                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
   4950     }
   4951 
   4952     /**
   4953      * Returns the size of the vertical faded edges used to indicate that more
   4954      * content in this view is visible.
   4955      *
   4956      * @return The size in pixels of the vertical faded edge or 0 if vertical
   4957      *         faded edges are not enabled for this view.
   4958      * @attr ref android.R.styleable#View_fadingEdgeLength
   4959      */
   4960     public int getVerticalFadingEdgeLength() {
   4961         if (isVerticalFadingEdgeEnabled()) {
   4962             ScrollabilityCache cache = mScrollCache;
   4963             if (cache != null) {
   4964                 return cache.fadingEdgeLength;
   4965             }
   4966         }
   4967         return 0;
   4968     }
   4969 
   4970     /**
   4971      * Set the size of the faded edge used to indicate that more content in this
   4972      * view is available.  Will not change whether the fading edge is enabled; use
   4973      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
   4974      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
   4975      * for the vertical or horizontal fading edges.
   4976      *
   4977      * @param length The size in pixels of the faded edge used to indicate that more
   4978      *        content in this view is visible.
   4979      */
   4980     public void setFadingEdgeLength(int length) {
   4981         initScrollCache();
   4982         mScrollCache.fadingEdgeLength = length;
   4983     }
   4984 
   4985     /**
   4986      * Returns the size of the horizontal faded edges used to indicate that more
   4987      * content in this view is visible.
   4988      *
   4989      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
   4990      *         faded edges are not enabled for this view.
   4991      * @attr ref android.R.styleable#View_fadingEdgeLength
   4992      */
   4993     public int getHorizontalFadingEdgeLength() {
   4994         if (isHorizontalFadingEdgeEnabled()) {
   4995             ScrollabilityCache cache = mScrollCache;
   4996             if (cache != null) {
   4997                 return cache.fadingEdgeLength;
   4998             }
   4999         }
   5000         return 0;
   5001     }
   5002 
   5003     /**
   5004      * Returns the width of the vertical scrollbar.
   5005      *
   5006      * @return The width in pixels of the vertical scrollbar or 0 if there
   5007      *         is no vertical scrollbar.
   5008      */
   5009     public int getVerticalScrollbarWidth() {
   5010         ScrollabilityCache cache = mScrollCache;
   5011         if (cache != null) {
   5012             ScrollBarDrawable scrollBar = cache.scrollBar;
   5013             if (scrollBar != null) {
   5014                 int size = scrollBar.getSize(true);
   5015                 if (size <= 0) {
   5016                     size = cache.scrollBarSize;
   5017                 }
   5018                 return size;
   5019             }
   5020             return 0;
   5021         }
   5022         return 0;
   5023     }
   5024 
   5025     /**
   5026      * Returns the height of the horizontal scrollbar.
   5027      *
   5028      * @return The height in pixels of the horizontal scrollbar or 0 if
   5029      *         there is no horizontal scrollbar.
   5030      */
   5031     protected int getHorizontalScrollbarHeight() {
   5032         ScrollabilityCache cache = mScrollCache;
   5033         if (cache != null) {
   5034             ScrollBarDrawable scrollBar = cache.scrollBar;
   5035             if (scrollBar != null) {
   5036                 int size = scrollBar.getSize(false);
   5037                 if (size <= 0) {
   5038                     size = cache.scrollBarSize;
   5039                 }
   5040                 return size;
   5041             }
   5042             return 0;
   5043         }
   5044         return 0;
   5045     }
   5046 
   5047     /**
   5048      * <p>
   5049      * Initializes the scrollbars from a given set of styled attributes. This
   5050      * method should be called by subclasses that need scrollbars and when an
   5051      * instance of these subclasses is created programmatically rather than
   5052      * being inflated from XML. This method is automatically called when the XML
   5053      * is inflated.
   5054      * </p>
   5055      *
   5056      * @param a the styled attributes set to initialize the scrollbars from
   5057      *
   5058      * @removed
   5059      */
   5060     protected void initializeScrollbars(TypedArray a) {
   5061         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
   5062         // using the View filter array which is not available to the SDK. As such, internal
   5063         // framework usage now uses initializeScrollbarsInternal and we grab a default
   5064         // TypedArray with the right filter instead here.
   5065         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   5066 
   5067         initializeScrollbarsInternal(arr);
   5068 
   5069         // We ignored the method parameter. Recycle the one we actually did use.
   5070         arr.recycle();
   5071     }
   5072 
   5073     /**
   5074      * <p>
   5075      * Initializes the scrollbars from a given set of styled attributes. This
   5076      * method should be called by subclasses that need scrollbars and when an
   5077      * instance of these subclasses is created programmatically rather than
   5078      * being inflated from XML. This method is automatically called when the XML
   5079      * is inflated.
   5080      * </p>
   5081      *
   5082      * @param a the styled attributes set to initialize the scrollbars from
   5083      * @hide
   5084      */
   5085     protected void initializeScrollbarsInternal(TypedArray a) {
   5086         initScrollCache();
   5087 
   5088         final ScrollabilityCache scrollabilityCache = mScrollCache;
   5089 
   5090         if (scrollabilityCache.scrollBar == null) {
   5091             scrollabilityCache.scrollBar = new ScrollBarDrawable();
   5092             scrollabilityCache.scrollBar.setState(getDrawableState());
   5093             scrollabilityCache.scrollBar.setCallback(this);
   5094         }
   5095 
   5096         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
   5097 
   5098         if (!fadeScrollbars) {
   5099             scrollabilityCache.state = ScrollabilityCache.ON;
   5100         }
   5101         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   5102 
   5103 
   5104         scrollabilityCache.scrollBarFadeDuration = a.getInt(
   5105                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
   5106                         .getScrollBarFadeDuration());
   5107         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
   5108                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
   5109                 ViewConfiguration.getScrollDefaultDelay());
   5110 
   5111 
   5112         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
   5113                 com.android.internal.R.styleable.View_scrollbarSize,
   5114                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
   5115 
   5116         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
   5117         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
   5118 
   5119         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
   5120         if (thumb != null) {
   5121             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
   5122         }
   5123 
   5124         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
   5125                 false);
   5126         if (alwaysDraw) {
   5127             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
   5128         }
   5129 
   5130         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
   5131         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
   5132 
   5133         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
   5134         if (thumb != null) {
   5135             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
   5136         }
   5137 
   5138         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
   5139                 false);
   5140         if (alwaysDraw) {
   5141             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
   5142         }
   5143 
   5144         // Apply layout direction to the new Drawables if needed
   5145         final int layoutDirection = getLayoutDirection();
   5146         if (track != null) {
   5147             track.setLayoutDirection(layoutDirection);
   5148         }
   5149         if (thumb != null) {
   5150             thumb.setLayoutDirection(layoutDirection);
   5151         }
   5152 
   5153         // Re-apply user/background padding so that scrollbar(s) get added
   5154         resolvePadding();
   5155     }
   5156 
   5157     private void initializeScrollIndicatorsInternal() {
   5158         // Some day maybe we'll break this into top/left/start/etc. and let the
   5159         // client control it. Until then, you can have any scroll indicator you
   5160         // want as long as it's a 1dp foreground-colored rectangle.
   5161         if (mScrollIndicatorDrawable == null) {
   5162             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
   5163         }
   5164     }
   5165 
   5166     /**
   5167      * <p>
   5168      * Initalizes the scrollability cache if necessary.
   5169      * </p>
   5170      */
   5171     private void initScrollCache() {
   5172         if (mScrollCache == null) {
   5173             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
   5174         }
   5175     }
   5176 
   5177     private ScrollabilityCache getScrollCache() {
   5178         initScrollCache();
   5179         return mScrollCache;
   5180     }
   5181 
   5182     /**
   5183      * Set the position of the vertical scroll bar. Should be one of
   5184      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
   5185      * {@link #SCROLLBAR_POSITION_RIGHT}.
   5186      *
   5187      * @param position Where the vertical scroll bar should be positioned.
   5188      */
   5189     public void setVerticalScrollbarPosition(int position) {
   5190         if (mVerticalScrollbarPosition != position) {
   5191             mVerticalScrollbarPosition = position;
   5192             computeOpaqueFlags();
   5193             resolvePadding();
   5194         }
   5195     }
   5196 
   5197     /**
   5198      * @return The position where the vertical scroll bar will show, if applicable.
   5199      * @see #setVerticalScrollbarPosition(int)
   5200      */
   5201     public int getVerticalScrollbarPosition() {
   5202         return mVerticalScrollbarPosition;
   5203     }
   5204 
   5205     boolean isOnScrollbar(float x, float y) {
   5206         if (mScrollCache == null) {
   5207             return false;
   5208         }
   5209         x += getScrollX();
   5210         y += getScrollY();
   5211         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
   5212             final Rect bounds = mScrollCache.mScrollBarBounds;
   5213             getVerticalScrollBarBounds(bounds);
   5214             if (bounds.contains((int)x, (int)y)) {
   5215                 return true;
   5216             }
   5217         }
   5218         if (isHorizontalScrollBarEnabled()) {
   5219             final Rect bounds = mScrollCache.mScrollBarBounds;
   5220             getHorizontalScrollBarBounds(bounds);
   5221             if (bounds.contains((int)x, (int)y)) {
   5222                 return true;
   5223             }
   5224         }
   5225         return false;
   5226     }
   5227 
   5228     boolean isOnScrollbarThumb(float x, float y) {
   5229         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
   5230     }
   5231 
   5232     private boolean isOnVerticalScrollbarThumb(float x, float y) {
   5233         if (mScrollCache == null) {
   5234             return false;
   5235         }
   5236         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
   5237             x += getScrollX();
   5238             y += getScrollY();
   5239             final Rect bounds = mScrollCache.mScrollBarBounds;
   5240             getVerticalScrollBarBounds(bounds);
   5241             final int range = computeVerticalScrollRange();
   5242             final int offset = computeVerticalScrollOffset();
   5243             final int extent = computeVerticalScrollExtent();
   5244             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
   5245                     extent, range);
   5246             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
   5247                     extent, range, offset);
   5248             final int thumbTop = bounds.top + thumbOffset;
   5249             if (x >= bounds.left && x <= bounds.right && y >= thumbTop
   5250                     && y <= thumbTop + thumbLength) {
   5251                 return true;
   5252             }
   5253         }
   5254         return false;
   5255     }
   5256 
   5257     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
   5258         if (mScrollCache == null) {
   5259             return false;
   5260         }
   5261         if (isHorizontalScrollBarEnabled()) {
   5262             x += getScrollX();
   5263             y += getScrollY();
   5264             final Rect bounds = mScrollCache.mScrollBarBounds;
   5265             getHorizontalScrollBarBounds(bounds);
   5266             final int range = computeHorizontalScrollRange();
   5267             final int offset = computeHorizontalScrollOffset();
   5268             final int extent = computeHorizontalScrollExtent();
   5269             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
   5270                     extent, range);
   5271             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
   5272                     extent, range, offset);
   5273             final int thumbLeft = bounds.left + thumbOffset;
   5274             if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
   5275                     && y <= bounds.bottom) {
   5276                 return true;
   5277             }
   5278         }
   5279         return false;
   5280     }
   5281 
   5282     boolean isDraggingScrollBar() {
   5283         return mScrollCache != null
   5284                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
   5285     }
   5286 
   5287     /**
   5288      * Sets the state of all scroll indicators.
   5289      * <p>
   5290      * See {@link #setScrollIndicators(int, int)} for usage information.
   5291      *
   5292      * @param indicators a bitmask of indicators that should be enabled, or
   5293      *                   {@code 0} to disable all indicators
   5294      * @see #setScrollIndicators(int, int)
   5295      * @see #getScrollIndicators()
   5296      * @attr ref android.R.styleable#View_scrollIndicators
   5297      */
   5298     public void setScrollIndicators(@ScrollIndicators int indicators) {
   5299         setScrollIndicators(indicators,
   5300                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
   5301     }
   5302 
   5303     /**
   5304      * Sets the state of the scroll indicators specified by the mask. To change
   5305      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
   5306      * <p>
   5307      * When a scroll indicator is enabled, it will be displayed if the view
   5308      * can scroll in the direction of the indicator.
   5309      * <p>
   5310      * Multiple indicator types may be enabled or disabled by passing the
   5311      * logical OR of the desired types. If multiple types are specified, they
   5312      * will all be set to the same enabled state.
   5313      * <p>
   5314      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
   5315      *
   5316      * @param indicators the indicator direction, or the logical OR of multiple
   5317      *             indicator directions. One or more of:
   5318      *             <ul>
   5319      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
   5320      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
   5321      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
   5322      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
   5323      *               <li>{@link #SCROLL_INDICATOR_START}</li>
   5324      *               <li>{@link #SCROLL_INDICATOR_END}</li>
   5325      *             </ul>
   5326      * @see #setScrollIndicators(int)
   5327      * @see #getScrollIndicators()
   5328      * @attr ref android.R.styleable#View_scrollIndicators
   5329      */
   5330     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
   5331         // Shift and sanitize mask.
   5332         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   5333         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
   5334 
   5335         // Shift and mask indicators.
   5336         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   5337         indicators &= mask;
   5338 
   5339         // Merge with non-masked flags.
   5340         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
   5341 
   5342         if (mPrivateFlags3 != updatedFlags) {
   5343             mPrivateFlags3 = updatedFlags;
   5344 
   5345             if (indicators != 0) {
   5346                 initializeScrollIndicatorsInternal();
   5347             }
   5348             invalidate();
   5349         }
   5350     }
   5351 
   5352     /**
   5353      * Returns a bitmask representing the enabled scroll indicators.
   5354      * <p>
   5355      * For example, if the top and left scroll indicators are enabled and all
   5356      * other indicators are disabled, the return value will be
   5357      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
   5358      * <p>
   5359      * To check whether the bottom scroll indicator is enabled, use the value
   5360      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
   5361      *
   5362      * @return a bitmask representing the enabled scroll indicators
   5363      */
   5364     @ScrollIndicators
   5365     public int getScrollIndicators() {
   5366         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
   5367                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   5368     }
   5369 
   5370     ListenerInfo getListenerInfo() {
   5371         if (mListenerInfo != null) {
   5372             return mListenerInfo;
   5373         }
   5374         mListenerInfo = new ListenerInfo();
   5375         return mListenerInfo;
   5376     }
   5377 
   5378     /**
   5379      * Register a callback to be invoked when the scroll X or Y positions of
   5380      * this view change.
   5381      * <p>
   5382      * <b>Note:</b> Some views handle scrolling independently from View and may
   5383      * have their own separate listeners for scroll-type events. For example,
   5384      * {@link android.widget.ListView ListView} allows clients to register an
   5385      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   5386      * to listen for changes in list scroll position.
   5387      *
   5388      * @param l The listener to notify when the scroll X or Y position changes.
   5389      * @see android.view.View#getScrollX()
   5390      * @see android.view.View#getScrollY()
   5391      */
   5392     public void setOnScrollChangeListener(OnScrollChangeListener l) {
   5393         getListenerInfo().mOnScrollChangeListener = l;
   5394     }
   5395 
   5396     /**
   5397      * Register a callback to be invoked when focus of this view changed.
   5398      *
   5399      * @param l The callback that will run.
   5400      */
   5401     public void setOnFocusChangeListener(OnFocusChangeListener l) {
   5402         getListenerInfo().mOnFocusChangeListener = l;
   5403     }
   5404 
   5405     /**
   5406      * Add a listener that will be called when the bounds of the view change due to
   5407      * layout processing.
   5408      *
   5409      * @param listener The listener that will be called when layout bounds change.
   5410      */
   5411     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
   5412         ListenerInfo li = getListenerInfo();
   5413         if (li.mOnLayoutChangeListeners == null) {
   5414             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
   5415         }
   5416         if (!li.mOnLayoutChangeListeners.contains(listener)) {
   5417             li.mOnLayoutChangeListeners.add(listener);
   5418         }
   5419     }
   5420 
   5421     /**
   5422      * Remove a listener for layout changes.
   5423      *
   5424      * @param listener The listener for layout bounds change.
   5425      */
   5426     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
   5427         ListenerInfo li = mListenerInfo;
   5428         if (li == null || li.mOnLayoutChangeListeners == null) {
   5429             return;
   5430         }
   5431         li.mOnLayoutChangeListeners.remove(listener);
   5432     }
   5433 
   5434     /**
   5435      * Add a listener for attach state changes.
   5436      *
   5437      * This listener will be called whenever this view is attached or detached
   5438      * from a window. Remove the listener using
   5439      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
   5440      *
   5441      * @param listener Listener to attach
   5442      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
   5443      */
   5444     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   5445         ListenerInfo li = getListenerInfo();
   5446         if (li.mOnAttachStateChangeListeners == null) {
   5447             li.mOnAttachStateChangeListeners
   5448                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
   5449         }
   5450         li.mOnAttachStateChangeListeners.add(listener);
   5451     }
   5452 
   5453     /**
   5454      * Remove a listener for attach state changes. The listener will receive no further
   5455      * notification of window attach/detach events.
   5456      *
   5457      * @param listener Listener to remove
   5458      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
   5459      */
   5460     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   5461         ListenerInfo li = mListenerInfo;
   5462         if (li == null || li.mOnAttachStateChangeListeners == null) {
   5463             return;
   5464         }
   5465         li.mOnAttachStateChangeListeners.remove(listener);
   5466     }
   5467 
   5468     /**
   5469      * Returns the focus-change callback registered for this view.
   5470      *
   5471      * @return The callback, or null if one is not registered.
   5472      */
   5473     public OnFocusChangeListener getOnFocusChangeListener() {
   5474         ListenerInfo li = mListenerInfo;
   5475         return li != null ? li.mOnFocusChangeListener : null;
   5476     }
   5477 
   5478     /**
   5479      * Register a callback to be invoked when this view is clicked. If this view is not
   5480      * clickable, it becomes clickable.
   5481      *
   5482      * @param l The callback that will run
   5483      *
   5484      * @see #setClickable(boolean)
   5485      */
   5486     public void setOnClickListener(@Nullable OnClickListener l) {
   5487         if (!isClickable()) {
   5488             setClickable(true);
   5489         }
   5490         getListenerInfo().mOnClickListener = l;
   5491     }
   5492 
   5493     /**
   5494      * Return whether this view has an attached OnClickListener.  Returns
   5495      * true if there is a listener, false if there is none.
   5496      */
   5497     public boolean hasOnClickListeners() {
   5498         ListenerInfo li = mListenerInfo;
   5499         return (li != null && li.mOnClickListener != null);
   5500     }
   5501 
   5502     /**
   5503      * Register a callback to be invoked when this view is clicked and held. If this view is not
   5504      * long clickable, it becomes long clickable.
   5505      *
   5506      * @param l The callback that will run
   5507      *
   5508      * @see #setLongClickable(boolean)
   5509      */
   5510     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
   5511         if (!isLongClickable()) {
   5512             setLongClickable(true);
   5513         }
   5514         getListenerInfo().mOnLongClickListener = l;
   5515     }
   5516 
   5517     /**
   5518      * Register a callback to be invoked when this view is context clicked. If the view is not
   5519      * context clickable, it becomes context clickable.
   5520      *
   5521      * @param l The callback that will run
   5522      * @see #setContextClickable(boolean)
   5523      */
   5524     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
   5525         if (!isContextClickable()) {
   5526             setContextClickable(true);
   5527         }
   5528         getListenerInfo().mOnContextClickListener = l;
   5529     }
   5530 
   5531     /**
   5532      * Register a callback to be invoked when the context menu for this view is
   5533      * being built. If this view is not long clickable, it becomes long clickable.
   5534      *
   5535      * @param l The callback that will run
   5536      *
   5537      */
   5538     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
   5539         if (!isLongClickable()) {
   5540             setLongClickable(true);
   5541         }
   5542         getListenerInfo().mOnCreateContextMenuListener = l;
   5543     }
   5544 
   5545     /**
   5546      * Set an observer to collect stats for each frame rendered for this view.
   5547      *
   5548      * @hide
   5549      */
   5550     public void addFrameMetricsListener(Window window,
   5551             Window.OnFrameMetricsAvailableListener listener,
   5552             Handler handler) {
   5553         if (mAttachInfo != null) {
   5554             if (mAttachInfo.mHardwareRenderer != null) {
   5555                 if (mFrameMetricsObservers == null) {
   5556                     mFrameMetricsObservers = new ArrayList<>();
   5557                 }
   5558 
   5559                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
   5560                         handler.getLooper(), listener);
   5561                 mFrameMetricsObservers.add(fmo);
   5562                 mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
   5563             } else {
   5564                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
   5565             }
   5566         } else {
   5567             if (mFrameMetricsObservers == null) {
   5568                 mFrameMetricsObservers = new ArrayList<>();
   5569             }
   5570 
   5571             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
   5572                     handler.getLooper(), listener);
   5573             mFrameMetricsObservers.add(fmo);
   5574         }
   5575     }
   5576 
   5577     /**
   5578      * Remove observer configured to collect frame stats for this view.
   5579      *
   5580      * @hide
   5581      */
   5582     public void removeFrameMetricsListener(
   5583             Window.OnFrameMetricsAvailableListener listener) {
   5584         ThreadedRenderer renderer = getHardwareRenderer();
   5585         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
   5586         if (fmo == null) {
   5587             throw new IllegalArgumentException(
   5588                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
   5589         }
   5590 
   5591         if (mFrameMetricsObservers != null) {
   5592             mFrameMetricsObservers.remove(fmo);
   5593             if (renderer != null) {
   5594                 renderer.removeFrameMetricsObserver(fmo);
   5595             }
   5596         }
   5597     }
   5598 
   5599     private void registerPendingFrameMetricsObservers() {
   5600         if (mFrameMetricsObservers != null) {
   5601             ThreadedRenderer renderer = getHardwareRenderer();
   5602             if (renderer != null) {
   5603                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
   5604                     renderer.addFrameMetricsObserver(fmo);
   5605                 }
   5606             } else {
   5607                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
   5608             }
   5609         }
   5610     }
   5611 
   5612     private FrameMetricsObserver findFrameMetricsObserver(
   5613             Window.OnFrameMetricsAvailableListener listener) {
   5614         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
   5615             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
   5616             if (observer.mListener == listener) {
   5617                 return observer;
   5618             }
   5619         }
   5620 
   5621         return null;
   5622     }
   5623 
   5624     /**
   5625      * Call this view's OnClickListener, if it is defined.  Performs all normal
   5626      * actions associated with clicking: reporting accessibility event, playing
   5627      * a sound, etc.
   5628      *
   5629      * @return True there was an assigned OnClickListener that was called, false
   5630      *         otherwise is returned.
   5631      */
   5632     public boolean performClick() {
   5633         final boolean result;
   5634         final ListenerInfo li = mListenerInfo;
   5635         if (li != null && li.mOnClickListener != null) {
   5636             playSoundEffect(SoundEffectConstants.CLICK);
   5637             li.mOnClickListener.onClick(this);
   5638             result = true;
   5639         } else {
   5640             result = false;
   5641         }
   5642 
   5643         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
   5644         return result;
   5645     }
   5646 
   5647     /**
   5648      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
   5649      * this only calls the listener, and does not do any associated clicking
   5650      * actions like reporting an accessibility event.
   5651      *
   5652      * @return True there was an assigned OnClickListener that was called, false
   5653      *         otherwise is returned.
   5654      */
   5655     public boolean callOnClick() {
   5656         ListenerInfo li = mListenerInfo;
   5657         if (li != null && li.mOnClickListener != null) {
   5658             li.mOnClickListener.onClick(this);
   5659             return true;
   5660         }
   5661         return false;
   5662     }
   5663 
   5664     /**
   5665      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   5666      * context menu if the OnLongClickListener did not consume the event.
   5667      *
   5668      * @return {@code true} if one of the above receivers consumed the event,
   5669      *         {@code false} otherwise
   5670      */
   5671     public boolean performLongClick() {
   5672         return performLongClickInternal(mLongClickX, mLongClickY);
   5673     }
   5674 
   5675     /**
   5676      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   5677      * context menu if the OnLongClickListener did not consume the event,
   5678      * anchoring it to an (x,y) coordinate.
   5679      *
   5680      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
   5681      *          to disable anchoring
   5682      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
   5683      *          to disable anchoring
   5684      * @return {@code true} if one of the above receivers consumed the event,
   5685      *         {@code false} otherwise
   5686      */
   5687     public boolean performLongClick(float x, float y) {
   5688         mLongClickX = x;
   5689         mLongClickY = y;
   5690         final boolean handled = performLongClick();
   5691         mLongClickX = Float.NaN;
   5692         mLongClickY = Float.NaN;
   5693         return handled;
   5694     }
   5695 
   5696     /**
   5697      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   5698      * context menu if the OnLongClickListener did not consume the event,
   5699      * optionally anchoring it to an (x,y) coordinate.
   5700      *
   5701      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
   5702      *          to disable anchoring
   5703      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
   5704      *          to disable anchoring
   5705      * @return {@code true} if one of the above receivers consumed the event,
   5706      *         {@code false} otherwise
   5707      */
   5708     private boolean performLongClickInternal(float x, float y) {
   5709         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
   5710 
   5711         boolean handled = false;
   5712         final ListenerInfo li = mListenerInfo;
   5713         if (li != null && li.mOnLongClickListener != null) {
   5714             handled = li.mOnLongClickListener.onLongClick(View.this);
   5715         }
   5716         if (!handled) {
   5717             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
   5718             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
   5719         }
   5720         if (handled) {
   5721             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
   5722         }
   5723         return handled;
   5724     }
   5725 
   5726     /**
   5727      * Call this view's OnContextClickListener, if it is defined.
   5728      *
   5729      * @param x the x coordinate of the context click
   5730      * @param y the y coordinate of the context click
   5731      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   5732      *         otherwise.
   5733      */
   5734     public boolean performContextClick(float x, float y) {
   5735         return performContextClick();
   5736     }
   5737 
   5738     /**
   5739      * Call this view's OnContextClickListener, if it is defined.
   5740      *
   5741      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   5742      *         otherwise.
   5743      */
   5744     public boolean performContextClick() {
   5745         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
   5746 
   5747         boolean handled = false;
   5748         ListenerInfo li = mListenerInfo;
   5749         if (li != null && li.mOnContextClickListener != null) {
   5750             handled = li.mOnContextClickListener.onContextClick(View.this);
   5751         }
   5752         if (handled) {
   5753             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
   5754         }
   5755         return handled;
   5756     }
   5757 
   5758     /**
   5759      * Performs button-related actions during a touch down event.
   5760      *
   5761      * @param event The event.
   5762      * @return True if the down was consumed.
   5763      *
   5764      * @hide
   5765      */
   5766     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
   5767         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
   5768             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
   5769             showContextMenu(event.getX(), event.getY());
   5770             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   5771             return true;
   5772         }
   5773         return false;
   5774     }
   5775 
   5776     /**
   5777      * Shows the context menu for this view.
   5778      *
   5779      * @return {@code true} if the context menu was shown, {@code false}
   5780      *         otherwise
   5781      * @see #showContextMenu(float, float)
   5782      */
   5783     public boolean showContextMenu() {
   5784         return getParent().showContextMenuForChild(this);
   5785     }
   5786 
   5787     /**
   5788      * Shows the context menu for this view anchored to the specified
   5789      * view-relative coordinate.
   5790      *
   5791      * @param x the X coordinate in pixels relative to the view to which the
   5792      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
   5793      * @param y the Y coordinate in pixels relative to the view to which the
   5794      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
   5795      * @return {@code true} if the context menu was shown, {@code false}
   5796      *         otherwise
   5797      */
   5798     public boolean showContextMenu(float x, float y) {
   5799         return getParent().showContextMenuForChild(this, x, y);
   5800     }
   5801 
   5802     /**
   5803      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
   5804      *
   5805      * @param callback Callback that will control the lifecycle of the action mode
   5806      * @return The new action mode if it is started, null otherwise
   5807      *
   5808      * @see ActionMode
   5809      * @see #startActionMode(android.view.ActionMode.Callback, int)
   5810      */
   5811     public ActionMode startActionMode(ActionMode.Callback callback) {
   5812         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
   5813     }
   5814 
   5815     /**
   5816      * Start an action mode with the given type.
   5817      *
   5818      * @param callback Callback that will control the lifecycle of the action mode
   5819      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
   5820      * @return The new action mode if it is started, null otherwise
   5821      *
   5822      * @see ActionMode
   5823      */
   5824     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
   5825         ViewParent parent = getParent();
   5826         if (parent == null) return null;
   5827         try {
   5828             return parent.startActionModeForChild(this, callback, type);
   5829         } catch (AbstractMethodError ame) {
   5830             // Older implementations of custom views might not implement this.
   5831             return parent.startActionModeForChild(this, callback);
   5832         }
   5833     }
   5834 
   5835     /**
   5836      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
   5837      * Context, creating a unique View identifier to retrieve the result.
   5838      *
   5839      * @param intent The Intent to be started.
   5840      * @param requestCode The request code to use.
   5841      * @hide
   5842      */
   5843     public void startActivityForResult(Intent intent, int requestCode) {
   5844         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
   5845         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
   5846     }
   5847 
   5848     /**
   5849      * If this View corresponds to the calling who, dispatches the activity result.
   5850      * @param who The identifier for the targeted View to receive the result.
   5851      * @param requestCode The integer request code originally supplied to
   5852      *                    startActivityForResult(), allowing you to identify who this
   5853      *                    result came from.
   5854      * @param resultCode The integer result code returned by the child activity
   5855      *                   through its setResult().
   5856      * @param data An Intent, which can return result data to the caller
   5857      *               (various data can be attached to Intent "extras").
   5858      * @return {@code true} if the activity result was dispatched.
   5859      * @hide
   5860      */
   5861     public boolean dispatchActivityResult(
   5862             String who, int requestCode, int resultCode, Intent data) {
   5863         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
   5864             onActivityResult(requestCode, resultCode, data);
   5865             mStartActivityRequestWho = null;
   5866             return true;
   5867         }
   5868         return false;
   5869     }
   5870 
   5871     /**
   5872      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
   5873      *
   5874      * @param requestCode The integer request code originally supplied to
   5875      *                    startActivityForResult(), allowing you to identify who this
   5876      *                    result came from.
   5877      * @param resultCode The integer result code returned by the child activity
   5878      *                   through its setResult().
   5879      * @param data An Intent, which can return result data to the caller
   5880      *               (various data can be attached to Intent "extras").
   5881      * @hide
   5882      */
   5883     public void onActivityResult(int requestCode, int resultCode, Intent data) {
   5884         // Do nothing.
   5885     }
   5886 
   5887     /**
   5888      * Register a callback to be invoked when a hardware key is pressed in this view.
   5889      * Key presses in software input methods will generally not trigger the methods of
   5890      * this listener.
   5891      * @param l the key listener to attach to this view
   5892      */
   5893     public void setOnKeyListener(OnKeyListener l) {
   5894         getListenerInfo().mOnKeyListener = l;
   5895     }
   5896 
   5897     /**
   5898      * Register a callback to be invoked when a touch event is sent to this view.
   5899      * @param l the touch listener to attach to this view
   5900      */
   5901     public void setOnTouchListener(OnTouchListener l) {
   5902         getListenerInfo().mOnTouchListener = l;
   5903     }
   5904 
   5905     /**
   5906      * Register a callback to be invoked when a generic motion event is sent to this view.
   5907      * @param l the generic motion listener to attach to this view
   5908      */
   5909     public void setOnGenericMotionListener(OnGenericMotionListener l) {
   5910         getListenerInfo().mOnGenericMotionListener = l;
   5911     }
   5912 
   5913     /**
   5914      * Register a callback to be invoked when a hover event is sent to this view.
   5915      * @param l the hover listener to attach to this view
   5916      */
   5917     public void setOnHoverListener(OnHoverListener l) {
   5918         getListenerInfo().mOnHoverListener = l;
   5919     }
   5920 
   5921     /**
   5922      * Register a drag event listener callback object for this View. The parameter is
   5923      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
   5924      * View, the system calls the
   5925      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
   5926      * @param l An implementation of {@link android.view.View.OnDragListener}.
   5927      */
   5928     public void setOnDragListener(OnDragListener l) {
   5929         getListenerInfo().mOnDragListener = l;
   5930     }
   5931 
   5932     /**
   5933      * Give this view focus. This will cause
   5934      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
   5935      *
   5936      * Note: this does not check whether this {@link View} should get focus, it just
   5937      * gives it focus no matter what.  It should only be called internally by framework
   5938      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
   5939      *
   5940      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
   5941      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
   5942      *        focus moved when requestFocus() is called. It may not always
   5943      *        apply, in which case use the default View.FOCUS_DOWN.
   5944      * @param previouslyFocusedRect The rectangle of the view that had focus
   5945      *        prior in this View's coordinate system.
   5946      */
   5947     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
   5948         if (DBG) {
   5949             System.out.println(this + " requestFocus()");
   5950         }
   5951 
   5952         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
   5953             mPrivateFlags |= PFLAG_FOCUSED;
   5954 
   5955             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
   5956 
   5957             if (mParent != null) {
   5958                 mParent.requestChildFocus(this, this);
   5959             }
   5960 
   5961             if (mAttachInfo != null) {
   5962                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
   5963             }
   5964 
   5965             onFocusChanged(true, direction, previouslyFocusedRect);
   5966             refreshDrawableState();
   5967         }
   5968     }
   5969 
   5970     /**
   5971      * Sets this view's preference for reveal behavior when it gains focus.
   5972      *
   5973      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
   5974      * this view would prefer to be brought fully into view when it gains focus.
   5975      * For example, a text field that a user is meant to type into. Other views such
   5976      * as scrolling containers may prefer to opt-out of this behavior.</p>
   5977      *
   5978      * <p>The default value for views is true, though subclasses may change this
   5979      * based on their preferred behavior.</p>
   5980      *
   5981      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
   5982      *
   5983      * @see #getRevealOnFocusHint()
   5984      */
   5985     public final void setRevealOnFocusHint(boolean revealOnFocus) {
   5986         if (revealOnFocus) {
   5987             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
   5988         } else {
   5989             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
   5990         }
   5991     }
   5992 
   5993     /**
   5994      * Returns this view's preference for reveal behavior when it gains focus.
   5995      *
   5996      * <p>When this method returns true for a child view requesting focus, ancestor
   5997      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
   5998      * should make a best effort to make the newly focused child fully visible to the user.
   5999      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
   6000      * other properties affecting visibility to the user as part of the focus change.</p>
   6001      *
   6002      * @return true if this view would prefer to become fully visible when it gains focus,
   6003      *         false if it would prefer not to disrupt scroll positioning
   6004      *
   6005      * @see #setRevealOnFocusHint(boolean)
   6006      */
   6007     public final boolean getRevealOnFocusHint() {
   6008         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
   6009     }
   6010 
   6011     /**
   6012      * Populates <code>outRect</code> with the hotspot bounds. By default,
   6013      * the hotspot bounds are identical to the screen bounds.
   6014      *
   6015      * @param outRect rect to populate with hotspot bounds
   6016      * @hide Only for internal use by views and widgets.
   6017      */
   6018     public void getHotspotBounds(Rect outRect) {
   6019         final Drawable background = getBackground();
   6020         if (background != null) {
   6021             background.getHotspotBounds(outRect);
   6022         } else {
   6023             getBoundsOnScreen(outRect);
   6024         }
   6025     }
   6026 
   6027     /**
   6028      * Request that a rectangle of this view be visible on the screen,
   6029      * scrolling if necessary just enough.
   6030      *
   6031      * <p>A View should call this if it maintains some notion of which part
   6032      * of its content is interesting.  For example, a text editing view
   6033      * should call this when its cursor moves.
   6034      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
   6035      * It should not be affected by which part of the View is currently visible or its scroll
   6036      * position.
   6037      *
   6038      * @param rectangle The rectangle in the View's content coordinate space
   6039      * @return Whether any parent scrolled.
   6040      */
   6041     public boolean requestRectangleOnScreen(Rect rectangle) {
   6042         return requestRectangleOnScreen(rectangle, false);
   6043     }
   6044 
   6045     /**
   6046      * Request that a rectangle of this view be visible on the screen,
   6047      * scrolling if necessary just enough.
   6048      *
   6049      * <p>A View should call this if it maintains some notion of which part
   6050      * of its content is interesting.  For example, a text editing view
   6051      * should call this when its cursor moves.
   6052      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
   6053      * It should not be affected by which part of the View is currently visible or its scroll
   6054      * position.
   6055      * <p>When <code>immediate</code> is set to true, scrolling will not be
   6056      * animated.
   6057      *
   6058      * @param rectangle The rectangle in the View's content coordinate space
   6059      * @param immediate True to forbid animated scrolling, false otherwise
   6060      * @return Whether any parent scrolled.
   6061      */
   6062     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
   6063         if (mParent == null) {
   6064             return false;
   6065         }
   6066 
   6067         View child = this;
   6068 
   6069         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
   6070         position.set(rectangle);
   6071 
   6072         ViewParent parent = mParent;
   6073         boolean scrolled = false;
   6074         while (parent != null) {
   6075             rectangle.set((int) position.left, (int) position.top,
   6076                     (int) position.right, (int) position.bottom);
   6077 
   6078             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
   6079 
   6080             if (!(parent instanceof View)) {
   6081                 break;
   6082             }
   6083 
   6084             // move it from child's content coordinate space to parent's content coordinate space
   6085             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
   6086 
   6087             child = (View) parent;
   6088             parent = child.getParent();
   6089         }
   6090 
   6091         return scrolled;
   6092     }
   6093 
   6094     /**
   6095      * Called when this view wants to give up focus. If focus is cleared
   6096      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
   6097      * <p>
   6098      * <strong>Note:</strong> When a View clears focus the framework is trying
   6099      * to give focus to the first focusable View from the top. Hence, if this
   6100      * View is the first from the top that can take focus, then all callbacks
   6101      * related to clearing focus will be invoked after which the framework will
   6102      * give focus to this view.
   6103      * </p>
   6104      */
   6105     public void clearFocus() {
   6106         if (DBG) {
   6107             System.out.println(this + " clearFocus()");
   6108         }
   6109 
   6110         clearFocusInternal(null, true, true);
   6111     }
   6112 
   6113     /**
   6114      * Clears focus from the view, optionally propagating the change up through
   6115      * the parent hierarchy and requesting that the root view place new focus.
   6116      *
   6117      * @param propagate whether to propagate the change up through the parent
   6118      *            hierarchy
   6119      * @param refocus when propagate is true, specifies whether to request the
   6120      *            root view place new focus
   6121      */
   6122     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
   6123         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   6124             mPrivateFlags &= ~PFLAG_FOCUSED;
   6125 
   6126             if (propagate && mParent != null) {
   6127                 mParent.clearChildFocus(this);
   6128             }
   6129 
   6130             onFocusChanged(false, 0, null);
   6131             refreshDrawableState();
   6132 
   6133             if (propagate && (!refocus || !rootViewRequestFocus())) {
   6134                 notifyGlobalFocusCleared(this);
   6135             }
   6136         }
   6137     }
   6138 
   6139     void notifyGlobalFocusCleared(View oldFocus) {
   6140         if (oldFocus != null && mAttachInfo != null) {
   6141             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
   6142         }
   6143     }
   6144 
   6145     boolean rootViewRequestFocus() {
   6146         final View root = getRootView();
   6147         return root != null && root.requestFocus();
   6148     }
   6149 
   6150     /**
   6151      * Called internally by the view system when a new view is getting focus.
   6152      * This is what clears the old focus.
   6153      * <p>
   6154      * <b>NOTE:</b> The parent view's focused child must be updated manually
   6155      * after calling this method. Otherwise, the view hierarchy may be left in
   6156      * an inconstent state.
   6157      */
   6158     void unFocus(View focused) {
   6159         if (DBG) {
   6160             System.out.println(this + " unFocus()");
   6161         }
   6162 
   6163         clearFocusInternal(focused, false, false);
   6164     }
   6165 
   6166     /**
   6167      * Returns true if this view has focus itself, or is the ancestor of the
   6168      * view that has focus.
   6169      *
   6170      * @return True if this view has or contains focus, false otherwise.
   6171      */
   6172     @ViewDebug.ExportedProperty(category = "focus")
   6173     public boolean hasFocus() {
   6174         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   6175     }
   6176 
   6177     /**
   6178      * Returns true if this view is focusable or if it contains a reachable View
   6179      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
   6180      * is a View whose parents do not block descendants focus.
   6181      *
   6182      * Only {@link #VISIBLE} views are considered focusable.
   6183      *
   6184      * @return True if the view is focusable or if the view contains a focusable
   6185      *         View, false otherwise.
   6186      *
   6187      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
   6188      * @see ViewGroup#getTouchscreenBlocksFocus()
   6189      */
   6190     public boolean hasFocusable() {
   6191         if (!isFocusableInTouchMode()) {
   6192             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
   6193                 final ViewGroup g = (ViewGroup) p;
   6194                 if (g.shouldBlockFocusForTouchscreen()) {
   6195                     return false;
   6196                 }
   6197             }
   6198         }
   6199         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
   6200     }
   6201 
   6202     /**
   6203      * Called by the view system when the focus state of this view changes.
   6204      * When the focus change event is caused by directional navigation, direction
   6205      * and previouslyFocusedRect provide insight into where the focus is coming from.
   6206      * When overriding, be sure to call up through to the super class so that
   6207      * the standard focus handling will occur.
   6208      *
   6209      * @param gainFocus True if the View has focus; false otherwise.
   6210      * @param direction The direction focus has moved when requestFocus()
   6211      *                  is called to give this view focus. Values are
   6212      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
   6213      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
   6214      *                  It may not always apply, in which case use the default.
   6215      * @param previouslyFocusedRect The rectangle, in this view's coordinate
   6216      *        system, of the previously focused view.  If applicable, this will be
   6217      *        passed in as finer grained information about where the focus is coming
   6218      *        from (in addition to direction).  Will be <code>null</code> otherwise.
   6219      */
   6220     @CallSuper
   6221     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
   6222             @Nullable Rect previouslyFocusedRect) {
   6223         if (gainFocus) {
   6224             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
   6225         } else {
   6226             notifyViewAccessibilityStateChangedIfNeeded(
   6227                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   6228         }
   6229 
   6230         InputMethodManager imm = InputMethodManager.peekInstance();
   6231         if (!gainFocus) {
   6232             if (isPressed()) {
   6233                 setPressed(false);
   6234             }
   6235             if (imm != null && mAttachInfo != null
   6236                     && mAttachInfo.mHasWindowFocus) {
   6237                 imm.focusOut(this);
   6238             }
   6239             onFocusLost();
   6240         } else if (imm != null && mAttachInfo != null
   6241                 && mAttachInfo.mHasWindowFocus) {
   6242             imm.focusIn(this);
   6243         }
   6244 
   6245         invalidate(true);
   6246         ListenerInfo li = mListenerInfo;
   6247         if (li != null && li.mOnFocusChangeListener != null) {
   6248             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
   6249         }
   6250 
   6251         if (mAttachInfo != null) {
   6252             mAttachInfo.mKeyDispatchState.reset(this);
   6253         }
   6254     }
   6255 
   6256     /**
   6257      * Sends an accessibility event of the given type. If accessibility is
   6258      * not enabled this method has no effect. The default implementation calls
   6259      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
   6260      * to populate information about the event source (this View), then calls
   6261      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
   6262      * populate the text content of the event source including its descendants,
   6263      * and last calls
   6264      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
   6265      * on its parent to request sending of the event to interested parties.
   6266      * <p>
   6267      * If an {@link AccessibilityDelegate} has been specified via calling
   6268      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6269      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
   6270      * responsible for handling this call.
   6271      * </p>
   6272      *
   6273      * @param eventType The type of the event to send, as defined by several types from
   6274      * {@link android.view.accessibility.AccessibilityEvent}, such as
   6275      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
   6276      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
   6277      *
   6278      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   6279      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   6280      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
   6281      * @see AccessibilityDelegate
   6282      */
   6283     public void sendAccessibilityEvent(int eventType) {
   6284         if (mAccessibilityDelegate != null) {
   6285             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
   6286         } else {
   6287             sendAccessibilityEventInternal(eventType);
   6288         }
   6289     }
   6290 
   6291     /**
   6292      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
   6293      * {@link AccessibilityEvent} to make an announcement which is related to some
   6294      * sort of a context change for which none of the events representing UI transitions
   6295      * is a good fit. For example, announcing a new page in a book. If accessibility
   6296      * is not enabled this method does nothing.
   6297      *
   6298      * @param text The announcement text.
   6299      */
   6300     public void announceForAccessibility(CharSequence text) {
   6301         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
   6302             AccessibilityEvent event = AccessibilityEvent.obtain(
   6303                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
   6304             onInitializeAccessibilityEvent(event);
   6305             event.getText().add(text);
   6306             event.setContentDescription(null);
   6307             mParent.requestSendAccessibilityEvent(this, event);
   6308         }
   6309     }
   6310 
   6311     /**
   6312      * @see #sendAccessibilityEvent(int)
   6313      *
   6314      * Note: Called from the default {@link AccessibilityDelegate}.
   6315      *
   6316      * @hide
   6317      */
   6318     public void sendAccessibilityEventInternal(int eventType) {
   6319         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   6320             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
   6321         }
   6322     }
   6323 
   6324     /**
   6325      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
   6326      * takes as an argument an empty {@link AccessibilityEvent} and does not
   6327      * perform a check whether accessibility is enabled.
   6328      * <p>
   6329      * If an {@link AccessibilityDelegate} has been specified via calling
   6330      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6331      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
   6332      * is responsible for handling this call.
   6333      * </p>
   6334      *
   6335      * @param event The event to send.
   6336      *
   6337      * @see #sendAccessibilityEvent(int)
   6338      */
   6339     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
   6340         if (mAccessibilityDelegate != null) {
   6341             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   6342         } else {
   6343             sendAccessibilityEventUncheckedInternal(event);
   6344         }
   6345     }
   6346 
   6347     /**
   6348      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
   6349      *
   6350      * Note: Called from the default {@link AccessibilityDelegate}.
   6351      *
   6352      * @hide
   6353      */
   6354     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
   6355         if (!isShown()) {
   6356             return;
   6357         }
   6358         onInitializeAccessibilityEvent(event);
   6359         // Only a subset of accessibility events populates text content.
   6360         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
   6361             dispatchPopulateAccessibilityEvent(event);
   6362         }
   6363         // In the beginning we called #isShown(), so we know that getParent() is not null.
   6364         getParent().requestSendAccessibilityEvent(this, event);
   6365     }
   6366 
   6367     /**
   6368      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
   6369      * to its children for adding their text content to the event. Note that the
   6370      * event text is populated in a separate dispatch path since we add to the
   6371      * event not only the text of the source but also the text of all its descendants.
   6372      * A typical implementation will call
   6373      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
   6374      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   6375      * on each child. Override this method if custom population of the event text
   6376      * content is required.
   6377      * <p>
   6378      * If an {@link AccessibilityDelegate} has been specified via calling
   6379      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6380      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
   6381      * is responsible for handling this call.
   6382      * </p>
   6383      * <p>
   6384      * <em>Note:</em> Accessibility events of certain types are not dispatched for
   6385      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
   6386      * </p>
   6387      *
   6388      * @param event The event.
   6389      *
   6390      * @return True if the event population was completed.
   6391      */
   6392     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
   6393         if (mAccessibilityDelegate != null) {
   6394             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
   6395         } else {
   6396             return dispatchPopulateAccessibilityEventInternal(event);
   6397         }
   6398     }
   6399 
   6400     /**
   6401      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   6402      *
   6403      * Note: Called from the default {@link AccessibilityDelegate}.
   6404      *
   6405      * @hide
   6406      */
   6407     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   6408         onPopulateAccessibilityEvent(event);
   6409         return false;
   6410     }
   6411 
   6412     /**
   6413      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   6414      * giving a chance to this View to populate the accessibility event with its
   6415      * text content. While this method is free to modify event
   6416      * attributes other than text content, doing so should normally be performed in
   6417      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
   6418      * <p>
   6419      * Example: Adding formatted date string to an accessibility event in addition
   6420      *          to the text added by the super implementation:
   6421      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   6422      *     super.onPopulateAccessibilityEvent(event);
   6423      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
   6424      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
   6425      *         mCurrentDate.getTimeInMillis(), flags);
   6426      *     event.getText().add(selectedDateUtterance);
   6427      * }</pre>
   6428      * <p>
   6429      * If an {@link AccessibilityDelegate} has been specified via calling
   6430      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6431      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
   6432      * is responsible for handling this call.
   6433      * </p>
   6434      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   6435      * information to the event, in case the default implementation has basic information to add.
   6436      * </p>
   6437      *
   6438      * @param event The accessibility event which to populate.
   6439      *
   6440      * @see #sendAccessibilityEvent(int)
   6441      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   6442      */
   6443     @CallSuper
   6444     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   6445         if (mAccessibilityDelegate != null) {
   6446             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
   6447         } else {
   6448             onPopulateAccessibilityEventInternal(event);
   6449         }
   6450     }
   6451 
   6452     /**
   6453      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
   6454      *
   6455      * Note: Called from the default {@link AccessibilityDelegate}.
   6456      *
   6457      * @hide
   6458      */
   6459     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   6460     }
   6461 
   6462     /**
   6463      * Initializes an {@link AccessibilityEvent} with information about
   6464      * this View which is the event source. In other words, the source of
   6465      * an accessibility event is the view whose state change triggered firing
   6466      * the event.
   6467      * <p>
   6468      * Example: Setting the password property of an event in addition
   6469      *          to properties set by the super implementation:
   6470      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   6471      *     super.onInitializeAccessibilityEvent(event);
   6472      *     event.setPassword(true);
   6473      * }</pre>
   6474      * <p>
   6475      * If an {@link AccessibilityDelegate} has been specified via calling
   6476      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6477      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
   6478      * is responsible for handling this call.
   6479      * </p>
   6480      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   6481      * information to the event, in case the default implementation has basic information to add.
   6482      * </p>
   6483      * @param event The event to initialize.
   6484      *
   6485      * @see #sendAccessibilityEvent(int)
   6486      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   6487      */
   6488     @CallSuper
   6489     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   6490         if (mAccessibilityDelegate != null) {
   6491             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
   6492         } else {
   6493             onInitializeAccessibilityEventInternal(event);
   6494         }
   6495     }
   6496 
   6497     /**
   6498      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   6499      *
   6500      * Note: Called from the default {@link AccessibilityDelegate}.
   6501      *
   6502      * @hide
   6503      */
   6504     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
   6505         event.setSource(this);
   6506         event.setClassName(getAccessibilityClassName());
   6507         event.setPackageName(getContext().getPackageName());
   6508         event.setEnabled(isEnabled());
   6509         event.setContentDescription(mContentDescription);
   6510 
   6511         switch (event.getEventType()) {
   6512             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
   6513                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
   6514                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
   6515                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
   6516                 event.setItemCount(focusablesTempList.size());
   6517                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
   6518                 if (mAttachInfo != null) {
   6519                     focusablesTempList.clear();
   6520                 }
   6521             } break;
   6522             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
   6523                 CharSequence text = getIterableTextForAccessibility();
   6524                 if (text != null && text.length() > 0) {
   6525                     event.setFromIndex(getAccessibilitySelectionStart());
   6526                     event.setToIndex(getAccessibilitySelectionEnd());
   6527                     event.setItemCount(text.length());
   6528                 }
   6529             } break;
   6530         }
   6531     }
   6532 
   6533     /**
   6534      * Returns an {@link AccessibilityNodeInfo} representing this view from the
   6535      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   6536      * This method is responsible for obtaining an accessibility node info from a
   6537      * pool of reusable instances and calling
   6538      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
   6539      * initialize the former.
   6540      * <p>
   6541      * Note: The client is responsible for recycling the obtained instance by calling
   6542      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
   6543      * </p>
   6544      *
   6545      * @return A populated {@link AccessibilityNodeInfo}.
   6546      *
   6547      * @see AccessibilityNodeInfo
   6548      */
   6549     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
   6550         if (mAccessibilityDelegate != null) {
   6551             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
   6552         } else {
   6553             return createAccessibilityNodeInfoInternal();
   6554         }
   6555     }
   6556 
   6557     /**
   6558      * @see #createAccessibilityNodeInfo()
   6559      *
   6560      * @hide
   6561      */
   6562     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
   6563         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   6564         if (provider != null) {
   6565             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
   6566         } else {
   6567             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
   6568             onInitializeAccessibilityNodeInfo(info);
   6569             return info;
   6570         }
   6571     }
   6572 
   6573     /**
   6574      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
   6575      * The base implementation sets:
   6576      * <ul>
   6577      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
   6578      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
   6579      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
   6580      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
   6581      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
   6582      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
   6583      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
   6584      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
   6585      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
   6586      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
   6587      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
   6588      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
   6589      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
   6590      * </ul>
   6591      * <p>
   6592      * Subclasses should override this method, call the super implementation,
   6593      * and set additional attributes.
   6594      * </p>
   6595      * <p>
   6596      * If an {@link AccessibilityDelegate} has been specified via calling
   6597      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6598      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
   6599      * is responsible for handling this call.
   6600      * </p>
   6601      *
   6602      * @param info The instance to initialize.
   6603      */
   6604     @CallSuper
   6605     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
   6606         if (mAccessibilityDelegate != null) {
   6607             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
   6608         } else {
   6609             onInitializeAccessibilityNodeInfoInternal(info);
   6610         }
   6611     }
   6612 
   6613     /**
   6614      * Gets the location of this view in screen coordinates.
   6615      *
   6616      * @param outRect The output location
   6617      * @hide
   6618      */
   6619     public void getBoundsOnScreen(Rect outRect) {
   6620         getBoundsOnScreen(outRect, false);
   6621     }
   6622 
   6623     /**
   6624      * Gets the location of this view in screen coordinates.
   6625      *
   6626      * @param outRect The output location
   6627      * @param clipToParent Whether to clip child bounds to the parent ones.
   6628      * @hide
   6629      */
   6630     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
   6631         if (mAttachInfo == null) {
   6632             return;
   6633         }
   6634 
   6635         RectF position = mAttachInfo.mTmpTransformRect;
   6636         position.set(0, 0, mRight - mLeft, mBottom - mTop);
   6637 
   6638         if (!hasIdentityMatrix()) {
   6639             getMatrix().mapRect(position);
   6640         }
   6641 
   6642         position.offset(mLeft, mTop);
   6643 
   6644         ViewParent parent = mParent;
   6645         while (parent instanceof View) {
   6646             View parentView = (View) parent;
   6647 
   6648             position.offset(-parentView.mScrollX, -parentView.mScrollY);
   6649 
   6650             if (clipToParent) {
   6651                 position.left = Math.max(position.left, 0);
   6652                 position.top = Math.max(position.top, 0);
   6653                 position.right = Math.min(position.right, parentView.getWidth());
   6654                 position.bottom = Math.min(position.bottom, parentView.getHeight());
   6655             }
   6656 
   6657             if (!parentView.hasIdentityMatrix()) {
   6658                 parentView.getMatrix().mapRect(position);
   6659             }
   6660 
   6661             position.offset(parentView.mLeft, parentView.mTop);
   6662 
   6663             parent = parentView.mParent;
   6664         }
   6665 
   6666         if (parent instanceof ViewRootImpl) {
   6667             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
   6668             position.offset(0, -viewRootImpl.mCurScrollY);
   6669         }
   6670 
   6671         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
   6672 
   6673         outRect.set(Math.round(position.left), Math.round(position.top),
   6674                 Math.round(position.right), Math.round(position.bottom));
   6675     }
   6676 
   6677     /**
   6678      * Return the class name of this object to be used for accessibility purposes.
   6679      * Subclasses should only override this if they are implementing something that
   6680      * should be seen as a completely new class of view when used by accessibility,
   6681      * unrelated to the class it is deriving from.  This is used to fill in
   6682      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
   6683      */
   6684     public CharSequence getAccessibilityClassName() {
   6685         return View.class.getName();
   6686     }
   6687 
   6688     /**
   6689      * Called when assist structure is being retrieved from a view as part of
   6690      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
   6691      * @param structure Fill in with structured view data.  The default implementation
   6692      * fills in all data that can be inferred from the view itself.
   6693      */
   6694     public void onProvideStructure(ViewStructure structure) {
   6695         final int id = mID;
   6696         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
   6697                 && (id&0x0000ffff) != 0) {
   6698             String pkg, type, entry;
   6699             try {
   6700                 final Resources res = getResources();
   6701                 entry = res.getResourceEntryName(id);
   6702                 type = res.getResourceTypeName(id);
   6703                 pkg = res.getResourcePackageName(id);
   6704             } catch (Resources.NotFoundException e) {
   6705                 entry = type = pkg = null;
   6706             }
   6707             structure.setId(id, pkg, type, entry);
   6708         } else {
   6709             structure.setId(id, null, null, null);
   6710         }
   6711         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
   6712         if (!hasIdentityMatrix()) {
   6713             structure.setTransformation(getMatrix());
   6714         }
   6715         structure.setElevation(getZ());
   6716         structure.setVisibility(getVisibility());
   6717         structure.setEnabled(isEnabled());
   6718         if (isClickable()) {
   6719             structure.setClickable(true);
   6720         }
   6721         if (isFocusable()) {
   6722             structure.setFocusable(true);
   6723         }
   6724         if (isFocused()) {
   6725             structure.setFocused(true);
   6726         }
   6727         if (isAccessibilityFocused()) {
   6728             structure.setAccessibilityFocused(true);
   6729         }
   6730         if (isSelected()) {
   6731             structure.setSelected(true);
   6732         }
   6733         if (isActivated()) {
   6734             structure.setActivated(true);
   6735         }
   6736         if (isLongClickable()) {
   6737             structure.setLongClickable(true);
   6738         }
   6739         if (this instanceof Checkable) {
   6740             structure.setCheckable(true);
   6741             if (((Checkable)this).isChecked()) {
   6742                 structure.setChecked(true);
   6743             }
   6744         }
   6745         if (isContextClickable()) {
   6746             structure.setContextClickable(true);
   6747         }
   6748         structure.setClassName(getAccessibilityClassName().toString());
   6749         structure.setContentDescription(getContentDescription());
   6750     }
   6751 
   6752     /**
   6753      * Called when assist structure is being retrieved from a view as part of
   6754      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
   6755      * generate additional virtual structure under this view.  The defaullt implementation
   6756      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
   6757      * view's virtual accessibility nodes, if any.  You can override this for a more
   6758      * optimal implementation providing this data.
   6759      */
   6760     public void onProvideVirtualStructure(ViewStructure structure) {
   6761         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   6762         if (provider != null) {
   6763             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
   6764             structure.setChildCount(1);
   6765             ViewStructure root = structure.newChild(0);
   6766             populateVirtualStructure(root, provider, info);
   6767             info.recycle();
   6768         }
   6769     }
   6770 
   6771     private void populateVirtualStructure(ViewStructure structure,
   6772             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
   6773         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
   6774                 null, null, null);
   6775         Rect rect = structure.getTempRect();
   6776         info.getBoundsInParent(rect);
   6777         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
   6778         structure.setVisibility(VISIBLE);
   6779         structure.setEnabled(info.isEnabled());
   6780         if (info.isClickable()) {
   6781             structure.setClickable(true);
   6782         }
   6783         if (info.isFocusable()) {
   6784             structure.setFocusable(true);
   6785         }
   6786         if (info.isFocused()) {
   6787             structure.setFocused(true);
   6788         }
   6789         if (info.isAccessibilityFocused()) {
   6790             structure.setAccessibilityFocused(true);
   6791         }
   6792         if (info.isSelected()) {
   6793             structure.setSelected(true);
   6794         }
   6795         if (info.isLongClickable()) {
   6796             structure.setLongClickable(true);
   6797         }
   6798         if (info.isCheckable()) {
   6799             structure.setCheckable(true);
   6800             if (info.isChecked()) {
   6801                 structure.setChecked(true);
   6802             }
   6803         }
   6804         if (info.isContextClickable()) {
   6805             structure.setContextClickable(true);
   6806         }
   6807         CharSequence cname = info.getClassName();
   6808         structure.setClassName(cname != null ? cname.toString() : null);
   6809         structure.setContentDescription(info.getContentDescription());
   6810         if (info.getText() != null || info.getError() != null) {
   6811             structure.setText(info.getText(), info.getTextSelectionStart(),
   6812                     info.getTextSelectionEnd());
   6813         }
   6814         final int NCHILDREN = info.getChildCount();
   6815         if (NCHILDREN > 0) {
   6816             structure.setChildCount(NCHILDREN);
   6817             for (int i=0; i<NCHILDREN; i++) {
   6818                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
   6819                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
   6820                 ViewStructure child = structure.newChild(i);
   6821                 populateVirtualStructure(child, provider, cinfo);
   6822                 cinfo.recycle();
   6823             }
   6824         }
   6825     }
   6826 
   6827     /**
   6828      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
   6829      * implementation calls {@link #onProvideStructure} and
   6830      * {@link #onProvideVirtualStructure}.
   6831      */
   6832     public void dispatchProvideStructure(ViewStructure structure) {
   6833         if (!isAssistBlocked()) {
   6834             onProvideStructure(structure);
   6835             onProvideVirtualStructure(structure);
   6836         } else {
   6837             structure.setClassName(getAccessibilityClassName().toString());
   6838             structure.setAssistBlocked(true);
   6839         }
   6840     }
   6841 
   6842     /**
   6843      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   6844      *
   6845      * Note: Called from the default {@link AccessibilityDelegate}.
   6846      *
   6847      * @hide
   6848      */
   6849     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
   6850         if (mAttachInfo == null) {
   6851             return;
   6852         }
   6853 
   6854         Rect bounds = mAttachInfo.mTmpInvalRect;
   6855 
   6856         getDrawingRect(bounds);
   6857         info.setBoundsInParent(bounds);
   6858 
   6859         getBoundsOnScreen(bounds, true);
   6860         info.setBoundsInScreen(bounds);
   6861 
   6862         ViewParent parent = getParentForAccessibility();
   6863         if (parent instanceof View) {
   6864             info.setParent((View) parent);
   6865         }
   6866 
   6867         if (mID != View.NO_ID) {
   6868             View rootView = getRootView();
   6869             if (rootView == null) {
   6870                 rootView = this;
   6871             }
   6872 
   6873             View label = rootView.findLabelForView(this, mID);
   6874             if (label != null) {
   6875                 info.setLabeledBy(label);
   6876             }
   6877 
   6878             if ((mAttachInfo.mAccessibilityFetchFlags
   6879                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
   6880                     && Resources.resourceHasPackage(mID)) {
   6881                 try {
   6882                     String viewId = getResources().getResourceName(mID);
   6883                     info.setViewIdResourceName(viewId);
   6884                 } catch (Resources.NotFoundException nfe) {
   6885                     /* ignore */
   6886                 }
   6887             }
   6888         }
   6889 
   6890         if (mLabelForId != View.NO_ID) {
   6891             View rootView = getRootView();
   6892             if (rootView == null) {
   6893                 rootView = this;
   6894             }
   6895             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
   6896             if (labeled != null) {
   6897                 info.setLabelFor(labeled);
   6898             }
   6899         }
   6900 
   6901         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
   6902             View rootView = getRootView();
   6903             if (rootView == null) {
   6904                 rootView = this;
   6905             }
   6906             View next = rootView.findViewInsideOutShouldExist(this,
   6907                     mAccessibilityTraversalBeforeId);
   6908             if (next != null && next.includeForAccessibility()) {
   6909                 info.setTraversalBefore(next);
   6910             }
   6911         }
   6912 
   6913         if (mAccessibilityTraversalAfterId != View.NO_ID) {
   6914             View rootView = getRootView();
   6915             if (rootView == null) {
   6916                 rootView = this;
   6917             }
   6918             View next = rootView.findViewInsideOutShouldExist(this,
   6919                     mAccessibilityTraversalAfterId);
   6920             if (next != null && next.includeForAccessibility()) {
   6921                 info.setTraversalAfter(next);
   6922             }
   6923         }
   6924 
   6925         info.setVisibleToUser(isVisibleToUser());
   6926 
   6927         if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
   6928                 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
   6929             info.setImportantForAccessibility(isImportantForAccessibility());
   6930         } else {
   6931             info.setImportantForAccessibility(true);
   6932         }
   6933 
   6934         info.setPackageName(mContext.getPackageName());
   6935         info.setClassName(getAccessibilityClassName());
   6936         info.setContentDescription(getContentDescription());
   6937 
   6938         info.setEnabled(isEnabled());
   6939         info.setClickable(isClickable());
   6940         info.setFocusable(isFocusable());
   6941         info.setFocused(isFocused());
   6942         info.setAccessibilityFocused(isAccessibilityFocused());
   6943         info.setSelected(isSelected());
   6944         info.setLongClickable(isLongClickable());
   6945         info.setContextClickable(isContextClickable());
   6946         info.setLiveRegion(getAccessibilityLiveRegion());
   6947 
   6948         // TODO: These make sense only if we are in an AdapterView but all
   6949         // views can be selected. Maybe from accessibility perspective
   6950         // we should report as selectable view in an AdapterView.
   6951         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
   6952         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
   6953 
   6954         if (isFocusable()) {
   6955             if (isFocused()) {
   6956                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
   6957             } else {
   6958                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
   6959             }
   6960         }
   6961 
   6962         if (!isAccessibilityFocused()) {
   6963             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
   6964         } else {
   6965             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
   6966         }
   6967 
   6968         if (isClickable() && isEnabled()) {
   6969             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
   6970         }
   6971 
   6972         if (isLongClickable() && isEnabled()) {
   6973             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
   6974         }
   6975 
   6976         if (isContextClickable() && isEnabled()) {
   6977             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
   6978         }
   6979 
   6980         CharSequence text = getIterableTextForAccessibility();
   6981         if (text != null && text.length() > 0) {
   6982             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
   6983 
   6984             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
   6985             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
   6986             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
   6987             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
   6988                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
   6989                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
   6990         }
   6991 
   6992         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
   6993         populateAccessibilityNodeInfoDrawingOrderInParent(info);
   6994     }
   6995 
   6996     /**
   6997      * Determine the order in which this view will be drawn relative to its siblings for a11y
   6998      *
   6999      * @param info The info whose drawing order should be populated
   7000      */
   7001     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
   7002         /*
   7003          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
   7004          * drawing order may not be well-defined, and some Views with custom drawing order may
   7005          * not be initialized sufficiently to respond properly getChildDrawingOrder.
   7006          */
   7007         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
   7008             info.setDrawingOrder(0);
   7009             return;
   7010         }
   7011         int drawingOrderInParent = 1;
   7012         // Iterate up the hierarchy if parents are not important for a11y
   7013         View viewAtDrawingLevel = this;
   7014         final ViewParent parent = getParentForAccessibility();
   7015         while (viewAtDrawingLevel != parent) {
   7016             final ViewParent currentParent = viewAtDrawingLevel.getParent();
   7017             if (!(currentParent instanceof ViewGroup)) {
   7018                 // Should only happen for the Decor
   7019                 drawingOrderInParent = 0;
   7020                 break;
   7021             } else {
   7022                 final ViewGroup parentGroup = (ViewGroup) currentParent;
   7023                 final int childCount = parentGroup.getChildCount();
   7024                 if (childCount > 1) {
   7025                     List<View> preorderedList = parentGroup.buildOrderedChildList();
   7026                     if (preorderedList != null) {
   7027                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
   7028                         for (int i = 0; i < childDrawIndex; i++) {
   7029                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
   7030                         }
   7031                     } else {
   7032                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
   7033                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
   7034                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
   7035                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
   7036                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
   7037                         if (childDrawIndex != 0) {
   7038                             for (int i = 0; i < numChildrenToIterate; i++) {
   7039                                 final int otherDrawIndex = (customOrder ?
   7040                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
   7041                                 if (otherDrawIndex < childDrawIndex) {
   7042                                     drawingOrderInParent +=
   7043                                             numViewsForAccessibility(parentGroup.getChildAt(i));
   7044                                 }
   7045                             }
   7046                         }
   7047                     }
   7048                 }
   7049             }
   7050             viewAtDrawingLevel = (View) currentParent;
   7051         }
   7052         info.setDrawingOrder(drawingOrderInParent);
   7053     }
   7054 
   7055     private static int numViewsForAccessibility(View view) {
   7056         if (view != null) {
   7057             if (view.includeForAccessibility()) {
   7058                 return 1;
   7059             } else if (view instanceof ViewGroup) {
   7060                 return ((ViewGroup) view).getNumChildrenForAccessibility();
   7061             }
   7062         }
   7063         return 0;
   7064     }
   7065 
   7066     private View findLabelForView(View view, int labeledId) {
   7067         if (mMatchLabelForPredicate == null) {
   7068             mMatchLabelForPredicate = new MatchLabelForPredicate();
   7069         }
   7070         mMatchLabelForPredicate.mLabeledId = labeledId;
   7071         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
   7072     }
   7073 
   7074     /**
   7075      * Computes whether this view is visible to the user. Such a view is
   7076      * attached, visible, all its predecessors are visible, it is not clipped
   7077      * entirely by its predecessors, and has an alpha greater than zero.
   7078      *
   7079      * @return Whether the view is visible on the screen.
   7080      *
   7081      * @hide
   7082      */
   7083     protected boolean isVisibleToUser() {
   7084         return isVisibleToUser(null);
   7085     }
   7086 
   7087     /**
   7088      * Computes whether the given portion of this view is visible to the user.
   7089      * Such a view is attached, visible, all its predecessors are visible,
   7090      * has an alpha greater than zero, and the specified portion is not
   7091      * clipped entirely by its predecessors.
   7092      *
   7093      * @param boundInView the portion of the view to test; coordinates should be relative; may be
   7094      *                    <code>null</code>, and the entire view will be tested in this case.
   7095      *                    When <code>true</code> is returned by the function, the actual visible
   7096      *                    region will be stored in this parameter; that is, if boundInView is fully
   7097      *                    contained within the view, no modification will be made, otherwise regions
   7098      *                    outside of the visible area of the view will be clipped.
   7099      *
   7100      * @return Whether the specified portion of the view is visible on the screen.
   7101      *
   7102      * @hide
   7103      */
   7104     protected boolean isVisibleToUser(Rect boundInView) {
   7105         if (mAttachInfo != null) {
   7106             // Attached to invisible window means this view is not visible.
   7107             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
   7108                 return false;
   7109             }
   7110             // An invisible predecessor or one with alpha zero means
   7111             // that this view is not visible to the user.
   7112             Object current = this;
   7113             while (current instanceof View) {
   7114                 View view = (View) current;
   7115                 // We have attach info so this view is attached and there is no
   7116                 // need to check whether we reach to ViewRootImpl on the way up.
   7117                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
   7118                         view.getVisibility() != VISIBLE) {
   7119                     return false;
   7120                 }
   7121                 current = view.mParent;
   7122             }
   7123             // Check if the view is entirely covered by its predecessors.
   7124             Rect visibleRect = mAttachInfo.mTmpInvalRect;
   7125             Point offset = mAttachInfo.mPoint;
   7126             if (!getGlobalVisibleRect(visibleRect, offset)) {
   7127                 return false;
   7128             }
   7129             // Check if the visible portion intersects the rectangle of interest.
   7130             if (boundInView != null) {
   7131                 visibleRect.offset(-offset.x, -offset.y);
   7132                 return boundInView.intersect(visibleRect);
   7133             }
   7134             return true;
   7135         }
   7136         return false;
   7137     }
   7138 
   7139     /**
   7140      * Returns the delegate for implementing accessibility support via
   7141      * composition. For more details see {@link AccessibilityDelegate}.
   7142      *
   7143      * @return The delegate, or null if none set.
   7144      *
   7145      * @hide
   7146      */
   7147     public AccessibilityDelegate getAccessibilityDelegate() {
   7148         return mAccessibilityDelegate;
   7149     }
   7150 
   7151     /**
   7152      * Sets a delegate for implementing accessibility support via composition
   7153      * (as opposed to inheritance). For more details, see
   7154      * {@link AccessibilityDelegate}.
   7155      * <p>
   7156      * <strong>Note:</strong> On platform versions prior to
   7157      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
   7158      * views in the {@code android.widget.*} package are called <i>before</i>
   7159      * host methods. This prevents certain properties such as class name from
   7160      * being modified by overriding
   7161      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
   7162      * as any changes will be overwritten by the host class.
   7163      * <p>
   7164      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
   7165      * methods are called <i>after</i> host methods, which all properties to be
   7166      * modified without being overwritten by the host class.
   7167      *
   7168      * @param delegate the object to which accessibility method calls should be
   7169      *                 delegated
   7170      * @see AccessibilityDelegate
   7171      */
   7172     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
   7173         mAccessibilityDelegate = delegate;
   7174     }
   7175 
   7176     /**
   7177      * Gets the provider for managing a virtual view hierarchy rooted at this View
   7178      * and reported to {@link android.accessibilityservice.AccessibilityService}s
   7179      * that explore the window content.
   7180      * <p>
   7181      * If this method returns an instance, this instance is responsible for managing
   7182      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
   7183      * View including the one representing the View itself. Similarly the returned
   7184      * instance is responsible for performing accessibility actions on any virtual
   7185      * view or the root view itself.
   7186      * </p>
   7187      * <p>
   7188      * If an {@link AccessibilityDelegate} has been specified via calling
   7189      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7190      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
   7191      * is responsible for handling this call.
   7192      * </p>
   7193      *
   7194      * @return The provider.
   7195      *
   7196      * @see AccessibilityNodeProvider
   7197      */
   7198     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
   7199         if (mAccessibilityDelegate != null) {
   7200             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
   7201         } else {
   7202             return null;
   7203         }
   7204     }
   7205 
   7206     /**
   7207      * Gets the unique identifier of this view on the screen for accessibility purposes.
   7208      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
   7209      *
   7210      * @return The view accessibility id.
   7211      *
   7212      * @hide
   7213      */
   7214     public int getAccessibilityViewId() {
   7215         if (mAccessibilityViewId == NO_ID) {
   7216             mAccessibilityViewId = sNextAccessibilityViewId++;
   7217         }
   7218         return mAccessibilityViewId;
   7219     }
   7220 
   7221     /**
   7222      * Gets the unique identifier of the window in which this View reseides.
   7223      *
   7224      * @return The window accessibility id.
   7225      *
   7226      * @hide
   7227      */
   7228     public int getAccessibilityWindowId() {
   7229         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
   7230                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
   7231     }
   7232 
   7233     /**
   7234      * Returns the {@link View}'s content description.
   7235      * <p>
   7236      * <strong>Note:</strong> Do not override this method, as it will have no
   7237      * effect on the content description presented to accessibility services.
   7238      * You must call {@link #setContentDescription(CharSequence)} to modify the
   7239      * content description.
   7240      *
   7241      * @return the content description
   7242      * @see #setContentDescription(CharSequence)
   7243      * @attr ref android.R.styleable#View_contentDescription
   7244      */
   7245     @ViewDebug.ExportedProperty(category = "accessibility")
   7246     public CharSequence getContentDescription() {
   7247         return mContentDescription;
   7248     }
   7249 
   7250     /**
   7251      * Sets the {@link View}'s content description.
   7252      * <p>
   7253      * A content description briefly describes the view and is primarily used
   7254      * for accessibility support to determine how a view should be presented to
   7255      * the user. In the case of a view with no textual representation, such as
   7256      * {@link android.widget.ImageButton}, a useful content description
   7257      * explains what the view does. For example, an image button with a phone
   7258      * icon that is used to place a call may use "Call" as its content
   7259      * description. An image of a floppy disk that is used to save a file may
   7260      * use "Save".
   7261      *
   7262      * @param contentDescription The content description.
   7263      * @see #getContentDescription()
   7264      * @attr ref android.R.styleable#View_contentDescription
   7265      */
   7266     @RemotableViewMethod
   7267     public void setContentDescription(CharSequence contentDescription) {
   7268         if (mContentDescription == null) {
   7269             if (contentDescription == null) {
   7270                 return;
   7271             }
   7272         } else if (mContentDescription.equals(contentDescription)) {
   7273             return;
   7274         }
   7275         mContentDescription = contentDescription;
   7276         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
   7277         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
   7278             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
   7279             notifySubtreeAccessibilityStateChangedIfNeeded();
   7280         } else {
   7281             notifyViewAccessibilityStateChangedIfNeeded(
   7282                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
   7283         }
   7284     }
   7285 
   7286     /**
   7287      * Sets the id of a view before which this one is visited in accessibility traversal.
   7288      * A screen-reader must visit the content of this view before the content of the one
   7289      * it precedes. For example, if view B is set to be before view A, then a screen-reader
   7290      * will traverse the entire content of B before traversing the entire content of A,
   7291      * regardles of what traversal strategy it is using.
   7292      * <p>
   7293      * Views that do not have specified before/after relationships are traversed in order
   7294      * determined by the screen-reader.
   7295      * </p>
   7296      * <p>
   7297      * Setting that this view is before a view that is not important for accessibility
   7298      * or if this view is not important for accessibility will have no effect as the
   7299      * screen-reader is not aware of unimportant views.
   7300      * </p>
   7301      *
   7302      * @param beforeId The id of a view this one precedes in accessibility traversal.
   7303      *
   7304      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
   7305      *
   7306      * @see #setImportantForAccessibility(int)
   7307      */
   7308     @RemotableViewMethod
   7309     public void setAccessibilityTraversalBefore(int beforeId) {
   7310         if (mAccessibilityTraversalBeforeId == beforeId) {
   7311             return;
   7312         }
   7313         mAccessibilityTraversalBeforeId = beforeId;
   7314         notifyViewAccessibilityStateChangedIfNeeded(
   7315                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   7316     }
   7317 
   7318     /**
   7319      * Gets the id of a view before which this one is visited in accessibility traversal.
   7320      *
   7321      * @return The id of a view this one precedes in accessibility traversal if
   7322      *         specified, otherwise {@link #NO_ID}.
   7323      *
   7324      * @see #setAccessibilityTraversalBefore(int)
   7325      */
   7326     public int getAccessibilityTraversalBefore() {
   7327         return mAccessibilityTraversalBeforeId;
   7328     }
   7329 
   7330     /**
   7331      * Sets the id of a view after which this one is visited in accessibility traversal.
   7332      * A screen-reader must visit the content of the other view before the content of this
   7333      * one. For example, if view B is set to be after view A, then a screen-reader
   7334      * will traverse the entire content of A before traversing the entire content of B,
   7335      * regardles of what traversal strategy it is using.
   7336      * <p>
   7337      * Views that do not have specified before/after relationships are traversed in order
   7338      * determined by the screen-reader.
   7339      * </p>
   7340      * <p>
   7341      * Setting that this view is after a view that is not important for accessibility
   7342      * or if this view is not important for accessibility will have no effect as the
   7343      * screen-reader is not aware of unimportant views.
   7344      * </p>
   7345      *
   7346      * @param afterId The id of a view this one succedees in accessibility traversal.
   7347      *
   7348      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
   7349      *
   7350      * @see #setImportantForAccessibility(int)
   7351      */
   7352     @RemotableViewMethod
   7353     public void setAccessibilityTraversalAfter(int afterId) {
   7354         if (mAccessibilityTraversalAfterId == afterId) {
   7355             return;
   7356         }
   7357         mAccessibilityTraversalAfterId = afterId;
   7358         notifyViewAccessibilityStateChangedIfNeeded(
   7359                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   7360     }
   7361 
   7362     /**
   7363      * Gets the id of a view after which this one is visited in accessibility traversal.
   7364      *
   7365      * @return The id of a view this one succeedes in accessibility traversal if
   7366      *         specified, otherwise {@link #NO_ID}.
   7367      *
   7368      * @see #setAccessibilityTraversalAfter(int)
   7369      */
   7370     public int getAccessibilityTraversalAfter() {
   7371         return mAccessibilityTraversalAfterId;
   7372     }
   7373 
   7374     /**
   7375      * Gets the id of a view for which this view serves as a label for
   7376      * accessibility purposes.
   7377      *
   7378      * @return The labeled view id.
   7379      */
   7380     @ViewDebug.ExportedProperty(category = "accessibility")
   7381     public int getLabelFor() {
   7382         return mLabelForId;
   7383     }
   7384 
   7385     /**
   7386      * Sets the id of a view for which this view serves as a label for
   7387      * accessibility purposes.
   7388      *
   7389      * @param id The labeled view id.
   7390      */
   7391     @RemotableViewMethod
   7392     public void setLabelFor(@IdRes int id) {
   7393         if (mLabelForId == id) {
   7394             return;
   7395         }
   7396         mLabelForId = id;
   7397         if (mLabelForId != View.NO_ID
   7398                 && mID == View.NO_ID) {
   7399             mID = generateViewId();
   7400         }
   7401         notifyViewAccessibilityStateChangedIfNeeded(
   7402                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   7403     }
   7404 
   7405     /**
   7406      * Invoked whenever this view loses focus, either by losing window focus or by losing
   7407      * focus within its window. This method can be used to clear any state tied to the
   7408      * focus. For instance, if a button is held pressed with the trackball and the window
   7409      * loses focus, this method can be used to cancel the press.
   7410      *
   7411      * Subclasses of View overriding this method should always call super.onFocusLost().
   7412      *
   7413      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
   7414      * @see #onWindowFocusChanged(boolean)
   7415      *
   7416      * @hide pending API council approval
   7417      */
   7418     @CallSuper
   7419     protected void onFocusLost() {
   7420         resetPressedState();
   7421     }
   7422 
   7423     private void resetPressedState() {
   7424         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   7425             return;
   7426         }
   7427 
   7428         if (isPressed()) {
   7429             setPressed(false);
   7430 
   7431             if (!mHasPerformedLongPress) {
   7432                 removeLongPressCallback();
   7433             }
   7434         }
   7435     }
   7436 
   7437     /**
   7438      * Returns true if this view has focus
   7439      *
   7440      * @return True if this view has focus, false otherwise.
   7441      */
   7442     @ViewDebug.ExportedProperty(category = "focus")
   7443     public boolean isFocused() {
   7444         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   7445     }
   7446 
   7447     /**
   7448      * Find the view in the hierarchy rooted at this view that currently has
   7449      * focus.
   7450      *
   7451      * @return The view that currently has focus, or null if no focused view can
   7452      *         be found.
   7453      */
   7454     public View findFocus() {
   7455         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
   7456     }
   7457 
   7458     /**
   7459      * Indicates whether this view is one of the set of scrollable containers in
   7460      * its window.
   7461      *
   7462      * @return whether this view is one of the set of scrollable containers in
   7463      * its window
   7464      *
   7465      * @attr ref android.R.styleable#View_isScrollContainer
   7466      */
   7467     public boolean isScrollContainer() {
   7468         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
   7469     }
   7470 
   7471     /**
   7472      * Change whether this view is one of the set of scrollable containers in
   7473      * its window.  This will be used to determine whether the window can
   7474      * resize or must pan when a soft input area is open -- scrollable
   7475      * containers allow the window to use resize mode since the container
   7476      * will appropriately shrink.
   7477      *
   7478      * @attr ref android.R.styleable#View_isScrollContainer
   7479      */
   7480     public void setScrollContainer(boolean isScrollContainer) {
   7481         if (isScrollContainer) {
   7482             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
   7483                 mAttachInfo.mScrollContainers.add(this);
   7484                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   7485             }
   7486             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
   7487         } else {
   7488             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   7489                 mAttachInfo.mScrollContainers.remove(this);
   7490             }
   7491             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
   7492         }
   7493     }
   7494 
   7495     /**
   7496      * Returns the quality of the drawing cache.
   7497      *
   7498      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   7499      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   7500      *
   7501      * @see #setDrawingCacheQuality(int)
   7502      * @see #setDrawingCacheEnabled(boolean)
   7503      * @see #isDrawingCacheEnabled()
   7504      *
   7505      * @attr ref android.R.styleable#View_drawingCacheQuality
   7506      */
   7507     @DrawingCacheQuality
   7508     public int getDrawingCacheQuality() {
   7509         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
   7510     }
   7511 
   7512     /**
   7513      * Set the drawing cache quality of this view. This value is used only when the
   7514      * drawing cache is enabled
   7515      *
   7516      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   7517      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   7518      *
   7519      * @see #getDrawingCacheQuality()
   7520      * @see #setDrawingCacheEnabled(boolean)
   7521      * @see #isDrawingCacheEnabled()
   7522      *
   7523      * @attr ref android.R.styleable#View_drawingCacheQuality
   7524      */
   7525     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
   7526         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
   7527     }
   7528 
   7529     /**
   7530      * Returns whether the screen should remain on, corresponding to the current
   7531      * value of {@link #KEEP_SCREEN_ON}.
   7532      *
   7533      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
   7534      *
   7535      * @see #setKeepScreenOn(boolean)
   7536      *
   7537      * @attr ref android.R.styleable#View_keepScreenOn
   7538      */
   7539     public boolean getKeepScreenOn() {
   7540         return (mViewFlags & KEEP_SCREEN_ON) != 0;
   7541     }
   7542 
   7543     /**
   7544      * Controls whether the screen should remain on, modifying the
   7545      * value of {@link #KEEP_SCREEN_ON}.
   7546      *
   7547      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
   7548      *
   7549      * @see #getKeepScreenOn()
   7550      *
   7551      * @attr ref android.R.styleable#View_keepScreenOn
   7552      */
   7553     public void setKeepScreenOn(boolean keepScreenOn) {
   7554         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
   7555     }
   7556 
   7557     /**
   7558      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   7559      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7560      *
   7561      * @attr ref android.R.styleable#View_nextFocusLeft
   7562      */
   7563     public int getNextFocusLeftId() {
   7564         return mNextFocusLeftId;
   7565     }
   7566 
   7567     /**
   7568      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   7569      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
   7570      * decide automatically.
   7571      *
   7572      * @attr ref android.R.styleable#View_nextFocusLeft
   7573      */
   7574     public void setNextFocusLeftId(int nextFocusLeftId) {
   7575         mNextFocusLeftId = nextFocusLeftId;
   7576     }
   7577 
   7578     /**
   7579      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   7580      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7581      *
   7582      * @attr ref android.R.styleable#View_nextFocusRight
   7583      */
   7584     public int getNextFocusRightId() {
   7585         return mNextFocusRightId;
   7586     }
   7587 
   7588     /**
   7589      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   7590      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
   7591      * decide automatically.
   7592      *
   7593      * @attr ref android.R.styleable#View_nextFocusRight
   7594      */
   7595     public void setNextFocusRightId(int nextFocusRightId) {
   7596         mNextFocusRightId = nextFocusRightId;
   7597     }
   7598 
   7599     /**
   7600      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   7601      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7602      *
   7603      * @attr ref android.R.styleable#View_nextFocusUp
   7604      */
   7605     public int getNextFocusUpId() {
   7606         return mNextFocusUpId;
   7607     }
   7608 
   7609     /**
   7610      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   7611      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
   7612      * decide automatically.
   7613      *
   7614      * @attr ref android.R.styleable#View_nextFocusUp
   7615      */
   7616     public void setNextFocusUpId(int nextFocusUpId) {
   7617         mNextFocusUpId = nextFocusUpId;
   7618     }
   7619 
   7620     /**
   7621      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   7622      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7623      *
   7624      * @attr ref android.R.styleable#View_nextFocusDown
   7625      */
   7626     public int getNextFocusDownId() {
   7627         return mNextFocusDownId;
   7628     }
   7629 
   7630     /**
   7631      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   7632      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
   7633      * decide automatically.
   7634      *
   7635      * @attr ref android.R.styleable#View_nextFocusDown
   7636      */
   7637     public void setNextFocusDownId(int nextFocusDownId) {
   7638         mNextFocusDownId = nextFocusDownId;
   7639     }
   7640 
   7641     /**
   7642      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   7643      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7644      *
   7645      * @attr ref android.R.styleable#View_nextFocusForward
   7646      */
   7647     public int getNextFocusForwardId() {
   7648         return mNextFocusForwardId;
   7649     }
   7650 
   7651     /**
   7652      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   7653      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
   7654      * decide automatically.
   7655      *
   7656      * @attr ref android.R.styleable#View_nextFocusForward
   7657      */
   7658     public void setNextFocusForwardId(int nextFocusForwardId) {
   7659         mNextFocusForwardId = nextFocusForwardId;
   7660     }
   7661 
   7662     /**
   7663      * Returns the visibility of this view and all of its ancestors
   7664      *
   7665      * @return True if this view and all of its ancestors are {@link #VISIBLE}
   7666      */
   7667     public boolean isShown() {
   7668         View current = this;
   7669         //noinspection ConstantConditions
   7670         do {
   7671             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   7672                 return false;
   7673             }
   7674             ViewParent parent = current.mParent;
   7675             if (parent == null) {
   7676                 return false; // We are not attached to the view root
   7677             }
   7678             if (!(parent instanceof View)) {
   7679                 return true;
   7680             }
   7681             current = (View) parent;
   7682         } while (current != null);
   7683 
   7684         return false;
   7685     }
   7686 
   7687     /**
   7688      * Called by the view hierarchy when the content insets for a window have
   7689      * changed, to allow it to adjust its content to fit within those windows.
   7690      * The content insets tell you the space that the status bar, input method,
   7691      * and other system windows infringe on the application's window.
   7692      *
   7693      * <p>You do not normally need to deal with this function, since the default
   7694      * window decoration given to applications takes care of applying it to the
   7695      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   7696      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
   7697      * and your content can be placed under those system elements.  You can then
   7698      * use this method within your view hierarchy if you have parts of your UI
   7699      * which you would like to ensure are not being covered.
   7700      *
   7701      * <p>The default implementation of this method simply applies the content
   7702      * insets to the view's padding, consuming that content (modifying the
   7703      * insets to be 0), and returning true.  This behavior is off by default, but can
   7704      * be enabled through {@link #setFitsSystemWindows(boolean)}.
   7705      *
   7706      * <p>This function's traversal down the hierarchy is depth-first.  The same content
   7707      * insets object is propagated down the hierarchy, so any changes made to it will
   7708      * be seen by all following views (including potentially ones above in
   7709      * the hierarchy since this is a depth-first traversal).  The first view
   7710      * that returns true will abort the entire traversal.
   7711      *
   7712      * <p>The default implementation works well for a situation where it is
   7713      * used with a container that covers the entire window, allowing it to
   7714      * apply the appropriate insets to its content on all edges.  If you need
   7715      * a more complicated layout (such as two different views fitting system
   7716      * windows, one on the top of the window, and one on the bottom),
   7717      * you can override the method and handle the insets however you would like.
   7718      * Note that the insets provided by the framework are always relative to the
   7719      * far edges of the window, not accounting for the location of the called view
   7720      * within that window.  (In fact when this method is called you do not yet know
   7721      * where the layout will place the view, as it is done before layout happens.)
   7722      *
   7723      * <p>Note: unlike many View methods, there is no dispatch phase to this
   7724      * call.  If you are overriding it in a ViewGroup and want to allow the
   7725      * call to continue to your children, you must be sure to call the super
   7726      * implementation.
   7727      *
   7728      * <p>Here is a sample layout that makes use of fitting system windows
   7729      * to have controls for a video view placed inside of the window decorations
   7730      * that it hides and shows.  This can be used with code like the second
   7731      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
   7732      *
   7733      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
   7734      *
   7735      * @param insets Current content insets of the window.  Prior to
   7736      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
   7737      * the insets or else you and Android will be unhappy.
   7738      *
   7739      * @return {@code true} if this view applied the insets and it should not
   7740      * continue propagating further down the hierarchy, {@code false} otherwise.
   7741      * @see #getFitsSystemWindows()
   7742      * @see #setFitsSystemWindows(boolean)
   7743      * @see #setSystemUiVisibility(int)
   7744      *
   7745      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
   7746      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
   7747      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
   7748      * to implement handling their own insets.
   7749      */
   7750     protected boolean fitSystemWindows(Rect insets) {
   7751         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
   7752             if (insets == null) {
   7753                 // Null insets by definition have already been consumed.
   7754                 // This call cannot apply insets since there are none to apply,
   7755                 // so return false.
   7756                 return false;
   7757             }
   7758             // If we're not in the process of dispatching the newer apply insets call,
   7759             // that means we're not in the compatibility path. Dispatch into the newer
   7760             // apply insets path and take things from there.
   7761             try {
   7762                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
   7763                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
   7764             } finally {
   7765                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
   7766             }
   7767         } else {
   7768             // We're being called from the newer apply insets path.
   7769             // Perform the standard fallback behavior.
   7770             return fitSystemWindowsInt(insets);
   7771         }
   7772     }
   7773 
   7774     private boolean fitSystemWindowsInt(Rect insets) {
   7775         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
   7776             mUserPaddingStart = UNDEFINED_PADDING;
   7777             mUserPaddingEnd = UNDEFINED_PADDING;
   7778             Rect localInsets = sThreadLocal.get();
   7779             if (localInsets == null) {
   7780                 localInsets = new Rect();
   7781                 sThreadLocal.set(localInsets);
   7782             }
   7783             boolean res = computeFitSystemWindows(insets, localInsets);
   7784             mUserPaddingLeftInitial = localInsets.left;
   7785             mUserPaddingRightInitial = localInsets.right;
   7786             internalSetPadding(localInsets.left, localInsets.top,
   7787                     localInsets.right, localInsets.bottom);
   7788             return res;
   7789         }
   7790         return false;
   7791     }
   7792 
   7793     /**
   7794      * Called when the view should apply {@link WindowInsets} according to its internal policy.
   7795      *
   7796      * <p>This method should be overridden by views that wish to apply a policy different from or
   7797      * in addition to the default behavior. Clients that wish to force a view subtree
   7798      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
   7799      *
   7800      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
   7801      * it will be called during dispatch instead of this method. The listener may optionally
   7802      * call this method from its own implementation if it wishes to apply the view's default
   7803      * insets policy in addition to its own.</p>
   7804      *
   7805      * <p>Implementations of this method should either return the insets parameter unchanged
   7806      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
   7807      * that this view applied itself. This allows new inset types added in future platform
   7808      * versions to pass through existing implementations unchanged without being erroneously
   7809      * consumed.</p>
   7810      *
   7811      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
   7812      * property is set then the view will consume the system window insets and apply them
   7813      * as padding for the view.</p>
   7814      *
   7815      * @param insets Insets to apply
   7816      * @return The supplied insets with any applied insets consumed
   7817      */
   7818     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
   7819         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
   7820             // We weren't called from within a direct call to fitSystemWindows,
   7821             // call into it as a fallback in case we're in a class that overrides it
   7822             // and has logic to perform.
   7823             if (fitSystemWindows(insets.getSystemWindowInsets())) {
   7824                 return insets.consumeSystemWindowInsets();
   7825             }
   7826         } else {
   7827             // We were called from within a direct call to fitSystemWindows.
   7828             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
   7829                 return insets.consumeSystemWindowInsets();
   7830             }
   7831         }
   7832         return insets;
   7833     }
   7834 
   7835     /**
   7836      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
   7837      * window insets to this view. The listener's
   7838      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   7839      * method will be called instead of the view's
   7840      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   7841      *
   7842      * @param listener Listener to set
   7843      *
   7844      * @see #onApplyWindowInsets(WindowInsets)
   7845      */
   7846     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
   7847         getListenerInfo().mOnApplyWindowInsetsListener = listener;
   7848     }
   7849 
   7850     /**
   7851      * Request to apply the given window insets to this view or another view in its subtree.
   7852      *
   7853      * <p>This method should be called by clients wishing to apply insets corresponding to areas
   7854      * obscured by window decorations or overlays. This can include the status and navigation bars,
   7855      * action bars, input methods and more. New inset categories may be added in the future.
   7856      * The method returns the insets provided minus any that were applied by this view or its
   7857      * children.</p>
   7858      *
   7859      * <p>Clients wishing to provide custom behavior should override the
   7860      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
   7861      * {@link OnApplyWindowInsetsListener} via the
   7862      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
   7863      * method.</p>
   7864      *
   7865      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
   7866      * </p>
   7867      *
   7868      * @param insets Insets to apply
   7869      * @return The provided insets minus the insets that were consumed
   7870      */
   7871     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
   7872         try {
   7873             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
   7874             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
   7875                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
   7876             } else {
   7877                 return onApplyWindowInsets(insets);
   7878             }
   7879         } finally {
   7880             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
   7881         }
   7882     }
   7883 
   7884     /**
   7885      * Compute the view's coordinate within the surface.
   7886      *
   7887      * <p>Computes the coordinates of this view in its surface. The argument
   7888      * must be an array of two integers. After the method returns, the array
   7889      * contains the x and y location in that order.</p>
   7890      * @hide
   7891      * @param location an array of two integers in which to hold the coordinates
   7892      */
   7893     public void getLocationInSurface(@Size(2) int[] location) {
   7894         getLocationInWindow(location);
   7895         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
   7896             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
   7897             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
   7898         }
   7899     }
   7900 
   7901     /**
   7902      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
   7903      * only available if the view is attached.
   7904      *
   7905      * @return WindowInsets from the top of the view hierarchy or null if View is detached
   7906      */
   7907     public WindowInsets getRootWindowInsets() {
   7908         if (mAttachInfo != null) {
   7909             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
   7910         }
   7911         return null;
   7912     }
   7913 
   7914     /**
   7915      * @hide Compute the insets that should be consumed by this view and the ones
   7916      * that should propagate to those under it.
   7917      */
   7918     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
   7919         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
   7920                 || mAttachInfo == null
   7921                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
   7922                         && !mAttachInfo.mOverscanRequested)) {
   7923             outLocalInsets.set(inoutInsets);
   7924             inoutInsets.set(0, 0, 0, 0);
   7925             return true;
   7926         } else {
   7927             // The application wants to take care of fitting system window for
   7928             // the content...  however we still need to take care of any overscan here.
   7929             final Rect overscan = mAttachInfo.mOverscanInsets;
   7930             outLocalInsets.set(overscan);
   7931             inoutInsets.left -= overscan.left;
   7932             inoutInsets.top -= overscan.top;
   7933             inoutInsets.right -= overscan.right;
   7934             inoutInsets.bottom -= overscan.bottom;
   7935             return false;
   7936         }
   7937     }
   7938 
   7939     /**
   7940      * Compute insets that should be consumed by this view and the ones that should propagate
   7941      * to those under it.
   7942      *
   7943      * @param in Insets currently being processed by this View, likely received as a parameter
   7944      *           to {@link #onApplyWindowInsets(WindowInsets)}.
   7945      * @param outLocalInsets A Rect that will receive the insets that should be consumed
   7946      *                       by this view
   7947      * @return Insets that should be passed along to views under this one
   7948      */
   7949     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
   7950         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
   7951                 || mAttachInfo == null
   7952                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
   7953             outLocalInsets.set(in.getSystemWindowInsets());
   7954             return in.consumeSystemWindowInsets();
   7955         } else {
   7956             outLocalInsets.set(0, 0, 0, 0);
   7957             return in;
   7958         }
   7959     }
   7960 
   7961     /**
   7962      * Sets whether or not this view should account for system screen decorations
   7963      * such as the status bar and inset its content; that is, controlling whether
   7964      * the default implementation of {@link #fitSystemWindows(Rect)} will be
   7965      * executed.  See that method for more details.
   7966      *
   7967      * <p>Note that if you are providing your own implementation of
   7968      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
   7969      * flag to true -- your implementation will be overriding the default
   7970      * implementation that checks this flag.
   7971      *
   7972      * @param fitSystemWindows If true, then the default implementation of
   7973      * {@link #fitSystemWindows(Rect)} will be executed.
   7974      *
   7975      * @attr ref android.R.styleable#View_fitsSystemWindows
   7976      * @see #getFitsSystemWindows()
   7977      * @see #fitSystemWindows(Rect)
   7978      * @see #setSystemUiVisibility(int)
   7979      */
   7980     public void setFitsSystemWindows(boolean fitSystemWindows) {
   7981         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
   7982     }
   7983 
   7984     /**
   7985      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
   7986      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
   7987      * will be executed.
   7988      *
   7989      * @return {@code true} if the default implementation of
   7990      * {@link #fitSystemWindows(Rect)} will be executed.
   7991      *
   7992      * @attr ref android.R.styleable#View_fitsSystemWindows
   7993      * @see #setFitsSystemWindows(boolean)
   7994      * @see #fitSystemWindows(Rect)
   7995      * @see #setSystemUiVisibility(int)
   7996      */
   7997     @ViewDebug.ExportedProperty
   7998     public boolean getFitsSystemWindows() {
   7999         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
   8000     }
   8001 
   8002     /** @hide */
   8003     public boolean fitsSystemWindows() {
   8004         return getFitsSystemWindows();
   8005     }
   8006 
   8007     /**
   8008      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
   8009      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
   8010      */
   8011     public void requestFitSystemWindows() {
   8012         if (mParent != null) {
   8013             mParent.requestFitSystemWindows();
   8014         }
   8015     }
   8016 
   8017     /**
   8018      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
   8019      */
   8020     public void requestApplyInsets() {
   8021         requestFitSystemWindows();
   8022     }
   8023 
   8024     /**
   8025      * For use by PhoneWindow to make its own system window fitting optional.
   8026      * @hide
   8027      */
   8028     public void makeOptionalFitsSystemWindows() {
   8029         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
   8030     }
   8031 
   8032     /**
   8033      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
   8034      * treat them as such.
   8035      * @hide
   8036      */
   8037     public void getOutsets(Rect outOutsetRect) {
   8038         if (mAttachInfo != null) {
   8039             outOutsetRect.set(mAttachInfo.mOutsets);
   8040         } else {
   8041             outOutsetRect.setEmpty();
   8042         }
   8043     }
   8044 
   8045     /**
   8046      * Returns the visibility status for this view.
   8047      *
   8048      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   8049      * @attr ref android.R.styleable#View_visibility
   8050      */
   8051     @ViewDebug.ExportedProperty(mapping = {
   8052         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
   8053         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
   8054         @ViewDebug.IntToString(from = GONE,      to = "GONE")
   8055     })
   8056     @Visibility
   8057     public int getVisibility() {
   8058         return mViewFlags & VISIBILITY_MASK;
   8059     }
   8060 
   8061     /**
   8062      * Set the visibility state of this view.
   8063      *
   8064      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   8065      * @attr ref android.R.styleable#View_visibility
   8066      */
   8067     @RemotableViewMethod
   8068     public void setVisibility(@Visibility int visibility) {
   8069         setFlags(visibility, VISIBILITY_MASK);
   8070     }
   8071 
   8072     /**
   8073      * Returns the enabled status for this view. The interpretation of the
   8074      * enabled state varies by subclass.
   8075      *
   8076      * @return True if this view is enabled, false otherwise.
   8077      */
   8078     @ViewDebug.ExportedProperty
   8079     public boolean isEnabled() {
   8080         return (mViewFlags & ENABLED_MASK) == ENABLED;
   8081     }
   8082 
   8083     /**
   8084      * Set the enabled state of this view. The interpretation of the enabled
   8085      * state varies by subclass.
   8086      *
   8087      * @param enabled True if this view is enabled, false otherwise.
   8088      */
   8089     @RemotableViewMethod
   8090     public void setEnabled(boolean enabled) {
   8091         if (enabled == isEnabled()) return;
   8092 
   8093         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
   8094 
   8095         /*
   8096          * The View most likely has to change its appearance, so refresh
   8097          * the drawable state.
   8098          */
   8099         refreshDrawableState();
   8100 
   8101         // Invalidate too, since the default behavior for views is to be
   8102         // be drawn at 50% alpha rather than to change the drawable.
   8103         invalidate(true);
   8104 
   8105         if (!enabled) {
   8106             cancelPendingInputEvents();
   8107         }
   8108     }
   8109 
   8110     /**
   8111      * Set whether this view can receive the focus.
   8112      *
   8113      * Setting this to false will also ensure that this view is not focusable
   8114      * in touch mode.
   8115      *
   8116      * @param focusable If true, this view can receive the focus.
   8117      *
   8118      * @see #setFocusableInTouchMode(boolean)
   8119      * @attr ref android.R.styleable#View_focusable
   8120      */
   8121     public void setFocusable(boolean focusable) {
   8122         if (!focusable) {
   8123             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
   8124         }
   8125         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
   8126     }
   8127 
   8128     /**
   8129      * Set whether this view can receive focus while in touch mode.
   8130      *
   8131      * Setting this to true will also ensure that this view is focusable.
   8132      *
   8133      * @param focusableInTouchMode If true, this view can receive the focus while
   8134      *   in touch mode.
   8135      *
   8136      * @see #setFocusable(boolean)
   8137      * @attr ref android.R.styleable#View_focusableInTouchMode
   8138      */
   8139     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
   8140         // Focusable in touch mode should always be set before the focusable flag
   8141         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
   8142         // which, in touch mode, will not successfully request focus on this view
   8143         // because the focusable in touch mode flag is not set
   8144         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
   8145         if (focusableInTouchMode) {
   8146             setFlags(FOCUSABLE, FOCUSABLE_MASK);
   8147         }
   8148     }
   8149 
   8150     /**
   8151      * Set whether this view should have sound effects enabled for events such as
   8152      * clicking and touching.
   8153      *
   8154      * <p>You may wish to disable sound effects for a view if you already play sounds,
   8155      * for instance, a dial key that plays dtmf tones.
   8156      *
   8157      * @param soundEffectsEnabled whether sound effects are enabled for this view.
   8158      * @see #isSoundEffectsEnabled()
   8159      * @see #playSoundEffect(int)
   8160      * @attr ref android.R.styleable#View_soundEffectsEnabled
   8161      */
   8162     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
   8163         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
   8164     }
   8165 
   8166     /**
   8167      * @return whether this view should have sound effects enabled for events such as
   8168      *     clicking and touching.
   8169      *
   8170      * @see #setSoundEffectsEnabled(boolean)
   8171      * @see #playSoundEffect(int)
   8172      * @attr ref android.R.styleable#View_soundEffectsEnabled
   8173      */
   8174     @ViewDebug.ExportedProperty
   8175     public boolean isSoundEffectsEnabled() {
   8176         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
   8177     }
   8178 
   8179     /**
   8180      * Set whether this view should have haptic feedback for events such as
   8181      * long presses.
   8182      *
   8183      * <p>You may wish to disable haptic feedback if your view already controls
   8184      * its own haptic feedback.
   8185      *
   8186      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
   8187      * @see #isHapticFeedbackEnabled()
   8188      * @see #performHapticFeedback(int)
   8189      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   8190      */
   8191     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
   8192         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
   8193     }
   8194 
   8195     /**
   8196      * @return whether this view should have haptic feedback enabled for events
   8197      * long presses.
   8198      *
   8199      * @see #setHapticFeedbackEnabled(boolean)
   8200      * @see #performHapticFeedback(int)
   8201      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   8202      */
   8203     @ViewDebug.ExportedProperty
   8204     public boolean isHapticFeedbackEnabled() {
   8205         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
   8206     }
   8207 
   8208     /**
   8209      * Returns the layout direction for this view.
   8210      *
   8211      * @return One of {@link #LAYOUT_DIRECTION_LTR},
   8212      *   {@link #LAYOUT_DIRECTION_RTL},
   8213      *   {@link #LAYOUT_DIRECTION_INHERIT} or
   8214      *   {@link #LAYOUT_DIRECTION_LOCALE}.
   8215      *
   8216      * @attr ref android.R.styleable#View_layoutDirection
   8217      *
   8218      * @hide
   8219      */
   8220     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   8221         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
   8222         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
   8223         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
   8224         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
   8225     })
   8226     @LayoutDir
   8227     public int getRawLayoutDirection() {
   8228         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   8229     }
   8230 
   8231     /**
   8232      * Set the layout direction for this view. This will propagate a reset of layout direction
   8233      * resolution to the view's children and resolve layout direction for this view.
   8234      *
   8235      * @param layoutDirection the layout direction to set. Should be one of:
   8236      *
   8237      * {@link #LAYOUT_DIRECTION_LTR},
   8238      * {@link #LAYOUT_DIRECTION_RTL},
   8239      * {@link #LAYOUT_DIRECTION_INHERIT},
   8240      * {@link #LAYOUT_DIRECTION_LOCALE}.
   8241      *
   8242      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
   8243      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   8244      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
   8245      *
   8246      * @attr ref android.R.styleable#View_layoutDirection
   8247      */
   8248     @RemotableViewMethod
   8249     public void setLayoutDirection(@LayoutDir int layoutDirection) {
   8250         if (getRawLayoutDirection() != layoutDirection) {
   8251             // Reset the current layout direction and the resolved one
   8252             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
   8253             resetRtlProperties();
   8254             // Set the new layout direction (filtered)
   8255             mPrivateFlags2 |=
   8256                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
   8257             // We need to resolve all RTL properties as they all depend on layout direction
   8258             resolveRtlPropertiesIfNeeded();
   8259             requestLayout();
   8260             invalidate(true);
   8261         }
   8262     }
   8263 
   8264     /**
   8265      * Returns the resolved layout direction for this view.
   8266      *
   8267      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
   8268      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
   8269      *
   8270      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
   8271      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
   8272      *
   8273      * @attr ref android.R.styleable#View_layoutDirection
   8274      */
   8275     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   8276         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
   8277         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
   8278     })
   8279     @ResolvedLayoutDir
   8280     public int getLayoutDirection() {
   8281         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   8282         if (targetSdkVersion < JELLY_BEAN_MR1) {
   8283             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   8284             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
   8285         }
   8286         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
   8287                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
   8288     }
   8289 
   8290     /**
   8291      * Indicates whether or not this view's layout is right-to-left. This is resolved from
   8292      * layout attribute and/or the inherited value from the parent
   8293      *
   8294      * @return true if the layout is right-to-left.
   8295      *
   8296      * @hide
   8297      */
   8298     @ViewDebug.ExportedProperty(category = "layout")
   8299     public boolean isLayoutRtl() {
   8300         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
   8301     }
   8302 
   8303     /**
   8304      * Indicates whether the view is currently tracking transient state that the
   8305      * app should not need to concern itself with saving and restoring, but that
   8306      * the framework should take special note to preserve when possible.
   8307      *
   8308      * <p>A view with transient state cannot be trivially rebound from an external
   8309      * data source, such as an adapter binding item views in a list. This may be
   8310      * because the view is performing an animation, tracking user selection
   8311      * of content, or similar.</p>
   8312      *
   8313      * @return true if the view has transient state
   8314      */
   8315     @ViewDebug.ExportedProperty(category = "layout")
   8316     public boolean hasTransientState() {
   8317         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
   8318     }
   8319 
   8320     /**
   8321      * Set whether this view is currently tracking transient state that the
   8322      * framework should attempt to preserve when possible. This flag is reference counted,
   8323      * so every call to setHasTransientState(true) should be paired with a later call
   8324      * to setHasTransientState(false).
   8325      *
   8326      * <p>A view with transient state cannot be trivially rebound from an external
   8327      * data source, such as an adapter binding item views in a list. This may be
   8328      * because the view is performing an animation, tracking user selection
   8329      * of content, or similar.</p>
   8330      *
   8331      * @param hasTransientState true if this view has transient state
   8332      */
   8333     public void setHasTransientState(boolean hasTransientState) {
   8334         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
   8335                 mTransientStateCount - 1;
   8336         if (mTransientStateCount < 0) {
   8337             mTransientStateCount = 0;
   8338             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
   8339                     "unmatched pair of setHasTransientState calls");
   8340         } else if ((hasTransientState && mTransientStateCount == 1) ||
   8341                 (!hasTransientState && mTransientStateCount == 0)) {
   8342             // update flag if we've just incremented up from 0 or decremented down to 0
   8343             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
   8344                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
   8345             if (mParent != null) {
   8346                 try {
   8347                     mParent.childHasTransientStateChanged(this, hasTransientState);
   8348                 } catch (AbstractMethodError e) {
   8349                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   8350                             " does not fully implement ViewParent", e);
   8351                 }
   8352             }
   8353         }
   8354     }
   8355 
   8356     /**
   8357      * Returns true if this view is currently attached to a window.
   8358      */
   8359     public boolean isAttachedToWindow() {
   8360         return mAttachInfo != null;
   8361     }
   8362 
   8363     /**
   8364      * Returns true if this view has been through at least one layout since it
   8365      * was last attached to or detached from a window.
   8366      */
   8367     public boolean isLaidOut() {
   8368         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
   8369     }
   8370 
   8371     /**
   8372      * If this view doesn't do any drawing on its own, set this flag to
   8373      * allow further optimizations. By default, this flag is not set on
   8374      * View, but could be set on some View subclasses such as ViewGroup.
   8375      *
   8376      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
   8377      * you should clear this flag.
   8378      *
   8379      * @param willNotDraw whether or not this View draw on its own
   8380      */
   8381     public void setWillNotDraw(boolean willNotDraw) {
   8382         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
   8383     }
   8384 
   8385     /**
   8386      * Returns whether or not this View draws on its own.
   8387      *
   8388      * @return true if this view has nothing to draw, false otherwise
   8389      */
   8390     @ViewDebug.ExportedProperty(category = "drawing")
   8391     public boolean willNotDraw() {
   8392         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
   8393     }
   8394 
   8395     /**
   8396      * When a View's drawing cache is enabled, drawing is redirected to an
   8397      * offscreen bitmap. Some views, like an ImageView, must be able to
   8398      * bypass this mechanism if they already draw a single bitmap, to avoid
   8399      * unnecessary usage of the memory.
   8400      *
   8401      * @param willNotCacheDrawing true if this view does not cache its
   8402      *        drawing, false otherwise
   8403      */
   8404     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
   8405         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
   8406     }
   8407 
   8408     /**
   8409      * Returns whether or not this View can cache its drawing or not.
   8410      *
   8411      * @return true if this view does not cache its drawing, false otherwise
   8412      */
   8413     @ViewDebug.ExportedProperty(category = "drawing")
   8414     public boolean willNotCacheDrawing() {
   8415         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
   8416     }
   8417 
   8418     /**
   8419      * Indicates whether this view reacts to click events or not.
   8420      *
   8421      * @return true if the view is clickable, false otherwise
   8422      *
   8423      * @see #setClickable(boolean)
   8424      * @attr ref android.R.styleable#View_clickable
   8425      */
   8426     @ViewDebug.ExportedProperty
   8427     public boolean isClickable() {
   8428         return (mViewFlags & CLICKABLE) == CLICKABLE;
   8429     }
   8430 
   8431     /**
   8432      * Enables or disables click events for this view. When a view
   8433      * is clickable it will change its state to "pressed" on every click.
   8434      * Subclasses should set the view clickable to visually react to
   8435      * user's clicks.
   8436      *
   8437      * @param clickable true to make the view clickable, false otherwise
   8438      *
   8439      * @see #isClickable()
   8440      * @attr ref android.R.styleable#View_clickable
   8441      */
   8442     public void setClickable(boolean clickable) {
   8443         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
   8444     }
   8445 
   8446     /**
   8447      * Indicates whether this view reacts to long click events or not.
   8448      *
   8449      * @return true if the view is long clickable, false otherwise
   8450      *
   8451      * @see #setLongClickable(boolean)
   8452      * @attr ref android.R.styleable#View_longClickable
   8453      */
   8454     public boolean isLongClickable() {
   8455         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   8456     }
   8457 
   8458     /**
   8459      * Enables or disables long click events for this view. When a view is long
   8460      * clickable it reacts to the user holding down the button for a longer
   8461      * duration than a tap. This event can either launch the listener or a
   8462      * context menu.
   8463      *
   8464      * @param longClickable true to make the view long clickable, false otherwise
   8465      * @see #isLongClickable()
   8466      * @attr ref android.R.styleable#View_longClickable
   8467      */
   8468     public void setLongClickable(boolean longClickable) {
   8469         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
   8470     }
   8471 
   8472     /**
   8473      * Indicates whether this view reacts to context clicks or not.
   8474      *
   8475      * @return true if the view is context clickable, false otherwise
   8476      * @see #setContextClickable(boolean)
   8477      * @attr ref android.R.styleable#View_contextClickable
   8478      */
   8479     public boolean isContextClickable() {
   8480         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   8481     }
   8482 
   8483     /**
   8484      * Enables or disables context clicking for this view. This event can launch the listener.
   8485      *
   8486      * @param contextClickable true to make the view react to a context click, false otherwise
   8487      * @see #isContextClickable()
   8488      * @attr ref android.R.styleable#View_contextClickable
   8489      */
   8490     public void setContextClickable(boolean contextClickable) {
   8491         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
   8492     }
   8493 
   8494     /**
   8495      * Sets the pressed state for this view and provides a touch coordinate for
   8496      * animation hinting.
   8497      *
   8498      * @param pressed Pass true to set the View's internal state to "pressed",
   8499      *            or false to reverts the View's internal state from a
   8500      *            previously set "pressed" state.
   8501      * @param x The x coordinate of the touch that caused the press
   8502      * @param y The y coordinate of the touch that caused the press
   8503      */
   8504     private void setPressed(boolean pressed, float x, float y) {
   8505         if (pressed) {
   8506             drawableHotspotChanged(x, y);
   8507         }
   8508 
   8509         setPressed(pressed);
   8510     }
   8511 
   8512     /**
   8513      * Sets the pressed state for this view.
   8514      *
   8515      * @see #isClickable()
   8516      * @see #setClickable(boolean)
   8517      *
   8518      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
   8519      *        the View's internal state from a previously set "pressed" state.
   8520      */
   8521     public void setPressed(boolean pressed) {
   8522         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
   8523 
   8524         if (pressed) {
   8525             mPrivateFlags |= PFLAG_PRESSED;
   8526         } else {
   8527             mPrivateFlags &= ~PFLAG_PRESSED;
   8528         }
   8529 
   8530         if (needsRefresh) {
   8531             refreshDrawableState();
   8532         }
   8533         dispatchSetPressed(pressed);
   8534     }
   8535 
   8536     /**
   8537      * Dispatch setPressed to all of this View's children.
   8538      *
   8539      * @see #setPressed(boolean)
   8540      *
   8541      * @param pressed The new pressed state
   8542      */
   8543     protected void dispatchSetPressed(boolean pressed) {
   8544     }
   8545 
   8546     /**
   8547      * Indicates whether the view is currently in pressed state. Unless
   8548      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
   8549      * the pressed state.
   8550      *
   8551      * @see #setPressed(boolean)
   8552      * @see #isClickable()
   8553      * @see #setClickable(boolean)
   8554      *
   8555      * @return true if the view is currently pressed, false otherwise
   8556      */
   8557     @ViewDebug.ExportedProperty
   8558     public boolean isPressed() {
   8559         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
   8560     }
   8561 
   8562     /**
   8563      * @hide
   8564      * Indicates whether this view will participate in data collection through
   8565      * {@link ViewStructure}.  If true, it will not provide any data
   8566      * for itself or its children.  If false, the normal data collection will be allowed.
   8567      *
   8568      * @return Returns false if assist data collection is not blocked, else true.
   8569      *
   8570      * @see #setAssistBlocked(boolean)
   8571      * @attr ref android.R.styleable#View_assistBlocked
   8572      */
   8573     public boolean isAssistBlocked() {
   8574         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
   8575     }
   8576 
   8577     /**
   8578      * @hide
   8579      * Controls whether assist data collection from this view and its children is enabled
   8580      * (that is, whether {@link #onProvideStructure} and
   8581      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
   8582      * allowing normal assist collection.  Setting this to false will disable assist collection.
   8583      *
   8584      * @param enabled Set to true to <em>disable</em> assist data collection, or false
   8585      * (the default) to allow it.
   8586      *
   8587      * @see #isAssistBlocked()
   8588      * @see #onProvideStructure
   8589      * @see #onProvideVirtualStructure
   8590      * @attr ref android.R.styleable#View_assistBlocked
   8591      */
   8592     public void setAssistBlocked(boolean enabled) {
   8593         if (enabled) {
   8594             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
   8595         } else {
   8596             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
   8597         }
   8598     }
   8599 
   8600     /**
   8601      * Indicates whether this view will save its state (that is,
   8602      * whether its {@link #onSaveInstanceState} method will be called).
   8603      *
   8604      * @return Returns true if the view state saving is enabled, else false.
   8605      *
   8606      * @see #setSaveEnabled(boolean)
   8607      * @attr ref android.R.styleable#View_saveEnabled
   8608      */
   8609     public boolean isSaveEnabled() {
   8610         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
   8611     }
   8612 
   8613     /**
   8614      * Controls whether the saving of this view's state is
   8615      * enabled (that is, whether its {@link #onSaveInstanceState} method
   8616      * will be called).  Note that even if freezing is enabled, the
   8617      * view still must have an id assigned to it (via {@link #setId(int)})
   8618      * for its state to be saved.  This flag can only disable the
   8619      * saving of this view; any child views may still have their state saved.
   8620      *
   8621      * @param enabled Set to false to <em>disable</em> state saving, or true
   8622      * (the default) to allow it.
   8623      *
   8624      * @see #isSaveEnabled()
   8625      * @see #setId(int)
   8626      * @see #onSaveInstanceState()
   8627      * @attr ref android.R.styleable#View_saveEnabled
   8628      */
   8629     public void setSaveEnabled(boolean enabled) {
   8630         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
   8631     }
   8632 
   8633     /**
   8634      * Gets whether the framework should discard touches when the view's
   8635      * window is obscured by another visible window.
   8636      * Refer to the {@link View} security documentation for more details.
   8637      *
   8638      * @return True if touch filtering is enabled.
   8639      *
   8640      * @see #setFilterTouchesWhenObscured(boolean)
   8641      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   8642      */
   8643     @ViewDebug.ExportedProperty
   8644     public boolean getFilterTouchesWhenObscured() {
   8645         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
   8646     }
   8647 
   8648     /**
   8649      * Sets whether the framework should discard touches when the view's
   8650      * window is obscured by another visible window.
   8651      * Refer to the {@link View} security documentation for more details.
   8652      *
   8653      * @param enabled True if touch filtering should be enabled.
   8654      *
   8655      * @see #getFilterTouchesWhenObscured
   8656      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   8657      */
   8658     public void setFilterTouchesWhenObscured(boolean enabled) {
   8659         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
   8660                 FILTER_TOUCHES_WHEN_OBSCURED);
   8661     }
   8662 
   8663     /**
   8664      * Indicates whether the entire hierarchy under this view will save its
   8665      * state when a state saving traversal occurs from its parent.  The default
   8666      * is true; if false, these views will not be saved unless
   8667      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   8668      *
   8669      * @return Returns true if the view state saving from parent is enabled, else false.
   8670      *
   8671      * @see #setSaveFromParentEnabled(boolean)
   8672      */
   8673     public boolean isSaveFromParentEnabled() {
   8674         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
   8675     }
   8676 
   8677     /**
   8678      * Controls whether the entire hierarchy under this view will save its
   8679      * state when a state saving traversal occurs from its parent.  The default
   8680      * is true; if false, these views will not be saved unless
   8681      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   8682      *
   8683      * @param enabled Set to false to <em>disable</em> state saving, or true
   8684      * (the default) to allow it.
   8685      *
   8686      * @see #isSaveFromParentEnabled()
   8687      * @see #setId(int)
   8688      * @see #onSaveInstanceState()
   8689      */
   8690     public void setSaveFromParentEnabled(boolean enabled) {
   8691         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
   8692     }
   8693 
   8694 
   8695     /**
   8696      * Returns whether this View is able to take focus.
   8697      *
   8698      * @return True if this view can take focus, or false otherwise.
   8699      * @attr ref android.R.styleable#View_focusable
   8700      */
   8701     @ViewDebug.ExportedProperty(category = "focus")
   8702     public final boolean isFocusable() {
   8703         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
   8704     }
   8705 
   8706     /**
   8707      * When a view is focusable, it may not want to take focus when in touch mode.
   8708      * For example, a button would like focus when the user is navigating via a D-pad
   8709      * so that the user can click on it, but once the user starts touching the screen,
   8710      * the button shouldn't take focus
   8711      * @return Whether the view is focusable in touch mode.
   8712      * @attr ref android.R.styleable#View_focusableInTouchMode
   8713      */
   8714     @ViewDebug.ExportedProperty
   8715     public final boolean isFocusableInTouchMode() {
   8716         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
   8717     }
   8718 
   8719     /**
   8720      * Find the nearest view in the specified direction that can take focus.
   8721      * This does not actually give focus to that view.
   8722      *
   8723      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   8724      *
   8725      * @return The nearest focusable in the specified direction, or null if none
   8726      *         can be found.
   8727      */
   8728     public View focusSearch(@FocusRealDirection int direction) {
   8729         if (mParent != null) {
   8730             return mParent.focusSearch(this, direction);
   8731         } else {
   8732             return null;
   8733         }
   8734     }
   8735 
   8736     /**
   8737      * This method is the last chance for the focused view and its ancestors to
   8738      * respond to an arrow key. This is called when the focused view did not
   8739      * consume the key internally, nor could the view system find a new view in
   8740      * the requested direction to give focus to.
   8741      *
   8742      * @param focused The currently focused view.
   8743      * @param direction The direction focus wants to move. One of FOCUS_UP,
   8744      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
   8745      * @return True if the this view consumed this unhandled move.
   8746      */
   8747     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
   8748         return false;
   8749     }
   8750 
   8751     /**
   8752      * If a user manually specified the next view id for a particular direction,
   8753      * use the root to look up the view.
   8754      * @param root The root view of the hierarchy containing this view.
   8755      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
   8756      * or FOCUS_BACKWARD.
   8757      * @return The user specified next view, or null if there is none.
   8758      */
   8759     View findUserSetNextFocus(View root, @FocusDirection int direction) {
   8760         switch (direction) {
   8761             case FOCUS_LEFT:
   8762                 if (mNextFocusLeftId == View.NO_ID) return null;
   8763                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
   8764             case FOCUS_RIGHT:
   8765                 if (mNextFocusRightId == View.NO_ID) return null;
   8766                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
   8767             case FOCUS_UP:
   8768                 if (mNextFocusUpId == View.NO_ID) return null;
   8769                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
   8770             case FOCUS_DOWN:
   8771                 if (mNextFocusDownId == View.NO_ID) return null;
   8772                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
   8773             case FOCUS_FORWARD:
   8774                 if (mNextFocusForwardId == View.NO_ID) return null;
   8775                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
   8776             case FOCUS_BACKWARD: {
   8777                 if (mID == View.NO_ID) return null;
   8778                 final int id = mID;
   8779                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
   8780                     @Override
   8781                     public boolean apply(View t) {
   8782                         return t.mNextFocusForwardId == id;
   8783                     }
   8784                 });
   8785             }
   8786         }
   8787         return null;
   8788     }
   8789 
   8790     private View findViewInsideOutShouldExist(View root, int id) {
   8791         if (mMatchIdPredicate == null) {
   8792             mMatchIdPredicate = new MatchIdPredicate();
   8793         }
   8794         mMatchIdPredicate.mId = id;
   8795         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
   8796         if (result == null) {
   8797             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
   8798         }
   8799         return result;
   8800     }
   8801 
   8802     /**
   8803      * Find and return all focusable views that are descendants of this view,
   8804      * possibly including this view if it is focusable itself.
   8805      *
   8806      * @param direction The direction of the focus
   8807      * @return A list of focusable views
   8808      */
   8809     public ArrayList<View> getFocusables(@FocusDirection int direction) {
   8810         ArrayList<View> result = new ArrayList<View>(24);
   8811         addFocusables(result, direction);
   8812         return result;
   8813     }
   8814 
   8815     /**
   8816      * Add any focusable views that are descendants of this view (possibly
   8817      * including this view if it is focusable itself) to views.  If we are in touch mode,
   8818      * only add views that are also focusable in touch mode.
   8819      *
   8820      * @param views Focusable views found so far
   8821      * @param direction The direction of the focus
   8822      */
   8823     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
   8824         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
   8825     }
   8826 
   8827     /**
   8828      * Adds any focusable views that are descendants of this view (possibly
   8829      * including this view if it is focusable itself) to views. This method
   8830      * adds all focusable views regardless if we are in touch mode or
   8831      * only views focusable in touch mode if we are in touch mode or
   8832      * only views that can take accessibility focus if accessibility is enabled
   8833      * depending on the focusable mode parameter.
   8834      *
   8835      * @param views Focusable views found so far or null if all we are interested is
   8836      *        the number of focusables.
   8837      * @param direction The direction of the focus.
   8838      * @param focusableMode The type of focusables to be added.
   8839      *
   8840      * @see #FOCUSABLES_ALL
   8841      * @see #FOCUSABLES_TOUCH_MODE
   8842      */
   8843     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
   8844             @FocusableMode int focusableMode) {
   8845         if (views == null) {
   8846             return;
   8847         }
   8848         if (!isFocusable()) {
   8849             return;
   8850         }
   8851         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
   8852                 && !isFocusableInTouchMode()) {
   8853             return;
   8854         }
   8855         views.add(this);
   8856     }
   8857 
   8858     /**
   8859      * Finds the Views that contain given text. The containment is case insensitive.
   8860      * The search is performed by either the text that the View renders or the content
   8861      * description that describes the view for accessibility purposes and the view does
   8862      * not render or both. Clients can specify how the search is to be performed via
   8863      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
   8864      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
   8865      *
   8866      * @param outViews The output list of matching Views.
   8867      * @param searched The text to match against.
   8868      *
   8869      * @see #FIND_VIEWS_WITH_TEXT
   8870      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
   8871      * @see #setContentDescription(CharSequence)
   8872      */
   8873     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
   8874             @FindViewFlags int flags) {
   8875         if (getAccessibilityNodeProvider() != null) {
   8876             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
   8877                 outViews.add(this);
   8878             }
   8879         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
   8880                 && (searched != null && searched.length() > 0)
   8881                 && (mContentDescription != null && mContentDescription.length() > 0)) {
   8882             String searchedLowerCase = searched.toString().toLowerCase();
   8883             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
   8884             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
   8885                 outViews.add(this);
   8886             }
   8887         }
   8888     }
   8889 
   8890     /**
   8891      * Find and return all touchable views that are descendants of this view,
   8892      * possibly including this view if it is touchable itself.
   8893      *
   8894      * @return A list of touchable views
   8895      */
   8896     public ArrayList<View> getTouchables() {
   8897         ArrayList<View> result = new ArrayList<View>();
   8898         addTouchables(result);
   8899         return result;
   8900     }
   8901 
   8902     /**
   8903      * Add any touchable views that are descendants of this view (possibly
   8904      * including this view if it is touchable itself) to views.
   8905      *
   8906      * @param views Touchable views found so far
   8907      */
   8908     public void addTouchables(ArrayList<View> views) {
   8909         final int viewFlags = mViewFlags;
   8910 
   8911         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   8912                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
   8913                 && (viewFlags & ENABLED_MASK) == ENABLED) {
   8914             views.add(this);
   8915         }
   8916     }
   8917 
   8918     /**
   8919      * Returns whether this View is accessibility focused.
   8920      *
   8921      * @return True if this View is accessibility focused.
   8922      */
   8923     public boolean isAccessibilityFocused() {
   8924         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
   8925     }
   8926 
   8927     /**
   8928      * Call this to try to give accessibility focus to this view.
   8929      *
   8930      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
   8931      * returns false or the view is no visible or the view already has accessibility
   8932      * focus.
   8933      *
   8934      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8935      * have focus, and you want your parent to look for the next one.
   8936      *
   8937      * @return Whether this view actually took accessibility focus.
   8938      *
   8939      * @hide
   8940      */
   8941     public boolean requestAccessibilityFocus() {
   8942         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
   8943         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
   8944             return false;
   8945         }
   8946         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   8947             return false;
   8948         }
   8949         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
   8950             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
   8951             ViewRootImpl viewRootImpl = getViewRootImpl();
   8952             if (viewRootImpl != null) {
   8953                 viewRootImpl.setAccessibilityFocus(this, null);
   8954             }
   8955             invalidate();
   8956             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
   8957             return true;
   8958         }
   8959         return false;
   8960     }
   8961 
   8962     /**
   8963      * Call this to try to clear accessibility focus of this view.
   8964      *
   8965      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8966      * have focus, and you want your parent to look for the next one.
   8967      *
   8968      * @hide
   8969      */
   8970     public void clearAccessibilityFocus() {
   8971         clearAccessibilityFocusNoCallbacks(0);
   8972 
   8973         // Clear the global reference of accessibility focus if this view or
   8974         // any of its descendants had accessibility focus. This will NOT send
   8975         // an event or update internal state if focus is cleared from a
   8976         // descendant view, which may leave views in inconsistent states.
   8977         final ViewRootImpl viewRootImpl = getViewRootImpl();
   8978         if (viewRootImpl != null) {
   8979             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
   8980             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   8981                 viewRootImpl.setAccessibilityFocus(null, null);
   8982             }
   8983         }
   8984     }
   8985 
   8986     private void sendAccessibilityHoverEvent(int eventType) {
   8987         // Since we are not delivering to a client accessibility events from not
   8988         // important views (unless the clinet request that) we need to fire the
   8989         // event from the deepest view exposed to the client. As a consequence if
   8990         // the user crosses a not exposed view the client will see enter and exit
   8991         // of the exposed predecessor followed by and enter and exit of that same
   8992         // predecessor when entering and exiting the not exposed descendant. This
   8993         // is fine since the client has a clear idea which view is hovered at the
   8994         // price of a couple more events being sent. This is a simple and
   8995         // working solution.
   8996         View source = this;
   8997         while (true) {
   8998             if (source.includeForAccessibility()) {
   8999                 source.sendAccessibilityEvent(eventType);
   9000                 return;
   9001             }
   9002             ViewParent parent = source.getParent();
   9003             if (parent instanceof View) {
   9004                 source = (View) parent;
   9005             } else {
   9006                 return;
   9007             }
   9008         }
   9009     }
   9010 
   9011     /**
   9012      * Clears accessibility focus without calling any callback methods
   9013      * normally invoked in {@link #clearAccessibilityFocus()}. This method
   9014      * is used separately from that one for clearing accessibility focus when
   9015      * giving this focus to another view.
   9016      *
   9017      * @param action The action, if any, that led to focus being cleared. Set to
   9018      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
   9019      * the window.
   9020      */
   9021     void clearAccessibilityFocusNoCallbacks(int action) {
   9022         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
   9023             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
   9024             invalidate();
   9025             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   9026                 AccessibilityEvent event = AccessibilityEvent.obtain(
   9027                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
   9028                 event.setAction(action);
   9029                 if (mAccessibilityDelegate != null) {
   9030                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   9031                 } else {
   9032                     sendAccessibilityEventUnchecked(event);
   9033                 }
   9034             }
   9035         }
   9036     }
   9037 
   9038     /**
   9039      * Call this to try to give focus to a specific view or to one of its
   9040      * descendants.
   9041      *
   9042      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   9043      * false), or if it is focusable and it is not focusable in touch mode
   9044      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   9045      *
   9046      * See also {@link #focusSearch(int)}, which is what you call to say that you
   9047      * have focus, and you want your parent to look for the next one.
   9048      *
   9049      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
   9050      * {@link #FOCUS_DOWN} and <code>null</code>.
   9051      *
   9052      * @return Whether this view or one of its descendants actually took focus.
   9053      */
   9054     public final boolean requestFocus() {
   9055         return requestFocus(View.FOCUS_DOWN);
   9056     }
   9057 
   9058     /**
   9059      * Call this to try to give focus to a specific view or to one of its
   9060      * descendants and give it a hint about what direction focus is heading.
   9061      *
   9062      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   9063      * false), or if it is focusable and it is not focusable in touch mode
   9064      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   9065      *
   9066      * See also {@link #focusSearch(int)}, which is what you call to say that you
   9067      * have focus, and you want your parent to look for the next one.
   9068      *
   9069      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
   9070      * <code>null</code> set for the previously focused rectangle.
   9071      *
   9072      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   9073      * @return Whether this view or one of its descendants actually took focus.
   9074      */
   9075     public final boolean requestFocus(int direction) {
   9076         return requestFocus(direction, null);
   9077     }
   9078 
   9079     /**
   9080      * Call this to try to give focus to a specific view or to one of its descendants
   9081      * and give it hints about the direction and a specific rectangle that the focus
   9082      * is coming from.  The rectangle can help give larger views a finer grained hint
   9083      * about where focus is coming from, and therefore, where to show selection, or
   9084      * forward focus change internally.
   9085      *
   9086      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   9087      * false), or if it is focusable and it is not focusable in touch mode
   9088      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   9089      *
   9090      * A View will not take focus if it is not visible.
   9091      *
   9092      * A View will not take focus if one of its parents has
   9093      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
   9094      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
   9095      *
   9096      * See also {@link #focusSearch(int)}, which is what you call to say that you
   9097      * have focus, and you want your parent to look for the next one.
   9098      *
   9099      * You may wish to override this method if your custom {@link View} has an internal
   9100      * {@link View} that it wishes to forward the request to.
   9101      *
   9102      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   9103      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
   9104      *        to give a finer grained hint about where focus is coming from.  May be null
   9105      *        if there is no hint.
   9106      * @return Whether this view or one of its descendants actually took focus.
   9107      */
   9108     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
   9109         return requestFocusNoSearch(direction, previouslyFocusedRect);
   9110     }
   9111 
   9112     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
   9113         // need to be focusable
   9114         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
   9115                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   9116             return false;
   9117         }
   9118 
   9119         // need to be focusable in touch mode if in touch mode
   9120         if (isInTouchMode() &&
   9121             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
   9122                return false;
   9123         }
   9124 
   9125         // need to not have any parents blocking us
   9126         if (hasAncestorThatBlocksDescendantFocus()) {
   9127             return false;
   9128         }
   9129 
   9130         handleFocusGainInternal(direction, previouslyFocusedRect);
   9131         return true;
   9132     }
   9133 
   9134     /**
   9135      * Call this to try to give focus to a specific view or to one of its descendants. This is a
   9136      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
   9137      * touch mode to request focus when they are touched.
   9138      *
   9139      * @return Whether this view or one of its descendants actually took focus.
   9140      *
   9141      * @see #isInTouchMode()
   9142      *
   9143      */
   9144     public final boolean requestFocusFromTouch() {
   9145         // Leave touch mode if we need to
   9146         if (isInTouchMode()) {
   9147             ViewRootImpl viewRoot = getViewRootImpl();
   9148             if (viewRoot != null) {
   9149                 viewRoot.ensureTouchMode(false);
   9150             }
   9151         }
   9152         return requestFocus(View.FOCUS_DOWN);
   9153     }
   9154 
   9155     /**
   9156      * @return Whether any ancestor of this view blocks descendant focus.
   9157      */
   9158     private boolean hasAncestorThatBlocksDescendantFocus() {
   9159         final boolean focusableInTouchMode = isFocusableInTouchMode();
   9160         ViewParent ancestor = mParent;
   9161         while (ancestor instanceof ViewGroup) {
   9162             final ViewGroup vgAncestor = (ViewGroup) ancestor;
   9163             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
   9164                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
   9165                 return true;
   9166             } else {
   9167                 ancestor = vgAncestor.getParent();
   9168             }
   9169         }
   9170         return false;
   9171     }
   9172 
   9173     /**
   9174      * Gets the mode for determining whether this View is important for accessibility
   9175      * which is if it fires accessibility events and if it is reported to
   9176      * accessibility services that query the screen.
   9177      *
   9178      * @return The mode for determining whether a View is important for accessibility.
   9179      *
   9180      * @attr ref android.R.styleable#View_importantForAccessibility
   9181      *
   9182      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   9183      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   9184      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   9185      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   9186      */
   9187     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
   9188             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
   9189             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
   9190             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
   9191             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
   9192                     to = "noHideDescendants")
   9193         })
   9194     public int getImportantForAccessibility() {
   9195         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   9196                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   9197     }
   9198 
   9199     /**
   9200      * Sets the live region mode for this view. This indicates to accessibility
   9201      * services whether they should automatically notify the user about changes
   9202      * to the view's content description or text, or to the content descriptions
   9203      * or text of the view's children (where applicable).
   9204      * <p>
   9205      * For example, in a login screen with a TextView that displays an "incorrect
   9206      * password" notification, that view should be marked as a live region with
   9207      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   9208      * <p>
   9209      * To disable change notifications for this view, use
   9210      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
   9211      * mode for most views.
   9212      * <p>
   9213      * To indicate that the user should be notified of changes, use
   9214      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   9215      * <p>
   9216      * If the view's changes should interrupt ongoing speech and notify the user
   9217      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
   9218      *
   9219      * @param mode The live region mode for this view, one of:
   9220      *        <ul>
   9221      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
   9222      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
   9223      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
   9224      *        </ul>
   9225      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   9226      */
   9227     public void setAccessibilityLiveRegion(int mode) {
   9228         if (mode != getAccessibilityLiveRegion()) {
   9229             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   9230             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
   9231                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   9232             notifyViewAccessibilityStateChangedIfNeeded(
   9233                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9234         }
   9235     }
   9236 
   9237     /**
   9238      * Gets the live region mode for this View.
   9239      *
   9240      * @return The live region mode for the view.
   9241      *
   9242      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   9243      *
   9244      * @see #setAccessibilityLiveRegion(int)
   9245      */
   9246     public int getAccessibilityLiveRegion() {
   9247         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
   9248                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   9249     }
   9250 
   9251     /**
   9252      * Sets how to determine whether this view is important for accessibility
   9253      * which is if it fires accessibility events and if it is reported to
   9254      * accessibility services that query the screen.
   9255      *
   9256      * @param mode How to determine whether this view is important for accessibility.
   9257      *
   9258      * @attr ref android.R.styleable#View_importantForAccessibility
   9259      *
   9260      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   9261      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   9262      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   9263      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   9264      */
   9265     public void setImportantForAccessibility(int mode) {
   9266         final int oldMode = getImportantForAccessibility();
   9267         if (mode != oldMode) {
   9268             final boolean hideDescendants =
   9269                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
   9270 
   9271             // If this node or its descendants are no longer important, try to
   9272             // clear accessibility focus.
   9273             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
   9274                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
   9275                 if (focusHost != null) {
   9276                     focusHost.clearAccessibilityFocus();
   9277                 }
   9278             }
   9279 
   9280             // If we're moving between AUTO and another state, we might not need
   9281             // to send a subtree changed notification. We'll store the computed
   9282             // importance, since we'll need to check it later to make sure.
   9283             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
   9284                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   9285             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
   9286             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   9287             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
   9288                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   9289             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
   9290                 notifySubtreeAccessibilityStateChangedIfNeeded();
   9291             } else {
   9292                 notifyViewAccessibilityStateChangedIfNeeded(
   9293                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9294             }
   9295         }
   9296     }
   9297 
   9298     /**
   9299      * Returns the view within this view's hierarchy that is hosting
   9300      * accessibility focus.
   9301      *
   9302      * @param searchDescendants whether to search for focus in descendant views
   9303      * @return the view hosting accessibility focus, or {@code null}
   9304      */
   9305     private View findAccessibilityFocusHost(boolean searchDescendants) {
   9306         if (isAccessibilityFocusedViewOrHost()) {
   9307             return this;
   9308         }
   9309 
   9310         if (searchDescendants) {
   9311             final ViewRootImpl viewRoot = getViewRootImpl();
   9312             if (viewRoot != null) {
   9313                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
   9314                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   9315                     return focusHost;
   9316                 }
   9317             }
   9318         }
   9319 
   9320         return null;
   9321     }
   9322 
   9323     /**
   9324      * Computes whether this view should be exposed for accessibility. In
   9325      * general, views that are interactive or provide information are exposed
   9326      * while views that serve only as containers are hidden.
   9327      * <p>
   9328      * If an ancestor of this view has importance
   9329      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
   9330      * returns <code>false</code>.
   9331      * <p>
   9332      * Otherwise, the value is computed according to the view's
   9333      * {@link #getImportantForAccessibility()} value:
   9334      * <ol>
   9335      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
   9336      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
   9337      * </code>
   9338      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
   9339      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
   9340      * view satisfies any of the following:
   9341      * <ul>
   9342      * <li>Is actionable, e.g. {@link #isClickable()},
   9343      * {@link #isLongClickable()}, or {@link #isFocusable()}
   9344      * <li>Has an {@link AccessibilityDelegate}
   9345      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
   9346      * {@link OnKeyListener}, etc.
   9347      * <li>Is an accessibility live region, e.g.
   9348      * {@link #getAccessibilityLiveRegion()} is not
   9349      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
   9350      * </ul>
   9351      * </ol>
   9352      *
   9353      * @return Whether the view is exposed for accessibility.
   9354      * @see #setImportantForAccessibility(int)
   9355      * @see #getImportantForAccessibility()
   9356      */
   9357     public boolean isImportantForAccessibility() {
   9358         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   9359                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   9360         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
   9361                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   9362             return false;
   9363         }
   9364 
   9365         // Check parent mode to ensure we're not hidden.
   9366         ViewParent parent = mParent;
   9367         while (parent instanceof View) {
   9368             if (((View) parent).getImportantForAccessibility()
   9369                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   9370                 return false;
   9371             }
   9372             parent = parent.getParent();
   9373         }
   9374 
   9375         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
   9376                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
   9377                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
   9378     }
   9379 
   9380     /**
   9381      * Gets the parent for accessibility purposes. Note that the parent for
   9382      * accessibility is not necessary the immediate parent. It is the first
   9383      * predecessor that is important for accessibility.
   9384      *
   9385      * @return The parent for accessibility purposes.
   9386      */
   9387     public ViewParent getParentForAccessibility() {
   9388         if (mParent instanceof View) {
   9389             View parentView = (View) mParent;
   9390             if (parentView.includeForAccessibility()) {
   9391                 return mParent;
   9392             } else {
   9393                 return mParent.getParentForAccessibility();
   9394             }
   9395         }
   9396         return null;
   9397     }
   9398 
   9399     /**
   9400      * Adds the children of this View relevant for accessibility to the given list
   9401      * as output. Since some Views are not important for accessibility the added
   9402      * child views are not necessarily direct children of this view, rather they are
   9403      * the first level of descendants important for accessibility.
   9404      *
   9405      * @param outChildren The output list that will receive children for accessibility.
   9406      */
   9407     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
   9408 
   9409     }
   9410 
   9411     /**
   9412      * Whether to regard this view for accessibility. A view is regarded for
   9413      * accessibility if it is important for accessibility or the querying
   9414      * accessibility service has explicitly requested that view not
   9415      * important for accessibility are regarded.
   9416      *
   9417      * @return Whether to regard the view for accessibility.
   9418      *
   9419      * @hide
   9420      */
   9421     public boolean includeForAccessibility() {
   9422         if (mAttachInfo != null) {
   9423             return (mAttachInfo.mAccessibilityFetchFlags
   9424                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
   9425                     || isImportantForAccessibility();
   9426         }
   9427         return false;
   9428     }
   9429 
   9430     /**
   9431      * Returns whether the View is considered actionable from
   9432      * accessibility perspective. Such view are important for
   9433      * accessibility.
   9434      *
   9435      * @return True if the view is actionable for accessibility.
   9436      *
   9437      * @hide
   9438      */
   9439     public boolean isActionableForAccessibility() {
   9440         return (isClickable() || isLongClickable() || isFocusable());
   9441     }
   9442 
   9443     /**
   9444      * Returns whether the View has registered callbacks which makes it
   9445      * important for accessibility.
   9446      *
   9447      * @return True if the view is actionable for accessibility.
   9448      */
   9449     private boolean hasListenersForAccessibility() {
   9450         ListenerInfo info = getListenerInfo();
   9451         return mTouchDelegate != null || info.mOnKeyListener != null
   9452                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
   9453                 || info.mOnHoverListener != null || info.mOnDragListener != null;
   9454     }
   9455 
   9456     /**
   9457      * Notifies that the accessibility state of this view changed. The change
   9458      * is local to this view and does not represent structural changes such
   9459      * as children and parent. For example, the view became focusable. The
   9460      * notification is at at most once every
   9461      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   9462      * to avoid unnecessary load to the system. Also once a view has a pending
   9463      * notification this method is a NOP until the notification has been sent.
   9464      *
   9465      * @hide
   9466      */
   9467     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
   9468         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   9469             return;
   9470         }
   9471         if (mSendViewStateChangedAccessibilityEvent == null) {
   9472             mSendViewStateChangedAccessibilityEvent =
   9473                     new SendViewStateChangedAccessibilityEvent();
   9474         }
   9475         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
   9476     }
   9477 
   9478     /**
   9479      * Notifies that the accessibility state of this view changed. The change
   9480      * is *not* local to this view and does represent structural changes such
   9481      * as children and parent. For example, the view size changed. The
   9482      * notification is at at most once every
   9483      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   9484      * to avoid unnecessary load to the system. Also once a view has a pending
   9485      * notification this method is a NOP until the notification has been sent.
   9486      *
   9487      * @hide
   9488      */
   9489     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
   9490         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   9491             return;
   9492         }
   9493         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
   9494             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   9495             if (mParent != null) {
   9496                 try {
   9497                     mParent.notifySubtreeAccessibilityStateChanged(
   9498                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
   9499                 } catch (AbstractMethodError e) {
   9500                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   9501                             " does not fully implement ViewParent", e);
   9502                 }
   9503             }
   9504         }
   9505     }
   9506 
   9507     /**
   9508      * Change the visibility of the View without triggering any other changes. This is
   9509      * important for transitions, where visibility changes should not adjust focus or
   9510      * trigger a new layout. This is only used when the visibility has already been changed
   9511      * and we need a transient value during an animation. When the animation completes,
   9512      * the original visibility value is always restored.
   9513      *
   9514      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   9515      * @hide
   9516      */
   9517     public void setTransitionVisibility(@Visibility int visibility) {
   9518         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
   9519     }
   9520 
   9521     /**
   9522      * Reset the flag indicating the accessibility state of the subtree rooted
   9523      * at this view changed.
   9524      */
   9525     void resetSubtreeAccessibilityStateChanged() {
   9526         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   9527     }
   9528 
   9529     /**
   9530      * Report an accessibility action to this view's parents for delegated processing.
   9531      *
   9532      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
   9533      * call this method to delegate an accessibility action to a supporting parent. If the parent
   9534      * returns true from its
   9535      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
   9536      * method this method will return true to signify that the action was consumed.</p>
   9537      *
   9538      * <p>This method is useful for implementing nested scrolling child views. If
   9539      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
   9540      * a custom view implementation may invoke this method to allow a parent to consume the
   9541      * scroll first. If this method returns true the custom view should skip its own scrolling
   9542      * behavior.</p>
   9543      *
   9544      * @param action Accessibility action to delegate
   9545      * @param arguments Optional action arguments
   9546      * @return true if the action was consumed by a parent
   9547      */
   9548     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
   9549         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
   9550             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
   9551                 return true;
   9552             }
   9553         }
   9554         return false;
   9555     }
   9556 
   9557     /**
   9558      * Performs the specified accessibility action on the view. For
   9559      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   9560      * <p>
   9561      * If an {@link AccessibilityDelegate} has been specified via calling
   9562      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   9563      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
   9564      * is responsible for handling this call.
   9565      * </p>
   9566      *
   9567      * <p>The default implementation will delegate
   9568      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
   9569      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
   9570      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
   9571      *
   9572      * @param action The action to perform.
   9573      * @param arguments Optional action arguments.
   9574      * @return Whether the action was performed.
   9575      */
   9576     public boolean performAccessibilityAction(int action, Bundle arguments) {
   9577       if (mAccessibilityDelegate != null) {
   9578           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
   9579       } else {
   9580           return performAccessibilityActionInternal(action, arguments);
   9581       }
   9582     }
   9583 
   9584    /**
   9585     * @see #performAccessibilityAction(int, Bundle)
   9586     *
   9587     * Note: Called from the default {@link AccessibilityDelegate}.
   9588     *
   9589     * @hide
   9590     */
   9591     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
   9592         if (isNestedScrollingEnabled()
   9593                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
   9594                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
   9595                 || action == R.id.accessibilityActionScrollUp
   9596                 || action == R.id.accessibilityActionScrollLeft
   9597                 || action == R.id.accessibilityActionScrollDown
   9598                 || action == R.id.accessibilityActionScrollRight)) {
   9599             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
   9600                 return true;
   9601             }
   9602         }
   9603 
   9604         switch (action) {
   9605             case AccessibilityNodeInfo.ACTION_CLICK: {
   9606                 if (isClickable()) {
   9607                     performClick();
   9608                     return true;
   9609                 }
   9610             } break;
   9611             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
   9612                 if (isLongClickable()) {
   9613                     performLongClick();
   9614                     return true;
   9615                 }
   9616             } break;
   9617             case AccessibilityNodeInfo.ACTION_FOCUS: {
   9618                 if (!hasFocus()) {
   9619                     // Get out of touch mode since accessibility
   9620                     // wants to move focus around.
   9621                     getViewRootImpl().ensureTouchMode(false);
   9622                     return requestFocus();
   9623                 }
   9624             } break;
   9625             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
   9626                 if (hasFocus()) {
   9627                     clearFocus();
   9628                     return !isFocused();
   9629                 }
   9630             } break;
   9631             case AccessibilityNodeInfo.ACTION_SELECT: {
   9632                 if (!isSelected()) {
   9633                     setSelected(true);
   9634                     return isSelected();
   9635                 }
   9636             } break;
   9637             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
   9638                 if (isSelected()) {
   9639                     setSelected(false);
   9640                     return !isSelected();
   9641                 }
   9642             } break;
   9643             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
   9644                 if (!isAccessibilityFocused()) {
   9645                     return requestAccessibilityFocus();
   9646                 }
   9647             } break;
   9648             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
   9649                 if (isAccessibilityFocused()) {
   9650                     clearAccessibilityFocus();
   9651                     return true;
   9652                 }
   9653             } break;
   9654             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
   9655                 if (arguments != null) {
   9656                     final int granularity = arguments.getInt(
   9657                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   9658                     final boolean extendSelection = arguments.getBoolean(
   9659                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   9660                     return traverseAtGranularity(granularity, true, extendSelection);
   9661                 }
   9662             } break;
   9663             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
   9664                 if (arguments != null) {
   9665                     final int granularity = arguments.getInt(
   9666                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   9667                     final boolean extendSelection = arguments.getBoolean(
   9668                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   9669                     return traverseAtGranularity(granularity, false, extendSelection);
   9670                 }
   9671             } break;
   9672             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
   9673                 CharSequence text = getIterableTextForAccessibility();
   9674                 if (text == null) {
   9675                     return false;
   9676                 }
   9677                 final int start = (arguments != null) ? arguments.getInt(
   9678                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
   9679                 final int end = (arguments != null) ? arguments.getInt(
   9680                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
   9681                 // Only cursor position can be specified (selection length == 0)
   9682                 if ((getAccessibilitySelectionStart() != start
   9683                         || getAccessibilitySelectionEnd() != end)
   9684                         && (start == end)) {
   9685                     setAccessibilitySelection(start, end);
   9686                     notifyViewAccessibilityStateChangedIfNeeded(
   9687                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9688                     return true;
   9689                 }
   9690             } break;
   9691             case R.id.accessibilityActionShowOnScreen: {
   9692                 if (mAttachInfo != null) {
   9693                     final Rect r = mAttachInfo.mTmpInvalRect;
   9694                     getDrawingRect(r);
   9695                     return requestRectangleOnScreen(r, true);
   9696                 }
   9697             } break;
   9698             case R.id.accessibilityActionContextClick: {
   9699                 if (isContextClickable()) {
   9700                     performContextClick();
   9701                     return true;
   9702                 }
   9703             } break;
   9704         }
   9705         return false;
   9706     }
   9707 
   9708     private boolean traverseAtGranularity(int granularity, boolean forward,
   9709             boolean extendSelection) {
   9710         CharSequence text = getIterableTextForAccessibility();
   9711         if (text == null || text.length() == 0) {
   9712             return false;
   9713         }
   9714         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
   9715         if (iterator == null) {
   9716             return false;
   9717         }
   9718         int current = getAccessibilitySelectionEnd();
   9719         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   9720             current = forward ? 0 : text.length();
   9721         }
   9722         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
   9723         if (range == null) {
   9724             return false;
   9725         }
   9726         final int segmentStart = range[0];
   9727         final int segmentEnd = range[1];
   9728         int selectionStart;
   9729         int selectionEnd;
   9730         if (extendSelection && isAccessibilitySelectionExtendable()) {
   9731             selectionStart = getAccessibilitySelectionStart();
   9732             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   9733                 selectionStart = forward ? segmentStart : segmentEnd;
   9734             }
   9735             selectionEnd = forward ? segmentEnd : segmentStart;
   9736         } else {
   9737             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
   9738         }
   9739         setAccessibilitySelection(selectionStart, selectionEnd);
   9740         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
   9741                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
   9742         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
   9743         return true;
   9744     }
   9745 
   9746     /**
   9747      * Gets the text reported for accessibility purposes.
   9748      *
   9749      * @return The accessibility text.
   9750      *
   9751      * @hide
   9752      */
   9753     public CharSequence getIterableTextForAccessibility() {
   9754         return getContentDescription();
   9755     }
   9756 
   9757     /**
   9758      * Gets whether accessibility selection can be extended.
   9759      *
   9760      * @return If selection is extensible.
   9761      *
   9762      * @hide
   9763      */
   9764     public boolean isAccessibilitySelectionExtendable() {
   9765         return false;
   9766     }
   9767 
   9768     /**
   9769      * @hide
   9770      */
   9771     public int getAccessibilitySelectionStart() {
   9772         return mAccessibilityCursorPosition;
   9773     }
   9774 
   9775     /**
   9776      * @hide
   9777      */
   9778     public int getAccessibilitySelectionEnd() {
   9779         return getAccessibilitySelectionStart();
   9780     }
   9781 
   9782     /**
   9783      * @hide
   9784      */
   9785     public void setAccessibilitySelection(int start, int end) {
   9786         if (start ==  end && end == mAccessibilityCursorPosition) {
   9787             return;
   9788         }
   9789         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
   9790             mAccessibilityCursorPosition = start;
   9791         } else {
   9792             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   9793         }
   9794         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
   9795     }
   9796 
   9797     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
   9798             int fromIndex, int toIndex) {
   9799         if (mParent == null) {
   9800             return;
   9801         }
   9802         AccessibilityEvent event = AccessibilityEvent.obtain(
   9803                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
   9804         onInitializeAccessibilityEvent(event);
   9805         onPopulateAccessibilityEvent(event);
   9806         event.setFromIndex(fromIndex);
   9807         event.setToIndex(toIndex);
   9808         event.setAction(action);
   9809         event.setMovementGranularity(granularity);
   9810         mParent.requestSendAccessibilityEvent(this, event);
   9811     }
   9812 
   9813     /**
   9814      * @hide
   9815      */
   9816     public TextSegmentIterator getIteratorForGranularity(int granularity) {
   9817         switch (granularity) {
   9818             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
   9819                 CharSequence text = getIterableTextForAccessibility();
   9820                 if (text != null && text.length() > 0) {
   9821                     CharacterTextSegmentIterator iterator =
   9822                         CharacterTextSegmentIterator.getInstance(
   9823                                 mContext.getResources().getConfiguration().locale);
   9824                     iterator.initialize(text.toString());
   9825                     return iterator;
   9826                 }
   9827             } break;
   9828             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
   9829                 CharSequence text = getIterableTextForAccessibility();
   9830                 if (text != null && text.length() > 0) {
   9831                     WordTextSegmentIterator iterator =
   9832                         WordTextSegmentIterator.getInstance(
   9833                                 mContext.getResources().getConfiguration().locale);
   9834                     iterator.initialize(text.toString());
   9835                     return iterator;
   9836                 }
   9837             } break;
   9838             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
   9839                 CharSequence text = getIterableTextForAccessibility();
   9840                 if (text != null && text.length() > 0) {
   9841                     ParagraphTextSegmentIterator iterator =
   9842                         ParagraphTextSegmentIterator.getInstance();
   9843                     iterator.initialize(text.toString());
   9844                     return iterator;
   9845                 }
   9846             } break;
   9847         }
   9848         return null;
   9849     }
   9850 
   9851     /**
   9852      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
   9853      * and {@link #onFinishTemporaryDetach()}.
   9854      *
   9855      * <p>This method always returns {@code true} when called directly or indirectly from
   9856      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
   9857      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
   9858      * <ul>
   9859      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
   9860      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
   9861      * </ul>
   9862      * </p>
   9863      *
   9864      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
   9865      * and {@link #onFinishTemporaryDetach()}.
   9866      */
   9867     public final boolean isTemporarilyDetached() {
   9868         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
   9869     }
   9870 
   9871     /**
   9872      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
   9873      * a container View.
   9874      */
   9875     @CallSuper
   9876     public void dispatchStartTemporaryDetach() {
   9877         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
   9878         onStartTemporaryDetach();
   9879     }
   9880 
   9881     /**
   9882      * This is called when a container is going to temporarily detach a child, with
   9883      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
   9884      * It will either be followed by {@link #onFinishTemporaryDetach()} or
   9885      * {@link #onDetachedFromWindow()} when the container is done.
   9886      */
   9887     public void onStartTemporaryDetach() {
   9888         removeUnsetPressCallback();
   9889         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   9890     }
   9891 
   9892     /**
   9893      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
   9894      * a container View.
   9895      */
   9896     @CallSuper
   9897     public void dispatchFinishTemporaryDetach() {
   9898         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
   9899         onFinishTemporaryDetach();
   9900         if (hasWindowFocus() && hasFocus()) {
   9901             InputMethodManager.getInstance().focusIn(this);
   9902         }
   9903     }
   9904 
   9905     /**
   9906      * Called after {@link #onStartTemporaryDetach} when the container is done
   9907      * changing the view.
   9908      */
   9909     public void onFinishTemporaryDetach() {
   9910     }
   9911 
   9912     /**
   9913      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
   9914      * for this view's window.  Returns null if the view is not currently attached
   9915      * to the window.  Normally you will not need to use this directly, but
   9916      * just use the standard high-level event callbacks like
   9917      * {@link #onKeyDown(int, KeyEvent)}.
   9918      */
   9919     public KeyEvent.DispatcherState getKeyDispatcherState() {
   9920         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
   9921     }
   9922 
   9923     /**
   9924      * Dispatch a key event before it is processed by any input method
   9925      * associated with the view hierarchy.  This can be used to intercept
   9926      * key events in special situations before the IME consumes them; a
   9927      * typical example would be handling the BACK key to update the application's
   9928      * UI instead of allowing the IME to see it and close itself.
   9929      *
   9930      * @param event The key event to be dispatched.
   9931      * @return True if the event was handled, false otherwise.
   9932      */
   9933     public boolean dispatchKeyEventPreIme(KeyEvent event) {
   9934         return onKeyPreIme(event.getKeyCode(), event);
   9935     }
   9936 
   9937     /**
   9938      * Dispatch a key event to the next view on the focus path. This path runs
   9939      * from the top of the view tree down to the currently focused view. If this
   9940      * view has focus, it will dispatch to itself. Otherwise it will dispatch
   9941      * the next node down the focus path. This method also fires any key
   9942      * listeners.
   9943      *
   9944      * @param event The key event to be dispatched.
   9945      * @return True if the event was handled, false otherwise.
   9946      */
   9947     public boolean dispatchKeyEvent(KeyEvent event) {
   9948         if (mInputEventConsistencyVerifier != null) {
   9949             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
   9950         }
   9951 
   9952         // Give any attached key listener a first crack at the event.
   9953         //noinspection SimplifiableIfStatement
   9954         ListenerInfo li = mListenerInfo;
   9955         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   9956                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
   9957             return true;
   9958         }
   9959 
   9960         if (event.dispatch(this, mAttachInfo != null
   9961                 ? mAttachInfo.mKeyDispatchState : null, this)) {
   9962             return true;
   9963         }
   9964 
   9965         if (mInputEventConsistencyVerifier != null) {
   9966             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   9967         }
   9968         return false;
   9969     }
   9970 
   9971     /**
   9972      * Dispatches a key shortcut event.
   9973      *
   9974      * @param event The key event to be dispatched.
   9975      * @return True if the event was handled by the view, false otherwise.
   9976      */
   9977     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   9978         return onKeyShortcut(event.getKeyCode(), event);
   9979     }
   9980 
   9981     /**
   9982      * Pass the touch screen motion event down to the target view, or this
   9983      * view if it is the target.
   9984      *
   9985      * @param event The motion event to be dispatched.
   9986      * @return True if the event was handled by the view, false otherwise.
   9987      */
   9988     public boolean dispatchTouchEvent(MotionEvent event) {
   9989         // If the event should be handled by accessibility focus first.
   9990         if (event.isTargetAccessibilityFocus()) {
   9991             // We don't have focus or no virtual descendant has it, do not handle the event.
   9992             if (!isAccessibilityFocusedViewOrHost()) {
   9993                 return false;
   9994             }
   9995             // We have focus and got the event, then use normal event dispatch.
   9996             event.setTargetAccessibilityFocus(false);
   9997         }
   9998 
   9999         boolean result = false;
   10000 
   10001         if (mInputEventConsistencyVerifier != null) {
   10002             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
   10003         }
   10004 
   10005         final int actionMasked = event.getActionMasked();
   10006         if (actionMasked == MotionEvent.ACTION_DOWN) {
   10007             // Defensive cleanup for new gesture
   10008             stopNestedScroll();
   10009         }
   10010 
   10011         if (onFilterTouchEventForSecurity(event)) {
   10012             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
   10013                 result = true;
   10014             }
   10015             //noinspection SimplifiableIfStatement
   10016             ListenerInfo li = mListenerInfo;
   10017             if (li != null && li.mOnTouchListener != null
   10018                     && (mViewFlags & ENABLED_MASK) == ENABLED
   10019                     && li.mOnTouchListener.onTouch(this, event)) {
   10020                 result = true;
   10021             }
   10022 
   10023             if (!result && onTouchEvent(event)) {
   10024                 result = true;
   10025             }
   10026         }
   10027 
   10028         if (!result && mInputEventConsistencyVerifier != null) {
   10029             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   10030         }
   10031 
   10032         // Clean up after nested scrolls if this is the end of a gesture;
   10033         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
   10034         // of the gesture.
   10035         if (actionMasked == MotionEvent.ACTION_UP ||
   10036                 actionMasked == MotionEvent.ACTION_CANCEL ||
   10037                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
   10038             stopNestedScroll();
   10039         }
   10040 
   10041         return result;
   10042     }
   10043 
   10044     boolean isAccessibilityFocusedViewOrHost() {
   10045         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
   10046                 .getAccessibilityFocusedHost() == this);
   10047     }
   10048 
   10049     /**
   10050      * Filter the touch event to apply security policies.
   10051      *
   10052      * @param event The motion event to be filtered.
   10053      * @return True if the event should be dispatched, false if the event should be dropped.
   10054      *
   10055      * @see #getFilterTouchesWhenObscured
   10056      */
   10057     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
   10058         //noinspection RedundantIfStatement
   10059         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
   10060                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
   10061             // Window is obscured, drop this touch.
   10062             return false;
   10063         }
   10064         return true;
   10065     }
   10066 
   10067     /**
   10068      * Pass a trackball motion event down to the focused view.
   10069      *
   10070      * @param event The motion event to be dispatched.
   10071      * @return True if the event was handled by the view, false otherwise.
   10072      */
   10073     public boolean dispatchTrackballEvent(MotionEvent event) {
   10074         if (mInputEventConsistencyVerifier != null) {
   10075             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
   10076         }
   10077 
   10078         return onTrackballEvent(event);
   10079     }
   10080 
   10081     /**
   10082      * Dispatch a generic motion event.
   10083      * <p>
   10084      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   10085      * are delivered to the view under the pointer.  All other generic motion events are
   10086      * delivered to the focused view.  Hover events are handled specially and are delivered
   10087      * to {@link #onHoverEvent(MotionEvent)}.
   10088      * </p>
   10089      *
   10090      * @param event The motion event to be dispatched.
   10091      * @return True if the event was handled by the view, false otherwise.
   10092      */
   10093     public boolean dispatchGenericMotionEvent(MotionEvent event) {
   10094         if (mInputEventConsistencyVerifier != null) {
   10095             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
   10096         }
   10097 
   10098         final int source = event.getSource();
   10099         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   10100             final int action = event.getAction();
   10101             if (action == MotionEvent.ACTION_HOVER_ENTER
   10102                     || action == MotionEvent.ACTION_HOVER_MOVE
   10103                     || action == MotionEvent.ACTION_HOVER_EXIT) {
   10104                 if (dispatchHoverEvent(event)) {
   10105                     return true;
   10106                 }
   10107             } else if (dispatchGenericPointerEvent(event)) {
   10108                 return true;
   10109             }
   10110         } else if (dispatchGenericFocusedEvent(event)) {
   10111             return true;
   10112         }
   10113 
   10114         if (dispatchGenericMotionEventInternal(event)) {
   10115             return true;
   10116         }
   10117 
   10118         if (mInputEventConsistencyVerifier != null) {
   10119             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   10120         }
   10121         return false;
   10122     }
   10123 
   10124     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
   10125         //noinspection SimplifiableIfStatement
   10126         ListenerInfo li = mListenerInfo;
   10127         if (li != null && li.mOnGenericMotionListener != null
   10128                 && (mViewFlags & ENABLED_MASK) == ENABLED
   10129                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
   10130             return true;
   10131         }
   10132 
   10133         if (onGenericMotionEvent(event)) {
   10134             return true;
   10135         }
   10136 
   10137         final int actionButton = event.getActionButton();
   10138         switch (event.getActionMasked()) {
   10139             case MotionEvent.ACTION_BUTTON_PRESS:
   10140                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
   10141                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   10142                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   10143                     if (performContextClick(event.getX(), event.getY())) {
   10144                         mInContextButtonPress = true;
   10145                         setPressed(true, event.getX(), event.getY());
   10146                         removeTapCallback();
   10147                         removeLongPressCallback();
   10148                         return true;
   10149                     }
   10150                 }
   10151                 break;
   10152 
   10153             case MotionEvent.ACTION_BUTTON_RELEASE:
   10154                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   10155                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   10156                     mInContextButtonPress = false;
   10157                     mIgnoreNextUpEvent = true;
   10158                 }
   10159                 break;
   10160         }
   10161 
   10162         if (mInputEventConsistencyVerifier != null) {
   10163             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   10164         }
   10165         return false;
   10166     }
   10167 
   10168     /**
   10169      * Dispatch a hover event.
   10170      * <p>
   10171      * Do not call this method directly.
   10172      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   10173      * </p>
   10174      *
   10175      * @param event The motion event to be dispatched.
   10176      * @return True if the event was handled by the view, false otherwise.
   10177      */
   10178     protected boolean dispatchHoverEvent(MotionEvent event) {
   10179         ListenerInfo li = mListenerInfo;
   10180         //noinspection SimplifiableIfStatement
   10181         if (li != null && li.mOnHoverListener != null
   10182                 && (mViewFlags & ENABLED_MASK) == ENABLED
   10183                 && li.mOnHoverListener.onHover(this, event)) {
   10184             return true;
   10185         }
   10186 
   10187         return onHoverEvent(event);
   10188     }
   10189 
   10190     /**
   10191      * Returns true if the view has a child to which it has recently sent
   10192      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
   10193      * it does not have a hovered child, then it must be the innermost hovered view.
   10194      * @hide
   10195      */
   10196     protected boolean hasHoveredChild() {
   10197         return false;
   10198     }
   10199 
   10200     /**
   10201      * Dispatch a generic motion event to the view under the first pointer.
   10202      * <p>
   10203      * Do not call this method directly.
   10204      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   10205      * </p>
   10206      *
   10207      * @param event The motion event to be dispatched.
   10208      * @return True if the event was handled by the view, false otherwise.
   10209      */
   10210     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
   10211         return false;
   10212     }
   10213 
   10214     /**
   10215      * Dispatch a generic motion event to the currently focused view.
   10216      * <p>
   10217      * Do not call this method directly.
   10218      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   10219      * </p>
   10220      *
   10221      * @param event The motion event to be dispatched.
   10222      * @return True if the event was handled by the view, false otherwise.
   10223      */
   10224     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
   10225         return false;
   10226     }
   10227 
   10228     /**
   10229      * Dispatch a pointer event.
   10230      * <p>
   10231      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
   10232      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
   10233      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
   10234      * and should not be expected to handle other pointing device features.
   10235      * </p>
   10236      *
   10237      * @param event The motion event to be dispatched.
   10238      * @return True if the event was handled by the view, false otherwise.
   10239      * @hide
   10240      */
   10241     public final boolean dispatchPointerEvent(MotionEvent event) {
   10242         if (event.isTouchEvent()) {
   10243             return dispatchTouchEvent(event);
   10244         } else {
   10245             return dispatchGenericMotionEvent(event);
   10246         }
   10247     }
   10248 
   10249     /**
   10250      * Called when the window containing this view gains or loses window focus.
   10251      * ViewGroups should override to route to their children.
   10252      *
   10253      * @param hasFocus True if the window containing this view now has focus,
   10254      *        false otherwise.
   10255      */
   10256     public void dispatchWindowFocusChanged(boolean hasFocus) {
   10257         onWindowFocusChanged(hasFocus);
   10258     }
   10259 
   10260     /**
   10261      * Called when the window containing this view gains or loses focus.  Note
   10262      * that this is separate from view focus: to receive key events, both
   10263      * your view and its window must have focus.  If a window is displayed
   10264      * on top of yours that takes input focus, then your own window will lose
   10265      * focus but the view focus will remain unchanged.
   10266      *
   10267      * @param hasWindowFocus True if the window containing this view now has
   10268      *        focus, false otherwise.
   10269      */
   10270     public void onWindowFocusChanged(boolean hasWindowFocus) {
   10271         InputMethodManager imm = InputMethodManager.peekInstance();
   10272         if (!hasWindowFocus) {
   10273             if (isPressed()) {
   10274                 setPressed(false);
   10275             }
   10276             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
   10277                 imm.focusOut(this);
   10278             }
   10279             removeLongPressCallback();
   10280             removeTapCallback();
   10281             onFocusLost();
   10282         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
   10283             imm.focusIn(this);
   10284         }
   10285         refreshDrawableState();
   10286     }
   10287 
   10288     /**
   10289      * Returns true if this view is in a window that currently has window focus.
   10290      * Note that this is not the same as the view itself having focus.
   10291      *
   10292      * @return True if this view is in a window that currently has window focus.
   10293      */
   10294     public boolean hasWindowFocus() {
   10295         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
   10296     }
   10297 
   10298     /**
   10299      * Dispatch a view visibility change down the view hierarchy.
   10300      * ViewGroups should override to route to their children.
   10301      * @param changedView The view whose visibility changed. Could be 'this' or
   10302      * an ancestor view.
   10303      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   10304      * {@link #INVISIBLE} or {@link #GONE}.
   10305      */
   10306     protected void dispatchVisibilityChanged(@NonNull View changedView,
   10307             @Visibility int visibility) {
   10308         onVisibilityChanged(changedView, visibility);
   10309     }
   10310 
   10311     /**
   10312      * Called when the visibility of the view or an ancestor of the view has
   10313      * changed.
   10314      *
   10315      * @param changedView The view whose visibility changed. May be
   10316      *                    {@code this} or an ancestor view.
   10317      * @param visibility The new visibility, one of {@link #VISIBLE},
   10318      *                   {@link #INVISIBLE} or {@link #GONE}.
   10319      */
   10320     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
   10321     }
   10322 
   10323     /**
   10324      * Dispatch a hint about whether this view is displayed. For instance, when
   10325      * a View moves out of the screen, it might receives a display hint indicating
   10326      * the view is not displayed. Applications should not <em>rely</em> on this hint
   10327      * as there is no guarantee that they will receive one.
   10328      *
   10329      * @param hint A hint about whether or not this view is displayed:
   10330      * {@link #VISIBLE} or {@link #INVISIBLE}.
   10331      */
   10332     public void dispatchDisplayHint(@Visibility int hint) {
   10333         onDisplayHint(hint);
   10334     }
   10335 
   10336     /**
   10337      * Gives this view a hint about whether is displayed or not. For instance, when
   10338      * a View moves out of the screen, it might receives a display hint indicating
   10339      * the view is not displayed. Applications should not <em>rely</em> on this hint
   10340      * as there is no guarantee that they will receive one.
   10341      *
   10342      * @param hint A hint about whether or not this view is displayed:
   10343      * {@link #VISIBLE} or {@link #INVISIBLE}.
   10344      */
   10345     protected void onDisplayHint(@Visibility int hint) {
   10346     }
   10347 
   10348     /**
   10349      * Dispatch a window visibility change down the view hierarchy.
   10350      * ViewGroups should override to route to their children.
   10351      *
   10352      * @param visibility The new visibility of the window.
   10353      *
   10354      * @see #onWindowVisibilityChanged(int)
   10355      */
   10356     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
   10357         onWindowVisibilityChanged(visibility);
   10358     }
   10359 
   10360     /**
   10361      * Called when the window containing has change its visibility
   10362      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
   10363      * that this tells you whether or not your window is being made visible
   10364      * to the window manager; this does <em>not</em> tell you whether or not
   10365      * your window is obscured by other windows on the screen, even if it
   10366      * is itself visible.
   10367      *
   10368      * @param visibility The new visibility of the window.
   10369      */
   10370     protected void onWindowVisibilityChanged(@Visibility int visibility) {
   10371         if (visibility == VISIBLE) {
   10372             initialAwakenScrollBars();
   10373         }
   10374     }
   10375 
   10376     /**
   10377      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
   10378      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
   10379      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
   10380      *
   10381      * @param isVisible true if this view's visibility to the user is uninterrupted by its
   10382      *                  ancestors or by window visibility
   10383      * @return true if this view is visible to the user, not counting clipping or overlapping
   10384      */
   10385     boolean dispatchVisibilityAggregated(boolean isVisible) {
   10386         final boolean thisVisible = getVisibility() == VISIBLE;
   10387         // If we're not visible but something is telling us we are, ignore it.
   10388         if (thisVisible || !isVisible) {
   10389             onVisibilityAggregated(isVisible);
   10390         }
   10391         return thisVisible && isVisible;
   10392     }
   10393 
   10394     /**
   10395      * Called when the user-visibility of this View is potentially affected by a change
   10396      * to this view itself, an ancestor view or the window this view is attached to.
   10397      *
   10398      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
   10399      *                  and this view's window is also visible
   10400      */
   10401     @CallSuper
   10402     public void onVisibilityAggregated(boolean isVisible) {
   10403         if (isVisible && mAttachInfo != null) {
   10404             initialAwakenScrollBars();
   10405         }
   10406 
   10407         final Drawable dr = mBackground;
   10408         if (dr != null && isVisible != dr.isVisible()) {
   10409             dr.setVisible(isVisible, false);
   10410         }
   10411         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   10412         if (fg != null && isVisible != fg.isVisible()) {
   10413             fg.setVisible(isVisible, false);
   10414         }
   10415     }
   10416 
   10417     /**
   10418      * Returns the current visibility of the window this view is attached to
   10419      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
   10420      *
   10421      * @return Returns the current visibility of the view's window.
   10422      */
   10423     @Visibility
   10424     public int getWindowVisibility() {
   10425         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
   10426     }
   10427 
   10428     /**
   10429      * Retrieve the overall visible display size in which the window this view is
   10430      * attached to has been positioned in.  This takes into account screen
   10431      * decorations above the window, for both cases where the window itself
   10432      * is being position inside of them or the window is being placed under
   10433      * then and covered insets are used for the window to position its content
   10434      * inside.  In effect, this tells you the available area where content can
   10435      * be placed and remain visible to users.
   10436      *
   10437      * <p>This function requires an IPC back to the window manager to retrieve
   10438      * the requested information, so should not be used in performance critical
   10439      * code like drawing.
   10440      *
   10441      * @param outRect Filled in with the visible display frame.  If the view
   10442      * is not attached to a window, this is simply the raw display size.
   10443      */
   10444     public void getWindowVisibleDisplayFrame(Rect outRect) {
   10445         if (mAttachInfo != null) {
   10446             try {
   10447                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   10448             } catch (RemoteException e) {
   10449                 return;
   10450             }
   10451             // XXX This is really broken, and probably all needs to be done
   10452             // in the window manager, and we need to know more about whether
   10453             // we want the area behind or in front of the IME.
   10454             final Rect insets = mAttachInfo.mVisibleInsets;
   10455             outRect.left += insets.left;
   10456             outRect.top += insets.top;
   10457             outRect.right -= insets.right;
   10458             outRect.bottom -= insets.bottom;
   10459             return;
   10460         }
   10461         // The view is not attached to a display so we don't have a context.
   10462         // Make a best guess about the display size.
   10463         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   10464         d.getRectSize(outRect);
   10465     }
   10466 
   10467     /**
   10468      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
   10469      * is currently in without any insets.
   10470      *
   10471      * @hide
   10472      */
   10473     public void getWindowDisplayFrame(Rect outRect) {
   10474         if (mAttachInfo != null) {
   10475             try {
   10476                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   10477             } catch (RemoteException e) {
   10478                 return;
   10479             }
   10480             return;
   10481         }
   10482         // The view is not attached to a display so we don't have a context.
   10483         // Make a best guess about the display size.
   10484         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   10485         d.getRectSize(outRect);
   10486     }
   10487 
   10488     /**
   10489      * Dispatch a notification about a resource configuration change down
   10490      * the view hierarchy.
   10491      * ViewGroups should override to route to their children.
   10492      *
   10493      * @param newConfig The new resource configuration.
   10494      *
   10495      * @see #onConfigurationChanged(android.content.res.Configuration)
   10496      */
   10497     public void dispatchConfigurationChanged(Configuration newConfig) {
   10498         onConfigurationChanged(newConfig);
   10499     }
   10500 
   10501     /**
   10502      * Called when the current configuration of the resources being used
   10503      * by the application have changed.  You can use this to decide when
   10504      * to reload resources that can changed based on orientation and other
   10505      * configuration characteristics.  You only need to use this if you are
   10506      * not relying on the normal {@link android.app.Activity} mechanism of
   10507      * recreating the activity instance upon a configuration change.
   10508      *
   10509      * @param newConfig The new resource configuration.
   10510      */
   10511     protected void onConfigurationChanged(Configuration newConfig) {
   10512     }
   10513 
   10514     /**
   10515      * Private function to aggregate all per-view attributes in to the view
   10516      * root.
   10517      */
   10518     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   10519         performCollectViewAttributes(attachInfo, visibility);
   10520     }
   10521 
   10522     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   10523         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
   10524             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
   10525                 attachInfo.mKeepScreenOn = true;
   10526             }
   10527             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
   10528             ListenerInfo li = mListenerInfo;
   10529             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   10530                 attachInfo.mHasSystemUiListeners = true;
   10531             }
   10532         }
   10533     }
   10534 
   10535     void needGlobalAttributesUpdate(boolean force) {
   10536         final AttachInfo ai = mAttachInfo;
   10537         if (ai != null && !ai.mRecomputeGlobalAttributes) {
   10538             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
   10539                     || ai.mHasSystemUiListeners) {
   10540                 ai.mRecomputeGlobalAttributes = true;
   10541             }
   10542         }
   10543     }
   10544 
   10545     /**
   10546      * Returns whether the device is currently in touch mode.  Touch mode is entered
   10547      * once the user begins interacting with the device by touch, and affects various
   10548      * things like whether focus is always visible to the user.
   10549      *
   10550      * @return Whether the device is in touch mode.
   10551      */
   10552     @ViewDebug.ExportedProperty
   10553     public boolean isInTouchMode() {
   10554         if (mAttachInfo != null) {
   10555             return mAttachInfo.mInTouchMode;
   10556         } else {
   10557             return ViewRootImpl.isInTouchMode();
   10558         }
   10559     }
   10560 
   10561     /**
   10562      * Returns the context the view is running in, through which it can
   10563      * access the current theme, resources, etc.
   10564      *
   10565      * @return The view's Context.
   10566      */
   10567     @ViewDebug.CapturedViewProperty
   10568     public final Context getContext() {
   10569         return mContext;
   10570     }
   10571 
   10572     /**
   10573      * Handle a key event before it is processed by any input method
   10574      * associated with the view hierarchy.  This can be used to intercept
   10575      * key events in special situations before the IME consumes them; a
   10576      * typical example would be handling the BACK key to update the application's
   10577      * UI instead of allowing the IME to see it and close itself.
   10578      *
   10579      * @param keyCode The value in event.getKeyCode().
   10580      * @param event Description of the key event.
   10581      * @return If you handled the event, return true. If you want to allow the
   10582      *         event to be handled by the next receiver, return false.
   10583      */
   10584     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
   10585         return false;
   10586     }
   10587 
   10588     /**
   10589      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
   10590      * KeyEvent.Callback.onKeyDown()}: perform press of the view
   10591      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
   10592      * is released, if the view is enabled and clickable.
   10593      * <p>
   10594      * Key presses in software keyboards will generally NOT trigger this
   10595      * listener, although some may elect to do so in some situations. Do not
   10596      * rely on this to catch software key presses.
   10597      *
   10598      * @param keyCode a key code that represents the button pressed, from
   10599      *                {@link android.view.KeyEvent}
   10600      * @param event the KeyEvent object that defines the button action
   10601      */
   10602     public boolean onKeyDown(int keyCode, KeyEvent event) {
   10603         if (KeyEvent.isConfirmKey(keyCode)) {
   10604             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   10605                 return true;
   10606             }
   10607 
   10608             // Long clickable items don't necessarily have to be clickable.
   10609             if (((mViewFlags & CLICKABLE) == CLICKABLE
   10610                     || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   10611                     && (event.getRepeatCount() == 0)) {
   10612                 // For the purposes of menu anchoring and drawable hotspots,
   10613                 // key events are considered to be at the center of the view.
   10614                 final float x = getWidth() / 2f;
   10615                 final float y = getHeight() / 2f;
   10616                 setPressed(true, x, y);
   10617                 checkForLongClick(0, x, y);
   10618                 return true;
   10619             }
   10620         }
   10621 
   10622         return false;
   10623     }
   10624 
   10625     /**
   10626      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
   10627      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
   10628      * the event).
   10629      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   10630      * although some may elect to do so in some situations. Do not rely on this to
   10631      * catch software key presses.
   10632      */
   10633     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
   10634         return false;
   10635     }
   10636 
   10637     /**
   10638      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
   10639      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
   10640      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
   10641      * or {@link KeyEvent#KEYCODE_SPACE} is released.
   10642      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   10643      * although some may elect to do so in some situations. Do not rely on this to
   10644      * catch software key presses.
   10645      *
   10646      * @param keyCode A key code that represents the button pressed, from
   10647      *                {@link android.view.KeyEvent}.
   10648      * @param event   The KeyEvent object that defines the button action.
   10649      */
   10650     public boolean onKeyUp(int keyCode, KeyEvent event) {
   10651         if (KeyEvent.isConfirmKey(keyCode)) {
   10652             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   10653                 return true;
   10654             }
   10655             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
   10656                 setPressed(false);
   10657 
   10658                 if (!mHasPerformedLongPress) {
   10659                     // This is a tap, so remove the longpress check
   10660                     removeLongPressCallback();
   10661                     return performClick();
   10662                 }
   10663             }
   10664         }
   10665         return false;
   10666     }
   10667 
   10668     /**
   10669      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   10670      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
   10671      * the event).
   10672      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   10673      * although some may elect to do so in some situations. Do not rely on this to
   10674      * catch software key presses.
   10675      *
   10676      * @param keyCode     A key code that represents the button pressed, from
   10677      *                    {@link android.view.KeyEvent}.
   10678      * @param repeatCount The number of times the action was made.
   10679      * @param event       The KeyEvent object that defines the button action.
   10680      */
   10681     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
   10682         return false;
   10683     }
   10684 
   10685     /**
   10686      * Called on the focused view when a key shortcut event is not handled.
   10687      * Override this method to implement local key shortcuts for the View.
   10688      * Key shortcuts can also be implemented by setting the
   10689      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
   10690      *
   10691      * @param keyCode The value in event.getKeyCode().
   10692      * @param event Description of the key event.
   10693      * @return If you handled the event, return true. If you want to allow the
   10694      *         event to be handled by the next receiver, return false.
   10695      */
   10696     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
   10697         return false;
   10698     }
   10699 
   10700     /**
   10701      * Check whether the called view is a text editor, in which case it
   10702      * would make sense to automatically display a soft input window for
   10703      * it.  Subclasses should override this if they implement
   10704      * {@link #onCreateInputConnection(EditorInfo)} to return true if
   10705      * a call on that method would return a non-null InputConnection, and
   10706      * they are really a first-class editor that the user would normally
   10707      * start typing on when the go into a window containing your view.
   10708      *
   10709      * <p>The default implementation always returns false.  This does
   10710      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
   10711      * will not be called or the user can not otherwise perform edits on your
   10712      * view; it is just a hint to the system that this is not the primary
   10713      * purpose of this view.
   10714      *
   10715      * @return Returns true if this view is a text editor, else false.
   10716      */
   10717     public boolean onCheckIsTextEditor() {
   10718         return false;
   10719     }
   10720 
   10721     /**
   10722      * Create a new InputConnection for an InputMethod to interact
   10723      * with the view.  The default implementation returns null, since it doesn't
   10724      * support input methods.  You can override this to implement such support.
   10725      * This is only needed for views that take focus and text input.
   10726      *
   10727      * <p>When implementing this, you probably also want to implement
   10728      * {@link #onCheckIsTextEditor()} to indicate you will return a
   10729      * non-null InputConnection.</p>
   10730      *
   10731      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
   10732      * object correctly and in its entirety, so that the connected IME can rely
   10733      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
   10734      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
   10735      * must be filled in with the correct cursor position for IMEs to work correctly
   10736      * with your application.</p>
   10737      *
   10738      * @param outAttrs Fill in with attribute information about the connection.
   10739      */
   10740     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   10741         return null;
   10742     }
   10743 
   10744     /**
   10745      * Called by the {@link android.view.inputmethod.InputMethodManager}
   10746      * when a view who is not the current
   10747      * input connection target is trying to make a call on the manager.  The
   10748      * default implementation returns false; you can override this to return
   10749      * true for certain views if you are performing InputConnection proxying
   10750      * to them.
   10751      * @param view The View that is making the InputMethodManager call.
   10752      * @return Return true to allow the call, false to reject.
   10753      */
   10754     public boolean checkInputConnectionProxy(View view) {
   10755         return false;
   10756     }
   10757 
   10758     /**
   10759      * Show the context menu for this view. It is not safe to hold on to the
   10760      * menu after returning from this method.
   10761      *
   10762      * You should normally not overload this method. Overload
   10763      * {@link #onCreateContextMenu(ContextMenu)} or define an
   10764      * {@link OnCreateContextMenuListener} to add items to the context menu.
   10765      *
   10766      * @param menu The context menu to populate
   10767      */
   10768     public void createContextMenu(ContextMenu menu) {
   10769         ContextMenuInfo menuInfo = getContextMenuInfo();
   10770 
   10771         // Sets the current menu info so all items added to menu will have
   10772         // my extra info set.
   10773         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
   10774 
   10775         onCreateContextMenu(menu);
   10776         ListenerInfo li = mListenerInfo;
   10777         if (li != null && li.mOnCreateContextMenuListener != null) {
   10778             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
   10779         }
   10780 
   10781         // Clear the extra information so subsequent items that aren't mine don't
   10782         // have my extra info.
   10783         ((MenuBuilder)menu).setCurrentMenuInfo(null);
   10784 
   10785         if (mParent != null) {
   10786             mParent.createContextMenu(menu);
   10787         }
   10788     }
   10789 
   10790     /**
   10791      * Views should implement this if they have extra information to associate
   10792      * with the context menu. The return result is supplied as a parameter to
   10793      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
   10794      * callback.
   10795      *
   10796      * @return Extra information about the item for which the context menu
   10797      *         should be shown. This information will vary across different
   10798      *         subclasses of View.
   10799      */
   10800     protected ContextMenuInfo getContextMenuInfo() {
   10801         return null;
   10802     }
   10803 
   10804     /**
   10805      * Views should implement this if the view itself is going to add items to
   10806      * the context menu.
   10807      *
   10808      * @param menu the context menu to populate
   10809      */
   10810     protected void onCreateContextMenu(ContextMenu menu) {
   10811     }
   10812 
   10813     /**
   10814      * Implement this method to handle trackball motion events.  The
   10815      * <em>relative</em> movement of the trackball since the last event
   10816      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
   10817      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
   10818      * that a movement of 1 corresponds to the user pressing one DPAD key (so
   10819      * they will often be fractional values, representing the more fine-grained
   10820      * movement information available from a trackball).
   10821      *
   10822      * @param event The motion event.
   10823      * @return True if the event was handled, false otherwise.
   10824      */
   10825     public boolean onTrackballEvent(MotionEvent event) {
   10826         return false;
   10827     }
   10828 
   10829     /**
   10830      * Implement this method to handle generic motion events.
   10831      * <p>
   10832      * Generic motion events describe joystick movements, mouse hovers, track pad
   10833      * touches, scroll wheel movements and other input events.  The
   10834      * {@link MotionEvent#getSource() source} of the motion event specifies
   10835      * the class of input that was received.  Implementations of this method
   10836      * must examine the bits in the source before processing the event.
   10837      * The following code example shows how this is done.
   10838      * </p><p>
   10839      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   10840      * are delivered to the view under the pointer.  All other generic motion events are
   10841      * delivered to the focused view.
   10842      * </p>
   10843      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
   10844      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
   10845      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
   10846      *             // process the joystick movement...
   10847      *             return true;
   10848      *         }
   10849      *     }
   10850      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
   10851      *         switch (event.getAction()) {
   10852      *             case MotionEvent.ACTION_HOVER_MOVE:
   10853      *                 // process the mouse hover movement...
   10854      *                 return true;
   10855      *             case MotionEvent.ACTION_SCROLL:
   10856      *                 // process the scroll wheel movement...
   10857      *                 return true;
   10858      *         }
   10859      *     }
   10860      *     return super.onGenericMotionEvent(event);
   10861      * }</pre>
   10862      *
   10863      * @param event The generic motion event being processed.
   10864      * @return True if the event was handled, false otherwise.
   10865      */
   10866     public boolean onGenericMotionEvent(MotionEvent event) {
   10867         return false;
   10868     }
   10869 
   10870     /**
   10871      * Implement this method to handle hover events.
   10872      * <p>
   10873      * This method is called whenever a pointer is hovering into, over, or out of the
   10874      * bounds of a view and the view is not currently being touched.
   10875      * Hover events are represented as pointer events with action
   10876      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
   10877      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
   10878      * </p>
   10879      * <ul>
   10880      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
   10881      * when the pointer enters the bounds of the view.</li>
   10882      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
   10883      * when the pointer has already entered the bounds of the view and has moved.</li>
   10884      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
   10885      * when the pointer has exited the bounds of the view or when the pointer is
   10886      * about to go down due to a button click, tap, or similar user action that
   10887      * causes the view to be touched.</li>
   10888      * </ul>
   10889      * <p>
   10890      * The view should implement this method to return true to indicate that it is
   10891      * handling the hover event, such as by changing its drawable state.
   10892      * </p><p>
   10893      * The default implementation calls {@link #setHovered} to update the hovered state
   10894      * of the view when a hover enter or hover exit event is received, if the view
   10895      * is enabled and is clickable.  The default implementation also sends hover
   10896      * accessibility events.
   10897      * </p>
   10898      *
   10899      * @param event The motion event that describes the hover.
   10900      * @return True if the view handled the hover event.
   10901      *
   10902      * @see #isHovered
   10903      * @see #setHovered
   10904      * @see #onHoverChanged
   10905      */
   10906     public boolean onHoverEvent(MotionEvent event) {
   10907         // The root view may receive hover (or touch) events that are outside the bounds of
   10908         // the window.  This code ensures that we only send accessibility events for
   10909         // hovers that are actually within the bounds of the root view.
   10910         final int action = event.getActionMasked();
   10911         if (!mSendingHoverAccessibilityEvents) {
   10912             if ((action == MotionEvent.ACTION_HOVER_ENTER
   10913                     || action == MotionEvent.ACTION_HOVER_MOVE)
   10914                     && !hasHoveredChild()
   10915                     && pointInView(event.getX(), event.getY())) {
   10916                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
   10917                 mSendingHoverAccessibilityEvents = true;
   10918             }
   10919         } else {
   10920             if (action == MotionEvent.ACTION_HOVER_EXIT
   10921                     || (action == MotionEvent.ACTION_MOVE
   10922                             && !pointInView(event.getX(), event.getY()))) {
   10923                 mSendingHoverAccessibilityEvents = false;
   10924                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
   10925             }
   10926         }
   10927 
   10928         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
   10929                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
   10930                 && isOnScrollbar(event.getX(), event.getY())) {
   10931             awakenScrollBars();
   10932         }
   10933         if (isHoverable()) {
   10934             switch (action) {
   10935                 case MotionEvent.ACTION_HOVER_ENTER:
   10936                     setHovered(true);
   10937                     break;
   10938                 case MotionEvent.ACTION_HOVER_EXIT:
   10939                     setHovered(false);
   10940                     break;
   10941             }
   10942 
   10943             // Dispatch the event to onGenericMotionEvent before returning true.
   10944             // This is to provide compatibility with existing applications that
   10945             // handled HOVER_MOVE events in onGenericMotionEvent and that would
   10946             // break because of the new default handling for hoverable views
   10947             // in onHoverEvent.
   10948             // Note that onGenericMotionEvent will be called by default when
   10949             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
   10950             dispatchGenericMotionEventInternal(event);
   10951             // The event was already handled by calling setHovered(), so always
   10952             // return true.
   10953             return true;
   10954         }
   10955 
   10956         return false;
   10957     }
   10958 
   10959     /**
   10960      * Returns true if the view should handle {@link #onHoverEvent}
   10961      * by calling {@link #setHovered} to change its hovered state.
   10962      *
   10963      * @return True if the view is hoverable.
   10964      */
   10965     private boolean isHoverable() {
   10966         final int viewFlags = mViewFlags;
   10967         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   10968             return false;
   10969         }
   10970 
   10971         return (viewFlags & CLICKABLE) == CLICKABLE
   10972                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   10973                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   10974     }
   10975 
   10976     /**
   10977      * Returns true if the view is currently hovered.
   10978      *
   10979      * @return True if the view is currently hovered.
   10980      *
   10981      * @see #setHovered
   10982      * @see #onHoverChanged
   10983      */
   10984     @ViewDebug.ExportedProperty
   10985     public boolean isHovered() {
   10986         return (mPrivateFlags & PFLAG_HOVERED) != 0;
   10987     }
   10988 
   10989     /**
   10990      * Sets whether the view is currently hovered.
   10991      * <p>
   10992      * Calling this method also changes the drawable state of the view.  This
   10993      * enables the view to react to hover by using different drawable resources
   10994      * to change its appearance.
   10995      * </p><p>
   10996      * The {@link #onHoverChanged} method is called when the hovered state changes.
   10997      * </p>
   10998      *
   10999      * @param hovered True if the view is hovered.
   11000      *
   11001      * @see #isHovered
   11002      * @see #onHoverChanged
   11003      */
   11004     public void setHovered(boolean hovered) {
   11005         if (hovered) {
   11006             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
   11007                 mPrivateFlags |= PFLAG_HOVERED;
   11008                 refreshDrawableState();
   11009                 onHoverChanged(true);
   11010             }
   11011         } else {
   11012             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
   11013                 mPrivateFlags &= ~PFLAG_HOVERED;
   11014                 refreshDrawableState();
   11015                 onHoverChanged(false);
   11016             }
   11017         }
   11018     }
   11019 
   11020     /**
   11021      * Implement this method to handle hover state changes.
   11022      * <p>
   11023      * This method is called whenever the hover state changes as a result of a
   11024      * call to {@link #setHovered}.
   11025      * </p>
   11026      *
   11027      * @param hovered The current hover state, as returned by {@link #isHovered}.
   11028      *
   11029      * @see #isHovered
   11030      * @see #setHovered
   11031      */
   11032     public void onHoverChanged(boolean hovered) {
   11033     }
   11034 
   11035     /**
   11036      * Handles scroll bar dragging by mouse input.
   11037      *
   11038      * @hide
   11039      * @param event The motion event.
   11040      *
   11041      * @return true if the event was handled as a scroll bar dragging, false otherwise.
   11042      */
   11043     protected boolean handleScrollBarDragging(MotionEvent event) {
   11044         if (mScrollCache == null) {
   11045             return false;
   11046         }
   11047         final float x = event.getX();
   11048         final float y = event.getY();
   11049         final int action = event.getAction();
   11050         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
   11051                 && action != MotionEvent.ACTION_DOWN)
   11052                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
   11053                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
   11054             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
   11055             return false;
   11056         }
   11057 
   11058         switch (action) {
   11059             case MotionEvent.ACTION_MOVE:
   11060                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
   11061                     return false;
   11062                 }
   11063                 if (mScrollCache.mScrollBarDraggingState
   11064                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
   11065                     final Rect bounds = mScrollCache.mScrollBarBounds;
   11066                     getVerticalScrollBarBounds(bounds);
   11067                     final int range = computeVerticalScrollRange();
   11068                     final int offset = computeVerticalScrollOffset();
   11069                     final int extent = computeVerticalScrollExtent();
   11070 
   11071                     final int thumbLength = ScrollBarUtils.getThumbLength(
   11072                             bounds.height(), bounds.width(), extent, range);
   11073                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
   11074                             bounds.height(), thumbLength, extent, range, offset);
   11075 
   11076                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
   11077                     final float maxThumbOffset = bounds.height() - thumbLength;
   11078                     final float newThumbOffset =
   11079                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
   11080                     final int height = getHeight();
   11081                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
   11082                             && height > 0 && extent > 0) {
   11083                         final int newY = Math.round((range - extent)
   11084                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
   11085                         if (newY != getScrollY()) {
   11086                             mScrollCache.mScrollBarDraggingPos = y;
   11087                             setScrollY(newY);
   11088                         }
   11089                     }
   11090                     return true;
   11091                 }
   11092                 if (mScrollCache.mScrollBarDraggingState
   11093                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
   11094                     final Rect bounds = mScrollCache.mScrollBarBounds;
   11095                     getHorizontalScrollBarBounds(bounds);
   11096                     final int range = computeHorizontalScrollRange();
   11097                     final int offset = computeHorizontalScrollOffset();
   11098                     final int extent = computeHorizontalScrollExtent();
   11099 
   11100                     final int thumbLength = ScrollBarUtils.getThumbLength(
   11101                             bounds.width(), bounds.height(), extent, range);
   11102                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
   11103                             bounds.width(), thumbLength, extent, range, offset);
   11104 
   11105                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
   11106                     final float maxThumbOffset = bounds.width() - thumbLength;
   11107                     final float newThumbOffset =
   11108                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
   11109                     final int width = getWidth();
   11110                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
   11111                             && width > 0 && extent > 0) {
   11112                         final int newX = Math.round((range - extent)
   11113                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
   11114                         if (newX != getScrollX()) {
   11115                             mScrollCache.mScrollBarDraggingPos = x;
   11116                             setScrollX(newX);
   11117                         }
   11118                     }
   11119                     return true;
   11120                 }
   11121             case MotionEvent.ACTION_DOWN:
   11122                 if (mScrollCache.state == ScrollabilityCache.OFF) {
   11123                     return false;
   11124                 }
   11125                 if (isOnVerticalScrollbarThumb(x, y)) {
   11126                     mScrollCache.mScrollBarDraggingState =
   11127                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
   11128                     mScrollCache.mScrollBarDraggingPos = y;
   11129                     return true;
   11130                 }
   11131                 if (isOnHorizontalScrollbarThumb(x, y)) {
   11132                     mScrollCache.mScrollBarDraggingState =
   11133                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
   11134                     mScrollCache.mScrollBarDraggingPos = x;
   11135                     return true;
   11136                 }
   11137         }
   11138         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
   11139         return false;
   11140     }
   11141 
   11142     /**
   11143      * Implement this method to handle touch screen motion events.
   11144      * <p>
   11145      * If this method is used to detect click actions, it is recommended that
   11146      * the actions be performed by implementing and calling
   11147      * {@link #performClick()}. This will ensure consistent system behavior,
   11148      * including:
   11149      * <ul>
   11150      * <li>obeying click sound preferences
   11151      * <li>dispatching OnClickListener calls
   11152      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
   11153      * accessibility features are enabled
   11154      * </ul>
   11155      *
   11156      * @param event The motion event.
   11157      * @return True if the event was handled, false otherwise.
   11158      */
   11159     public boolean onTouchEvent(MotionEvent event) {
   11160         final float x = event.getX();
   11161         final float y = event.getY();
   11162         final int viewFlags = mViewFlags;
   11163         final int action = event.getAction();
   11164 
   11165         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   11166             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
   11167                 setPressed(false);
   11168             }
   11169             // A disabled view that is clickable still consumes the touch
   11170             // events, it just doesn't respond to them.
   11171             return (((viewFlags & CLICKABLE) == CLICKABLE
   11172                     || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   11173                     || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
   11174         }
   11175         if (mTouchDelegate != null) {
   11176             if (mTouchDelegate.onTouchEvent(event)) {
   11177                 return true;
   11178             }
   11179         }
   11180 
   11181         if (((viewFlags & CLICKABLE) == CLICKABLE ||
   11182                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
   11183                 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
   11184             switch (action) {
   11185                 case MotionEvent.ACTION_UP:
   11186                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
   11187                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
   11188                         // take focus if we don't have it already and we should in
   11189                         // touch mode.
   11190                         boolean focusTaken = false;
   11191                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
   11192                             focusTaken = requestFocus();
   11193                         }
   11194 
   11195                         if (prepressed) {
   11196                             // The button is being released before we actually
   11197                             // showed it as pressed.  Make it show the pressed
   11198                             // state now (before scheduling the click) to ensure
   11199                             // the user sees it.
   11200                             setPressed(true, x, y);
   11201                        }
   11202 
   11203                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
   11204                             // This is a tap, so remove the longpress check
   11205                             removeLongPressCallback();
   11206 
   11207                             // Only perform take click actions if we were in the pressed state
   11208                             if (!focusTaken) {
   11209                                 // Use a Runnable and post this rather than calling
   11210                                 // performClick directly. This lets other visual state
   11211                                 // of the view update before click actions start.
   11212                                 if (mPerformClick == null) {
   11213                                     mPerformClick = new PerformClick();
   11214                                 }
   11215                                 if (!post(mPerformClick)) {
   11216                                     performClick();
   11217                                 }
   11218                             }
   11219                         }
   11220 
   11221                         if (mUnsetPressedState == null) {
   11222                             mUnsetPressedState = new UnsetPressedState();
   11223                         }
   11224 
   11225                         if (prepressed) {
   11226                             postDelayed(mUnsetPressedState,
   11227                                     ViewConfiguration.getPressedStateDuration());
   11228                         } else if (!post(mUnsetPressedState)) {
   11229                             // If the post failed, unpress right now
   11230                             mUnsetPressedState.run();
   11231                         }
   11232 
   11233                         removeTapCallback();
   11234                     }
   11235                     mIgnoreNextUpEvent = false;
   11236                     break;
   11237 
   11238                 case MotionEvent.ACTION_DOWN:
   11239                     mHasPerformedLongPress = false;
   11240 
   11241                     if (performButtonActionOnTouchDown(event)) {
   11242                         break;
   11243                     }
   11244 
   11245                     // Walk up the hierarchy to determine if we're inside a scrolling container.
   11246                     boolean isInScrollingContainer = isInScrollingContainer();
   11247 
   11248                     // For views inside a scrolling container, delay the pressed feedback for
   11249                     // a short period in case this is a scroll.
   11250                     if (isInScrollingContainer) {
   11251                         mPrivateFlags |= PFLAG_PREPRESSED;
   11252                         if (mPendingCheckForTap == null) {
   11253                             mPendingCheckForTap = new CheckForTap();
   11254                         }
   11255                         mPendingCheckForTap.x = event.getX();
   11256                         mPendingCheckForTap.y = event.getY();
   11257                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
   11258                     } else {
   11259                         // Not inside a scrolling container, so show the feedback right away
   11260                         setPressed(true, x, y);
   11261                         checkForLongClick(0, x, y);
   11262                     }
   11263                     break;
   11264 
   11265                 case MotionEvent.ACTION_CANCEL:
   11266                     setPressed(false);
   11267                     removeTapCallback();
   11268                     removeLongPressCallback();
   11269                     mInContextButtonPress = false;
   11270                     mHasPerformedLongPress = false;
   11271                     mIgnoreNextUpEvent = false;
   11272                     break;
   11273 
   11274                 case MotionEvent.ACTION_MOVE:
   11275                     drawableHotspotChanged(x, y);
   11276 
   11277                     // Be lenient about moving outside of buttons
   11278                     if (!pointInView(x, y, mTouchSlop)) {
   11279                         // Outside button
   11280                         removeTapCallback();
   11281                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
   11282                             // Remove any future long press/tap checks
   11283                             removeLongPressCallback();
   11284 
   11285                             setPressed(false);
   11286                         }
   11287                     }
   11288                     break;
   11289             }
   11290 
   11291             return true;
   11292         }
   11293 
   11294         return false;
   11295     }
   11296 
   11297     /**
   11298      * @hide
   11299      */
   11300     public boolean isInScrollingContainer() {
   11301         ViewParent p = getParent();
   11302         while (p != null && p instanceof ViewGroup) {
   11303             if (((ViewGroup) p).shouldDelayChildPressedState()) {
   11304                 return true;
   11305             }
   11306             p = p.getParent();
   11307         }
   11308         return false;
   11309     }
   11310 
   11311     /**
   11312      * Remove the longpress detection timer.
   11313      */
   11314     private void removeLongPressCallback() {
   11315         if (mPendingCheckForLongPress != null) {
   11316           removeCallbacks(mPendingCheckForLongPress);
   11317         }
   11318     }
   11319 
   11320     /**
   11321      * Remove the pending click action
   11322      */
   11323     private void removePerformClickCallback() {
   11324         if (mPerformClick != null) {
   11325             removeCallbacks(mPerformClick);
   11326         }
   11327     }
   11328 
   11329     /**
   11330      * Remove the prepress detection timer.
   11331      */
   11332     private void removeUnsetPressCallback() {
   11333         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
   11334             setPressed(false);
   11335             removeCallbacks(mUnsetPressedState);
   11336         }
   11337     }
   11338 
   11339     /**
   11340      * Remove the tap detection timer.
   11341      */
   11342     private void removeTapCallback() {
   11343         if (mPendingCheckForTap != null) {
   11344             mPrivateFlags &= ~PFLAG_PREPRESSED;
   11345             removeCallbacks(mPendingCheckForTap);
   11346         }
   11347     }
   11348 
   11349     /**
   11350      * Cancels a pending long press.  Your subclass can use this if you
   11351      * want the context menu to come up if the user presses and holds
   11352      * at the same place, but you don't want it to come up if they press
   11353      * and then move around enough to cause scrolling.
   11354      */
   11355     public void cancelLongPress() {
   11356         removeLongPressCallback();
   11357 
   11358         /*
   11359          * The prepressed state handled by the tap callback is a display
   11360          * construct, but the tap callback will post a long press callback
   11361          * less its own timeout. Remove it here.
   11362          */
   11363         removeTapCallback();
   11364     }
   11365 
   11366     /**
   11367      * Remove the pending callback for sending a
   11368      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   11369      */
   11370     private void removeSendViewScrolledAccessibilityEventCallback() {
   11371         if (mSendViewScrolledAccessibilityEvent != null) {
   11372             removeCallbacks(mSendViewScrolledAccessibilityEvent);
   11373             mSendViewScrolledAccessibilityEvent.mIsPending = false;
   11374         }
   11375     }
   11376 
   11377     /**
   11378      * Sets the TouchDelegate for this View.
   11379      */
   11380     public void setTouchDelegate(TouchDelegate delegate) {
   11381         mTouchDelegate = delegate;
   11382     }
   11383 
   11384     /**
   11385      * Gets the TouchDelegate for this View.
   11386      */
   11387     public TouchDelegate getTouchDelegate() {
   11388         return mTouchDelegate;
   11389     }
   11390 
   11391     /**
   11392      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
   11393      *
   11394      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
   11395      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
   11396      * available. This method should only be called for touch events.
   11397      *
   11398      * <p class="note">This api is not intended for most applications. Buffered dispatch
   11399      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
   11400      * streams will not improve your input latency. Side effects include: increased latency,
   11401      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
   11402      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
   11403      * you.</p>
   11404      */
   11405     public final void requestUnbufferedDispatch(MotionEvent event) {
   11406         final int action = event.getAction();
   11407         if (mAttachInfo == null
   11408                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
   11409                 || !event.isTouchEvent()) {
   11410             return;
   11411         }
   11412         mAttachInfo.mUnbufferedDispatchRequested = true;
   11413     }
   11414 
   11415     /**
   11416      * Set flags controlling behavior of this view.
   11417      *
   11418      * @param flags Constant indicating the value which should be set
   11419      * @param mask Constant indicating the bit range that should be changed
   11420      */
   11421     void setFlags(int flags, int mask) {
   11422         final boolean accessibilityEnabled =
   11423                 AccessibilityManager.getInstance(mContext).isEnabled();
   11424         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
   11425 
   11426         int old = mViewFlags;
   11427         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
   11428 
   11429         int changed = mViewFlags ^ old;
   11430         if (changed == 0) {
   11431             return;
   11432         }
   11433         int privateFlags = mPrivateFlags;
   11434 
   11435         /* Check if the FOCUSABLE bit has changed */
   11436         if (((changed & FOCUSABLE_MASK) != 0) &&
   11437                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
   11438             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
   11439                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
   11440                 /* Give up focus if we are no longer focusable */
   11441                 clearFocus();
   11442             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
   11443                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
   11444                 /*
   11445                  * Tell the view system that we are now available to take focus
   11446                  * if no one else already has it.
   11447                  */
   11448                 if (mParent != null) mParent.focusableViewAvailable(this);
   11449             }
   11450         }
   11451 
   11452         final int newVisibility = flags & VISIBILITY_MASK;
   11453         if (newVisibility == VISIBLE) {
   11454             if ((changed & VISIBILITY_MASK) != 0) {
   11455                 /*
   11456                  * If this view is becoming visible, invalidate it in case it changed while
   11457                  * it was not visible. Marking it drawn ensures that the invalidation will
   11458                  * go through.
   11459                  */
   11460                 mPrivateFlags |= PFLAG_DRAWN;
   11461                 invalidate(true);
   11462 
   11463                 needGlobalAttributesUpdate(true);
   11464 
   11465                 // a view becoming visible is worth notifying the parent
   11466                 // about in case nothing has focus.  even if this specific view
   11467                 // isn't focusable, it may contain something that is, so let
   11468                 // the root view try to give this focus if nothing else does.
   11469                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
   11470                     mParent.focusableViewAvailable(this);
   11471                 }
   11472             }
   11473         }
   11474 
   11475         /* Check if the GONE bit has changed */
   11476         if ((changed & GONE) != 0) {
   11477             needGlobalAttributesUpdate(false);
   11478             requestLayout();
   11479 
   11480             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
   11481                 if (hasFocus()) clearFocus();
   11482                 clearAccessibilityFocus();
   11483                 destroyDrawingCache();
   11484                 if (mParent instanceof View) {
   11485                     // GONE views noop invalidation, so invalidate the parent
   11486                     ((View) mParent).invalidate(true);
   11487                 }
   11488                 // Mark the view drawn to ensure that it gets invalidated properly the next
   11489                 // time it is visible and gets invalidated
   11490                 mPrivateFlags |= PFLAG_DRAWN;
   11491             }
   11492             if (mAttachInfo != null) {
   11493                 mAttachInfo.mViewVisibilityChanged = true;
   11494             }
   11495         }
   11496 
   11497         /* Check if the VISIBLE bit has changed */
   11498         if ((changed & INVISIBLE) != 0) {
   11499             needGlobalAttributesUpdate(false);
   11500             /*
   11501              * If this view is becoming invisible, set the DRAWN flag so that
   11502              * the next invalidate() will not be skipped.
   11503              */
   11504             mPrivateFlags |= PFLAG_DRAWN;
   11505 
   11506             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
   11507                 // root view becoming invisible shouldn't clear focus and accessibility focus
   11508                 if (getRootView() != this) {
   11509                     if (hasFocus()) clearFocus();
   11510                     clearAccessibilityFocus();
   11511                 }
   11512             }
   11513             if (mAttachInfo != null) {
   11514                 mAttachInfo.mViewVisibilityChanged = true;
   11515             }
   11516         }
   11517 
   11518         if ((changed & VISIBILITY_MASK) != 0) {
   11519             // If the view is invisible, cleanup its display list to free up resources
   11520             if (newVisibility != VISIBLE && mAttachInfo != null) {
   11521                 cleanupDraw();
   11522             }
   11523 
   11524             if (mParent instanceof ViewGroup) {
   11525                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
   11526                         (changed & VISIBILITY_MASK), newVisibility);
   11527                 ((View) mParent).invalidate(true);
   11528             } else if (mParent != null) {
   11529                 mParent.invalidateChild(this, null);
   11530             }
   11531 
   11532             if (mAttachInfo != null) {
   11533                 dispatchVisibilityChanged(this, newVisibility);
   11534 
   11535                 // Aggregated visibility changes are dispatched to attached views
   11536                 // in visible windows where the parent is currently shown/drawn
   11537                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
   11538                 // discounting clipping or overlapping. This makes it a good place
   11539                 // to change animation states.
   11540                 if (mParent != null && getWindowVisibility() == VISIBLE &&
   11541                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
   11542                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
   11543                 }
   11544                 notifySubtreeAccessibilityStateChangedIfNeeded();
   11545             }
   11546         }
   11547 
   11548         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
   11549             destroyDrawingCache();
   11550         }
   11551 
   11552         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
   11553             destroyDrawingCache();
   11554             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   11555             invalidateParentCaches();
   11556         }
   11557 
   11558         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
   11559             destroyDrawingCache();
   11560             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   11561         }
   11562 
   11563         if ((changed & DRAW_MASK) != 0) {
   11564             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
   11565                 if (mBackground != null
   11566                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
   11567                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   11568                 } else {
   11569                     mPrivateFlags |= PFLAG_SKIP_DRAW;
   11570                 }
   11571             } else {
   11572                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   11573             }
   11574             requestLayout();
   11575             invalidate(true);
   11576         }
   11577 
   11578         if ((changed & KEEP_SCREEN_ON) != 0) {
   11579             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   11580                 mParent.recomputeViewAttributes(this);
   11581             }
   11582         }
   11583 
   11584         if (accessibilityEnabled) {
   11585             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
   11586                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
   11587                     || (changed & CONTEXT_CLICKABLE) != 0) {
   11588                 if (oldIncludeForAccessibility != includeForAccessibility()) {
   11589                     notifySubtreeAccessibilityStateChangedIfNeeded();
   11590                 } else {
   11591                     notifyViewAccessibilityStateChangedIfNeeded(
   11592                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   11593                 }
   11594             } else if ((changed & ENABLED_MASK) != 0) {
   11595                 notifyViewAccessibilityStateChangedIfNeeded(
   11596                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   11597             }
   11598         }
   11599     }
   11600 
   11601     /**
   11602      * Change the view's z order in the tree, so it's on top of other sibling
   11603      * views. This ordering change may affect layout, if the parent container
   11604      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
   11605      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
   11606      * method should be followed by calls to {@link #requestLayout()} and
   11607      * {@link View#invalidate()} on the view's parent to force the parent to redraw
   11608      * with the new child ordering.
   11609      *
   11610      * @see ViewGroup#bringChildToFront(View)
   11611      */
   11612     public void bringToFront() {
   11613         if (mParent != null) {
   11614             mParent.bringChildToFront(this);
   11615         }
   11616     }
   11617 
   11618     /**
   11619      * This is called in response to an internal scroll in this view (i.e., the
   11620      * view scrolled its own contents). This is typically as a result of
   11621      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
   11622      * called.
   11623      *
   11624      * @param l Current horizontal scroll origin.
   11625      * @param t Current vertical scroll origin.
   11626      * @param oldl Previous horizontal scroll origin.
   11627      * @param oldt Previous vertical scroll origin.
   11628      */
   11629     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   11630         notifySubtreeAccessibilityStateChangedIfNeeded();
   11631 
   11632         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   11633             postSendViewScrolledAccessibilityEventCallback();
   11634         }
   11635 
   11636         mBackgroundSizeChanged = true;
   11637         if (mForegroundInfo != null) {
   11638             mForegroundInfo.mBoundsChanged = true;
   11639         }
   11640 
   11641         final AttachInfo ai = mAttachInfo;
   11642         if (ai != null) {
   11643             ai.mViewScrollChanged = true;
   11644         }
   11645 
   11646         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
   11647             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
   11648         }
   11649     }
   11650 
   11651     /**
   11652      * Interface definition for a callback to be invoked when the scroll
   11653      * X or Y positions of a view change.
   11654      * <p>
   11655      * <b>Note:</b> Some views handle scrolling independently from View and may
   11656      * have their own separate listeners for scroll-type events. For example,
   11657      * {@link android.widget.ListView ListView} allows clients to register an
   11658      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   11659      * to listen for changes in list scroll position.
   11660      *
   11661      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
   11662      */
   11663     public interface OnScrollChangeListener {
   11664         /**
   11665          * Called when the scroll position of a view changes.
   11666          *
   11667          * @param v The view whose scroll position has changed.
   11668          * @param scrollX Current horizontal scroll origin.
   11669          * @param scrollY Current vertical scroll origin.
   11670          * @param oldScrollX Previous horizontal scroll origin.
   11671          * @param oldScrollY Previous vertical scroll origin.
   11672          */
   11673         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
   11674     }
   11675 
   11676     /**
   11677      * Interface definition for a callback to be invoked when the layout bounds of a view
   11678      * changes due to layout processing.
   11679      */
   11680     public interface OnLayoutChangeListener {
   11681         /**
   11682          * Called when the layout bounds of a view changes due to layout processing.
   11683          *
   11684          * @param v The view whose bounds have changed.
   11685          * @param left The new value of the view's left property.
   11686          * @param top The new value of the view's top property.
   11687          * @param right The new value of the view's right property.
   11688          * @param bottom The new value of the view's bottom property.
   11689          * @param oldLeft The previous value of the view's left property.
   11690          * @param oldTop The previous value of the view's top property.
   11691          * @param oldRight The previous value of the view's right property.
   11692          * @param oldBottom The previous value of the view's bottom property.
   11693          */
   11694         void onLayoutChange(View v, int left, int top, int right, int bottom,
   11695             int oldLeft, int oldTop, int oldRight, int oldBottom);
   11696     }
   11697 
   11698     /**
   11699      * This is called during layout when the size of this view has changed. If
   11700      * you were just added to the view hierarchy, you're called with the old
   11701      * values of 0.
   11702      *
   11703      * @param w Current width of this view.
   11704      * @param h Current height of this view.
   11705      * @param oldw Old width of this view.
   11706      * @param oldh Old height of this view.
   11707      */
   11708     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   11709     }
   11710 
   11711     /**
   11712      * Called by draw to draw the child views. This may be overridden
   11713      * by derived classes to gain control just before its children are drawn
   11714      * (but after its own view has been drawn).
   11715      * @param canvas the canvas on which to draw the view
   11716      */
   11717     protected void dispatchDraw(Canvas canvas) {
   11718 
   11719     }
   11720 
   11721     /**
   11722      * Gets the parent of this view. Note that the parent is a
   11723      * ViewParent and not necessarily a View.
   11724      *
   11725      * @return Parent of this view.
   11726      */
   11727     public final ViewParent getParent() {
   11728         return mParent;
   11729     }
   11730 
   11731     /**
   11732      * Set the horizontal scrolled position of your view. This will cause a call to
   11733      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   11734      * invalidated.
   11735      * @param value the x position to scroll to
   11736      */
   11737     public void setScrollX(int value) {
   11738         scrollTo(value, mScrollY);
   11739     }
   11740 
   11741     /**
   11742      * Set the vertical scrolled position of your view. This will cause a call to
   11743      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   11744      * invalidated.
   11745      * @param value the y position to scroll to
   11746      */
   11747     public void setScrollY(int value) {
   11748         scrollTo(mScrollX, value);
   11749     }
   11750 
   11751     /**
   11752      * Return the scrolled left position of this view. This is the left edge of
   11753      * the displayed part of your view. You do not need to draw any pixels
   11754      * farther left, since those are outside of the frame of your view on
   11755      * screen.
   11756      *
   11757      * @return The left edge of the displayed part of your view, in pixels.
   11758      */
   11759     public final int getScrollX() {
   11760         return mScrollX;
   11761     }
   11762 
   11763     /**
   11764      * Return the scrolled top position of this view. This is the top edge of
   11765      * the displayed part of your view. You do not need to draw any pixels above
   11766      * it, since those are outside of the frame of your view on screen.
   11767      *
   11768      * @return The top edge of the displayed part of your view, in pixels.
   11769      */
   11770     public final int getScrollY() {
   11771         return mScrollY;
   11772     }
   11773 
   11774     /**
   11775      * Return the width of the your view.
   11776      *
   11777      * @return The width of your view, in pixels.
   11778      */
   11779     @ViewDebug.ExportedProperty(category = "layout")
   11780     public final int getWidth() {
   11781         return mRight - mLeft;
   11782     }
   11783 
   11784     /**
   11785      * Return the height of your view.
   11786      *
   11787      * @return The height of your view, in pixels.
   11788      */
   11789     @ViewDebug.ExportedProperty(category = "layout")
   11790     public final int getHeight() {
   11791         return mBottom - mTop;
   11792     }
   11793 
   11794     /**
   11795      * Return the visible drawing bounds of your view. Fills in the output
   11796      * rectangle with the values from getScrollX(), getScrollY(),
   11797      * getWidth(), and getHeight(). These bounds do not account for any
   11798      * transformation properties currently set on the view, such as
   11799      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
   11800      *
   11801      * @param outRect The (scrolled) drawing bounds of the view.
   11802      */
   11803     public void getDrawingRect(Rect outRect) {
   11804         outRect.left = mScrollX;
   11805         outRect.top = mScrollY;
   11806         outRect.right = mScrollX + (mRight - mLeft);
   11807         outRect.bottom = mScrollY + (mBottom - mTop);
   11808     }
   11809 
   11810     /**
   11811      * Like {@link #getMeasuredWidthAndState()}, but only returns the
   11812      * raw width component (that is the result is masked by
   11813      * {@link #MEASURED_SIZE_MASK}).
   11814      *
   11815      * @return The raw measured width of this view.
   11816      */
   11817     public final int getMeasuredWidth() {
   11818         return mMeasuredWidth & MEASURED_SIZE_MASK;
   11819     }
   11820 
   11821     /**
   11822      * Return the full width measurement information for this view as computed
   11823      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   11824      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   11825      * This should be used during measurement and layout calculations only. Use
   11826      * {@link #getWidth()} to see how wide a view is after layout.
   11827      *
   11828      * @return The measured width of this view as a bit mask.
   11829      */
   11830     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   11831             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   11832                     name = "MEASURED_STATE_TOO_SMALL"),
   11833     })
   11834     public final int getMeasuredWidthAndState() {
   11835         return mMeasuredWidth;
   11836     }
   11837 
   11838     /**
   11839      * Like {@link #getMeasuredHeightAndState()}, but only returns the
   11840      * raw width component (that is the result is masked by
   11841      * {@link #MEASURED_SIZE_MASK}).
   11842      *
   11843      * @return The raw measured height of this view.
   11844      */
   11845     public final int getMeasuredHeight() {
   11846         return mMeasuredHeight & MEASURED_SIZE_MASK;
   11847     }
   11848 
   11849     /**
   11850      * Return the full height measurement information for this view as computed
   11851      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   11852      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   11853      * This should be used during measurement and layout calculations only. Use
   11854      * {@link #getHeight()} to see how wide a view is after layout.
   11855      *
   11856      * @return The measured width of this view as a bit mask.
   11857      */
   11858     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   11859             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   11860                     name = "MEASURED_STATE_TOO_SMALL"),
   11861     })
   11862     public final int getMeasuredHeightAndState() {
   11863         return mMeasuredHeight;
   11864     }
   11865 
   11866     /**
   11867      * Return only the state bits of {@link #getMeasuredWidthAndState()}
   11868      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
   11869      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
   11870      * and the height component is at the shifted bits
   11871      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
   11872      */
   11873     public final int getMeasuredState() {
   11874         return (mMeasuredWidth&MEASURED_STATE_MASK)
   11875                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
   11876                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
   11877     }
   11878 
   11879     /**
   11880      * The transform matrix of this view, which is calculated based on the current
   11881      * rotation, scale, and pivot properties.
   11882      *
   11883      * @see #getRotation()
   11884      * @see #getScaleX()
   11885      * @see #getScaleY()
   11886      * @see #getPivotX()
   11887      * @see #getPivotY()
   11888      * @return The current transform matrix for the view
   11889      */
   11890     public Matrix getMatrix() {
   11891         ensureTransformationInfo();
   11892         final Matrix matrix = mTransformationInfo.mMatrix;
   11893         mRenderNode.getMatrix(matrix);
   11894         return matrix;
   11895     }
   11896 
   11897     /**
   11898      * Returns true if the transform matrix is the identity matrix.
   11899      * Recomputes the matrix if necessary.
   11900      *
   11901      * @return True if the transform matrix is the identity matrix, false otherwise.
   11902      */
   11903     final boolean hasIdentityMatrix() {
   11904         return mRenderNode.hasIdentityMatrix();
   11905     }
   11906 
   11907     void ensureTransformationInfo() {
   11908         if (mTransformationInfo == null) {
   11909             mTransformationInfo = new TransformationInfo();
   11910         }
   11911     }
   11912 
   11913     /**
   11914      * Utility method to retrieve the inverse of the current mMatrix property.
   11915      * We cache the matrix to avoid recalculating it when transform properties
   11916      * have not changed.
   11917      *
   11918      * @return The inverse of the current matrix of this view.
   11919      * @hide
   11920      */
   11921     public final Matrix getInverseMatrix() {
   11922         ensureTransformationInfo();
   11923         if (mTransformationInfo.mInverseMatrix == null) {
   11924             mTransformationInfo.mInverseMatrix = new Matrix();
   11925         }
   11926         final Matrix matrix = mTransformationInfo.mInverseMatrix;
   11927         mRenderNode.getInverseMatrix(matrix);
   11928         return matrix;
   11929     }
   11930 
   11931     /**
   11932      * Gets the distance along the Z axis from the camera to this view.
   11933      *
   11934      * @see #setCameraDistance(float)
   11935      *
   11936      * @return The distance along the Z axis.
   11937      */
   11938     public float getCameraDistance() {
   11939         final float dpi = mResources.getDisplayMetrics().densityDpi;
   11940         return -(mRenderNode.getCameraDistance() * dpi);
   11941     }
   11942 
   11943     /**
   11944      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
   11945      * views are drawn) from the camera to this view. The camera's distance
   11946      * affects 3D transformations, for instance rotations around the X and Y
   11947      * axis. If the rotationX or rotationY properties are changed and this view is
   11948      * large (more than half the size of the screen), it is recommended to always
   11949      * use a camera distance that's greater than the height (X axis rotation) or
   11950      * the width (Y axis rotation) of this view.</p>
   11951      *
   11952      * <p>The distance of the camera from the view plane can have an affect on the
   11953      * perspective distortion of the view when it is rotated around the x or y axis.
   11954      * For example, a large distance will result in a large viewing angle, and there
   11955      * will not be much perspective distortion of the view as it rotates. A short
   11956      * distance may cause much more perspective distortion upon rotation, and can
   11957      * also result in some drawing artifacts if the rotated view ends up partially
   11958      * behind the camera (which is why the recommendation is to use a distance at
   11959      * least as far as the size of the view, if the view is to be rotated.)</p>
   11960      *
   11961      * <p>The distance is expressed in "depth pixels." The default distance depends
   11962      * on the screen density. For instance, on a medium density display, the
   11963      * default distance is 1280. On a high density display, the default distance
   11964      * is 1920.</p>
   11965      *
   11966      * <p>If you want to specify a distance that leads to visually consistent
   11967      * results across various densities, use the following formula:</p>
   11968      * <pre>
   11969      * float scale = context.getResources().getDisplayMetrics().density;
   11970      * view.setCameraDistance(distance * scale);
   11971      * </pre>
   11972      *
   11973      * <p>The density scale factor of a high density display is 1.5,
   11974      * and 1920 = 1280 * 1.5.</p>
   11975      *
   11976      * @param distance The distance in "depth pixels", if negative the opposite
   11977      *        value is used
   11978      *
   11979      * @see #setRotationX(float)
   11980      * @see #setRotationY(float)
   11981      */
   11982     public void setCameraDistance(float distance) {
   11983         final float dpi = mResources.getDisplayMetrics().densityDpi;
   11984 
   11985         invalidateViewProperty(true, false);
   11986         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
   11987         invalidateViewProperty(false, false);
   11988 
   11989         invalidateParentIfNeededAndWasQuickRejected();
   11990     }
   11991 
   11992     /**
   11993      * The degrees that the view is rotated around the pivot point.
   11994      *
   11995      * @see #setRotation(float)
   11996      * @see #getPivotX()
   11997      * @see #getPivotY()
   11998      *
   11999      * @return The degrees of rotation.
   12000      */
   12001     @ViewDebug.ExportedProperty(category = "drawing")
   12002     public float getRotation() {
   12003         return mRenderNode.getRotation();
   12004     }
   12005 
   12006     /**
   12007      * Sets the degrees that the view is rotated around the pivot point. Increasing values
   12008      * result in clockwise rotation.
   12009      *
   12010      * @param rotation The degrees of rotation.
   12011      *
   12012      * @see #getRotation()
   12013      * @see #getPivotX()
   12014      * @see #getPivotY()
   12015      * @see #setRotationX(float)
   12016      * @see #setRotationY(float)
   12017      *
   12018      * @attr ref android.R.styleable#View_rotation
   12019      */
   12020     public void setRotation(float rotation) {
   12021         if (rotation != getRotation()) {
   12022             // Double-invalidation is necessary to capture view's old and new areas
   12023             invalidateViewProperty(true, false);
   12024             mRenderNode.setRotation(rotation);
   12025             invalidateViewProperty(false, true);
   12026 
   12027             invalidateParentIfNeededAndWasQuickRejected();
   12028             notifySubtreeAccessibilityStateChangedIfNeeded();
   12029         }
   12030     }
   12031 
   12032     /**
   12033      * The degrees that the view is rotated around the vertical axis through the pivot point.
   12034      *
   12035      * @see #getPivotX()
   12036      * @see #getPivotY()
   12037      * @see #setRotationY(float)
   12038      *
   12039      * @return The degrees of Y rotation.
   12040      */
   12041     @ViewDebug.ExportedProperty(category = "drawing")
   12042     public float getRotationY() {
   12043         return mRenderNode.getRotationY();
   12044     }
   12045 
   12046     /**
   12047      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
   12048      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
   12049      * down the y axis.
   12050      *
   12051      * When rotating large views, it is recommended to adjust the camera distance
   12052      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   12053      *
   12054      * @param rotationY The degrees of Y rotation.
   12055      *
   12056      * @see #getRotationY()
   12057      * @see #getPivotX()
   12058      * @see #getPivotY()
   12059      * @see #setRotation(float)
   12060      * @see #setRotationX(float)
   12061      * @see #setCameraDistance(float)
   12062      *
   12063      * @attr ref android.R.styleable#View_rotationY
   12064      */
   12065     public void setRotationY(float rotationY) {
   12066         if (rotationY != getRotationY()) {
   12067             invalidateViewProperty(true, false);
   12068             mRenderNode.setRotationY(rotationY);
   12069             invalidateViewProperty(false, true);
   12070 
   12071             invalidateParentIfNeededAndWasQuickRejected();
   12072             notifySubtreeAccessibilityStateChangedIfNeeded();
   12073         }
   12074     }
   12075 
   12076     /**
   12077      * The degrees that the view is rotated around the horizontal axis through the pivot point.
   12078      *
   12079      * @see #getPivotX()
   12080      * @see #getPivotY()
   12081      * @see #setRotationX(float)
   12082      *
   12083      * @return The degrees of X rotation.
   12084      */
   12085     @ViewDebug.ExportedProperty(category = "drawing")
   12086     public float getRotationX() {
   12087         return mRenderNode.getRotationX();
   12088     }
   12089 
   12090     /**
   12091      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
   12092      * Increasing values result in clockwise rotation from the viewpoint of looking down the
   12093      * x axis.
   12094      *
   12095      * When rotating large views, it is recommended to adjust the camera distance
   12096      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   12097      *
   12098      * @param rotationX The degrees of X rotation.
   12099      *
   12100      * @see #getRotationX()
   12101      * @see #getPivotX()
   12102      * @see #getPivotY()
   12103      * @see #setRotation(float)
   12104      * @see #setRotationY(float)
   12105      * @see #setCameraDistance(float)
   12106      *
   12107      * @attr ref android.R.styleable#View_rotationX
   12108      */
   12109     public void setRotationX(float rotationX) {
   12110         if (rotationX != getRotationX()) {
   12111             invalidateViewProperty(true, false);
   12112             mRenderNode.setRotationX(rotationX);
   12113             invalidateViewProperty(false, true);
   12114 
   12115             invalidateParentIfNeededAndWasQuickRejected();
   12116             notifySubtreeAccessibilityStateChangedIfNeeded();
   12117         }
   12118     }
   12119 
   12120     /**
   12121      * The amount that the view is scaled in x around the pivot point, as a proportion of
   12122      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
   12123      *
   12124      * <p>By default, this is 1.0f.
   12125      *
   12126      * @see #getPivotX()
   12127      * @see #getPivotY()
   12128      * @return The scaling factor.
   12129      */
   12130     @ViewDebug.ExportedProperty(category = "drawing")
   12131     public float getScaleX() {
   12132         return mRenderNode.getScaleX();
   12133     }
   12134 
   12135     /**
   12136      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
   12137      * the view's unscaled width. A value of 1 means that no scaling is applied.
   12138      *
   12139      * @param scaleX The scaling factor.
   12140      * @see #getPivotX()
   12141      * @see #getPivotY()
   12142      *
   12143      * @attr ref android.R.styleable#View_scaleX
   12144      */
   12145     public void setScaleX(float scaleX) {
   12146         if (scaleX != getScaleX()) {
   12147             invalidateViewProperty(true, false);
   12148             mRenderNode.setScaleX(scaleX);
   12149             invalidateViewProperty(false, true);
   12150 
   12151             invalidateParentIfNeededAndWasQuickRejected();
   12152             notifySubtreeAccessibilityStateChangedIfNeeded();
   12153         }
   12154     }
   12155 
   12156     /**
   12157      * The amount that the view is scaled in y around the pivot point, as a proportion of
   12158      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
   12159      *
   12160      * <p>By default, this is 1.0f.
   12161      *
   12162      * @see #getPivotX()
   12163      * @see #getPivotY()
   12164      * @return The scaling factor.
   12165      */
   12166     @ViewDebug.ExportedProperty(category = "drawing")
   12167     public float getScaleY() {
   12168         return mRenderNode.getScaleY();
   12169     }
   12170 
   12171     /**
   12172      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
   12173      * the view's unscaled width. A value of 1 means that no scaling is applied.
   12174      *
   12175      * @param scaleY The scaling factor.
   12176      * @see #getPivotX()
   12177      * @see #getPivotY()
   12178      *
   12179      * @attr ref android.R.styleable#View_scaleY
   12180      */
   12181     public void setScaleY(float scaleY) {
   12182         if (scaleY != getScaleY()) {
   12183             invalidateViewProperty(true, false);
   12184             mRenderNode.setScaleY(scaleY);
   12185             invalidateViewProperty(false, true);
   12186 
   12187             invalidateParentIfNeededAndWasQuickRejected();
   12188             notifySubtreeAccessibilityStateChangedIfNeeded();
   12189         }
   12190     }
   12191 
   12192     /**
   12193      * The x location of the point around which the view is {@link #setRotation(float) rotated}
   12194      * and {@link #setScaleX(float) scaled}.
   12195      *
   12196      * @see #getRotation()
   12197      * @see #getScaleX()
   12198      * @see #getScaleY()
   12199      * @see #getPivotY()
   12200      * @return The x location of the pivot point.
   12201      *
   12202      * @attr ref android.R.styleable#View_transformPivotX
   12203      */
   12204     @ViewDebug.ExportedProperty(category = "drawing")
   12205     public float getPivotX() {
   12206         return mRenderNode.getPivotX();
   12207     }
   12208 
   12209     /**
   12210      * Sets the x location of the point around which the view is
   12211      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
   12212      * By default, the pivot point is centered on the object.
   12213      * Setting this property disables this behavior and causes the view to use only the
   12214      * explicitly set pivotX and pivotY values.
   12215      *
   12216      * @param pivotX The x location of the pivot point.
   12217      * @see #getRotation()
   12218      * @see #getScaleX()
   12219      * @see #getScaleY()
   12220      * @see #getPivotY()
   12221      *
   12222      * @attr ref android.R.styleable#View_transformPivotX
   12223      */
   12224     public void setPivotX(float pivotX) {
   12225         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
   12226             invalidateViewProperty(true, false);
   12227             mRenderNode.setPivotX(pivotX);
   12228             invalidateViewProperty(false, true);
   12229 
   12230             invalidateParentIfNeededAndWasQuickRejected();
   12231         }
   12232     }
   12233 
   12234     /**
   12235      * The y location of the point around which the view is {@link #setRotation(float) rotated}
   12236      * and {@link #setScaleY(float) scaled}.
   12237      *
   12238      * @see #getRotation()
   12239      * @see #getScaleX()
   12240      * @see #getScaleY()
   12241      * @see #getPivotY()
   12242      * @return The y location of the pivot point.
   12243      *
   12244      * @attr ref android.R.styleable#View_transformPivotY
   12245      */
   12246     @ViewDebug.ExportedProperty(category = "drawing")
   12247     public float getPivotY() {
   12248         return mRenderNode.getPivotY();
   12249     }
   12250 
   12251     /**
   12252      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
   12253      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
   12254      * Setting this property disables this behavior and causes the view to use only the
   12255      * explicitly set pivotX and pivotY values.
   12256      *
   12257      * @param pivotY The y location of the pivot point.
   12258      * @see #getRotation()
   12259      * @see #getScaleX()
   12260      * @see #getScaleY()
   12261      * @see #getPivotY()
   12262      *
   12263      * @attr ref android.R.styleable#View_transformPivotY
   12264      */
   12265     public void setPivotY(float pivotY) {
   12266         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
   12267             invalidateViewProperty(true, false);
   12268             mRenderNode.setPivotY(pivotY);
   12269             invalidateViewProperty(false, true);
   12270 
   12271             invalidateParentIfNeededAndWasQuickRejected();
   12272         }
   12273     }
   12274 
   12275     /**
   12276      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
   12277      * completely transparent and 1 means the view is completely opaque.
   12278      *
   12279      * <p>By default this is 1.0f.
   12280      * @return The opacity of the view.
   12281      */
   12282     @ViewDebug.ExportedProperty(category = "drawing")
   12283     public float getAlpha() {
   12284         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
   12285     }
   12286 
   12287     /**
   12288      * Sets the behavior for overlapping rendering for this view (see {@link
   12289      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
   12290      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
   12291      * providing the value which is then used internally. That is, when {@link
   12292      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
   12293      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
   12294      * instead.
   12295      *
   12296      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
   12297      * instead of that returned by {@link #hasOverlappingRendering()}.
   12298      *
   12299      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
   12300      */
   12301     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
   12302         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
   12303         if (hasOverlappingRendering) {
   12304             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
   12305         } else {
   12306             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
   12307         }
   12308     }
   12309 
   12310     /**
   12311      * Returns the value for overlapping rendering that is used internally. This is either
   12312      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
   12313      * the return value of {@link #hasOverlappingRendering()}, otherwise.
   12314      *
   12315      * @return The value for overlapping rendering being used internally.
   12316      */
   12317     public final boolean getHasOverlappingRendering() {
   12318         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
   12319                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
   12320                 hasOverlappingRendering();
   12321     }
   12322 
   12323     /**
   12324      * Returns whether this View has content which overlaps.
   12325      *
   12326      * <p>This function, intended to be overridden by specific View types, is an optimization when
   12327      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
   12328      * an offscreen buffer and then composited into place, which can be expensive. If the view has
   12329      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
   12330      * directly. An example of overlapping rendering is a TextView with a background image, such as
   12331      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
   12332      * ImageView with only the foreground image. The default implementation returns true; subclasses
   12333      * should override if they have cases which can be optimized.</p>
   12334      *
   12335      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
   12336      * necessitates that a View return true if it uses the methods internally without passing the
   12337      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
   12338      *
   12339      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
   12340      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
   12341      *
   12342      * @return true if the content in this view might overlap, false otherwise.
   12343      */
   12344     @ViewDebug.ExportedProperty(category = "drawing")
   12345     public boolean hasOverlappingRendering() {
   12346         return true;
   12347     }
   12348 
   12349     /**
   12350      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
   12351      * completely transparent and 1 means the view is completely opaque.
   12352      *
   12353      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
   12354      * can have significant performance implications, especially for large views. It is best to use
   12355      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
   12356      *
   12357      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
   12358      * strongly recommended for performance reasons to either override
   12359      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
   12360      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
   12361      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
   12362      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
   12363      * of rendering cost, even for simple or small views. Starting with
   12364      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
   12365      * applied to the view at the rendering level.</p>
   12366      *
   12367      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
   12368      * responsible for applying the opacity itself.</p>
   12369      *
   12370      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
   12371      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
   12372      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
   12373      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
   12374      *
   12375      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
   12376      * value will clip a View to its bounds, unless the View returns <code>false</code> from
   12377      * {@link #hasOverlappingRendering}.</p>
   12378      *
   12379      * @param alpha The opacity of the view.
   12380      *
   12381      * @see #hasOverlappingRendering()
   12382      * @see #setLayerType(int, android.graphics.Paint)
   12383      *
   12384      * @attr ref android.R.styleable#View_alpha
   12385      */
   12386     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
   12387         ensureTransformationInfo();
   12388         if (mTransformationInfo.mAlpha != alpha) {
   12389             // Report visibility changes, which can affect children, to accessibility
   12390             if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
   12391                 notifySubtreeAccessibilityStateChangedIfNeeded();
   12392             }
   12393             mTransformationInfo.mAlpha = alpha;
   12394             if (onSetAlpha((int) (alpha * 255))) {
   12395                 mPrivateFlags |= PFLAG_ALPHA_SET;
   12396                 // subclass is handling alpha - don't optimize rendering cache invalidation
   12397                 invalidateParentCaches();
   12398                 invalidate(true);
   12399             } else {
   12400                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   12401                 invalidateViewProperty(true, false);
   12402                 mRenderNode.setAlpha(getFinalAlpha());
   12403             }
   12404         }
   12405     }
   12406 
   12407     /**
   12408      * Faster version of setAlpha() which performs the same steps except there are
   12409      * no calls to invalidate(). The caller of this function should perform proper invalidation
   12410      * on the parent and this object. The return value indicates whether the subclass handles
   12411      * alpha (the return value for onSetAlpha()).
   12412      *
   12413      * @param alpha The new value for the alpha property
   12414      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
   12415      *         the new value for the alpha property is different from the old value
   12416      */
   12417     boolean setAlphaNoInvalidation(float alpha) {
   12418         ensureTransformationInfo();
   12419         if (mTransformationInfo.mAlpha != alpha) {
   12420             mTransformationInfo.mAlpha = alpha;
   12421             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
   12422             if (subclassHandlesAlpha) {
   12423                 mPrivateFlags |= PFLAG_ALPHA_SET;
   12424                 return true;
   12425             } else {
   12426                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   12427                 mRenderNode.setAlpha(getFinalAlpha());
   12428             }
   12429         }
   12430         return false;
   12431     }
   12432 
   12433     /**
   12434      * This property is hidden and intended only for use by the Fade transition, which
   12435      * animates it to produce a visual translucency that does not side-effect (or get
   12436      * affected by) the real alpha property. This value is composited with the other
   12437      * alpha value (and the AlphaAnimation value, when that is present) to produce
   12438      * a final visual translucency result, which is what is passed into the DisplayList.
   12439      *
   12440      * @hide
   12441      */
   12442     public void setTransitionAlpha(float alpha) {
   12443         ensureTransformationInfo();
   12444         if (mTransformationInfo.mTransitionAlpha != alpha) {
   12445             mTransformationInfo.mTransitionAlpha = alpha;
   12446             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   12447             invalidateViewProperty(true, false);
   12448             mRenderNode.setAlpha(getFinalAlpha());
   12449         }
   12450     }
   12451 
   12452     /**
   12453      * Calculates the visual alpha of this view, which is a combination of the actual
   12454      * alpha value and the transitionAlpha value (if set).
   12455      */
   12456     private float getFinalAlpha() {
   12457         if (mTransformationInfo != null) {
   12458             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
   12459         }
   12460         return 1;
   12461     }
   12462 
   12463     /**
   12464      * This property is hidden and intended only for use by the Fade transition, which
   12465      * animates it to produce a visual translucency that does not side-effect (or get
   12466      * affected by) the real alpha property. This value is composited with the other
   12467      * alpha value (and the AlphaAnimation value, when that is present) to produce
   12468      * a final visual translucency result, which is what is passed into the DisplayList.
   12469      *
   12470      * @hide
   12471      */
   12472     @ViewDebug.ExportedProperty(category = "drawing")
   12473     public float getTransitionAlpha() {
   12474         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
   12475     }
   12476 
   12477     /**
   12478      * Top position of this view relative to its parent.
   12479      *
   12480      * @return The top of this view, in pixels.
   12481      */
   12482     @ViewDebug.CapturedViewProperty
   12483     public final int getTop() {
   12484         return mTop;
   12485     }
   12486 
   12487     /**
   12488      * Sets the top position of this view relative to its parent. This method is meant to be called
   12489      * by the layout system and should not generally be called otherwise, because the property
   12490      * may be changed at any time by the layout.
   12491      *
   12492      * @param top The top of this view, in pixels.
   12493      */
   12494     public final void setTop(int top) {
   12495         if (top != mTop) {
   12496             final boolean matrixIsIdentity = hasIdentityMatrix();
   12497             if (matrixIsIdentity) {
   12498                 if (mAttachInfo != null) {
   12499                     int minTop;
   12500                     int yLoc;
   12501                     if (top < mTop) {
   12502                         minTop = top;
   12503                         yLoc = top - mTop;
   12504                     } else {
   12505                         minTop = mTop;
   12506                         yLoc = 0;
   12507                     }
   12508                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
   12509                 }
   12510             } else {
   12511                 // Double-invalidation is necessary to capture view's old and new areas
   12512                 invalidate(true);
   12513             }
   12514 
   12515             int width = mRight - mLeft;
   12516             int oldHeight = mBottom - mTop;
   12517 
   12518             mTop = top;
   12519             mRenderNode.setTop(mTop);
   12520 
   12521             sizeChange(width, mBottom - mTop, width, oldHeight);
   12522 
   12523             if (!matrixIsIdentity) {
   12524                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12525                 invalidate(true);
   12526             }
   12527             mBackgroundSizeChanged = true;
   12528             if (mForegroundInfo != null) {
   12529                 mForegroundInfo.mBoundsChanged = true;
   12530             }
   12531             invalidateParentIfNeeded();
   12532             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   12533                 // View was rejected last time it was drawn by its parent; this may have changed
   12534                 invalidateParentIfNeeded();
   12535             }
   12536         }
   12537     }
   12538 
   12539     /**
   12540      * Bottom position of this view relative to its parent.
   12541      *
   12542      * @return The bottom of this view, in pixels.
   12543      */
   12544     @ViewDebug.CapturedViewProperty
   12545     public final int getBottom() {
   12546         return mBottom;
   12547     }
   12548 
   12549     /**
   12550      * True if this view has changed since the last time being drawn.
   12551      *
   12552      * @return The dirty state of this view.
   12553      */
   12554     public boolean isDirty() {
   12555         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
   12556     }
   12557 
   12558     /**
   12559      * Sets the bottom position of this view relative to its parent. This method is meant to be
   12560      * called by the layout system and should not generally be called otherwise, because the
   12561      * property may be changed at any time by the layout.
   12562      *
   12563      * @param bottom The bottom of this view, in pixels.
   12564      */
   12565     public final void setBottom(int bottom) {
   12566         if (bottom != mBottom) {
   12567             final boolean matrixIsIdentity = hasIdentityMatrix();
   12568             if (matrixIsIdentity) {
   12569                 if (mAttachInfo != null) {
   12570                     int maxBottom;
   12571                     if (bottom < mBottom) {
   12572                         maxBottom = mBottom;
   12573                     } else {
   12574                         maxBottom = bottom;
   12575                     }
   12576                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
   12577                 }
   12578             } else {
   12579                 // Double-invalidation is necessary to capture view's old and new areas
   12580                 invalidate(true);
   12581             }
   12582 
   12583             int width = mRight - mLeft;
   12584             int oldHeight = mBottom - mTop;
   12585 
   12586             mBottom = bottom;
   12587             mRenderNode.setBottom(mBottom);
   12588 
   12589             sizeChange(width, mBottom - mTop, width, oldHeight);
   12590 
   12591             if (!matrixIsIdentity) {
   12592                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12593                 invalidate(true);
   12594             }
   12595             mBackgroundSizeChanged = true;
   12596             if (mForegroundInfo != null) {
   12597                 mForegroundInfo.mBoundsChanged = true;
   12598             }
   12599             invalidateParentIfNeeded();
   12600             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   12601                 // View was rejected last time it was drawn by its parent; this may have changed
   12602                 invalidateParentIfNeeded();
   12603             }
   12604         }
   12605     }
   12606 
   12607     /**
   12608      * Left position of this view relative to its parent.
   12609      *
   12610      * @return The left edge of this view, in pixels.
   12611      */
   12612     @ViewDebug.CapturedViewProperty
   12613     public final int getLeft() {
   12614         return mLeft;
   12615     }
   12616 
   12617     /**
   12618      * Sets the left position of this view relative to its parent. This method is meant to be called
   12619      * by the layout system and should not generally be called otherwise, because the property
   12620      * may be changed at any time by the layout.
   12621      *
   12622      * @param left The left of this view, in pixels.
   12623      */
   12624     public final void setLeft(int left) {
   12625         if (left != mLeft) {
   12626             final boolean matrixIsIdentity = hasIdentityMatrix();
   12627             if (matrixIsIdentity) {
   12628                 if (mAttachInfo != null) {
   12629                     int minLeft;
   12630                     int xLoc;
   12631                     if (left < mLeft) {
   12632                         minLeft = left;
   12633                         xLoc = left - mLeft;
   12634                     } else {
   12635                         minLeft = mLeft;
   12636                         xLoc = 0;
   12637                     }
   12638                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
   12639                 }
   12640             } else {
   12641                 // Double-invalidation is necessary to capture view's old and new areas
   12642                 invalidate(true);
   12643             }
   12644 
   12645             int oldWidth = mRight - mLeft;
   12646             int height = mBottom - mTop;
   12647 
   12648             mLeft = left;
   12649             mRenderNode.setLeft(left);
   12650 
   12651             sizeChange(mRight - mLeft, height, oldWidth, height);
   12652 
   12653             if (!matrixIsIdentity) {
   12654                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12655                 invalidate(true);
   12656             }
   12657             mBackgroundSizeChanged = true;
   12658             if (mForegroundInfo != null) {
   12659                 mForegroundInfo.mBoundsChanged = true;
   12660             }
   12661             invalidateParentIfNeeded();
   12662             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   12663                 // View was rejected last time it was drawn by its parent; this may have changed
   12664                 invalidateParentIfNeeded();
   12665             }
   12666         }
   12667     }
   12668 
   12669     /**
   12670      * Right position of this view relative to its parent.
   12671      *
   12672      * @return The right edge of this view, in pixels.
   12673      */
   12674     @ViewDebug.CapturedViewProperty
   12675     public final int getRight() {
   12676         return mRight;
   12677     }
   12678 
   12679     /**
   12680      * Sets the right position of this view relative to its parent. This method is meant to be called
   12681      * by the layout system and should not generally be called otherwise, because the property
   12682      * may be changed at any time by the layout.
   12683      *
   12684      * @param right The right of this view, in pixels.
   12685      */
   12686     public final void setRight(int right) {
   12687         if (right != mRight) {
   12688             final boolean matrixIsIdentity = hasIdentityMatrix();
   12689             if (matrixIsIdentity) {
   12690                 if (mAttachInfo != null) {
   12691                     int maxRight;
   12692                     if (right < mRight) {
   12693                         maxRight = mRight;
   12694                     } else {
   12695                         maxRight = right;
   12696                     }
   12697                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
   12698                 }
   12699             } else {
   12700                 // Double-invalidation is necessary to capture view's old and new areas
   12701                 invalidate(true);
   12702             }
   12703 
   12704             int oldWidth = mRight - mLeft;
   12705             int height = mBottom - mTop;
   12706 
   12707             mRight = right;
   12708             mRenderNode.setRight(mRight);
   12709 
   12710             sizeChange(mRight - mLeft, height, oldWidth, height);
   12711 
   12712             if (!matrixIsIdentity) {
   12713                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12714                 invalidate(true);
   12715             }
   12716             mBackgroundSizeChanged = true;
   12717             if (mForegroundInfo != null) {
   12718                 mForegroundInfo.mBoundsChanged = true;
   12719             }
   12720             invalidateParentIfNeeded();
   12721             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   12722                 // View was rejected last time it was drawn by its parent; this may have changed
   12723                 invalidateParentIfNeeded();
   12724             }
   12725         }
   12726     }
   12727 
   12728     /**
   12729      * The visual x position of this view, in pixels. This is equivalent to the
   12730      * {@link #setTranslationX(float) translationX} property plus the current
   12731      * {@link #getLeft() left} property.
   12732      *
   12733      * @return The visual x position of this view, in pixels.
   12734      */
   12735     @ViewDebug.ExportedProperty(category = "drawing")
   12736     public float getX() {
   12737         return mLeft + getTranslationX();
   12738     }
   12739 
   12740     /**
   12741      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
   12742      * {@link #setTranslationX(float) translationX} property to be the difference between
   12743      * the x value passed in and the current {@link #getLeft() left} property.
   12744      *
   12745      * @param x The visual x position of this view, in pixels.
   12746      */
   12747     public void setX(float x) {
   12748         setTranslationX(x - mLeft);
   12749     }
   12750 
   12751     /**
   12752      * The visual y position of this view, in pixels. This is equivalent to the
   12753      * {@link #setTranslationY(float) translationY} property plus the current
   12754      * {@link #getTop() top} property.
   12755      *
   12756      * @return The visual y position of this view, in pixels.
   12757      */
   12758     @ViewDebug.ExportedProperty(category = "drawing")
   12759     public float getY() {
   12760         return mTop + getTranslationY();
   12761     }
   12762 
   12763     /**
   12764      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
   12765      * {@link #setTranslationY(float) translationY} property to be the difference between
   12766      * the y value passed in and the current {@link #getTop() top} property.
   12767      *
   12768      * @param y The visual y position of this view, in pixels.
   12769      */
   12770     public void setY(float y) {
   12771         setTranslationY(y - mTop);
   12772     }
   12773 
   12774     /**
   12775      * The visual z position of this view, in pixels. This is equivalent to the
   12776      * {@link #setTranslationZ(float) translationZ} property plus the current
   12777      * {@link #getElevation() elevation} property.
   12778      *
   12779      * @return The visual z position of this view, in pixels.
   12780      */
   12781     @ViewDebug.ExportedProperty(category = "drawing")
   12782     public float getZ() {
   12783         return getElevation() + getTranslationZ();
   12784     }
   12785 
   12786     /**
   12787      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
   12788      * {@link #setTranslationZ(float) translationZ} property to be the difference between
   12789      * the x value passed in and the current {@link #getElevation() elevation} property.
   12790      *
   12791      * @param z The visual z position of this view, in pixels.
   12792      */
   12793     public void setZ(float z) {
   12794         setTranslationZ(z - getElevation());
   12795     }
   12796 
   12797     /**
   12798      * The base elevation of this view relative to its parent, in pixels.
   12799      *
   12800      * @return The base depth position of the view, in pixels.
   12801      */
   12802     @ViewDebug.ExportedProperty(category = "drawing")
   12803     public float getElevation() {
   12804         return mRenderNode.getElevation();
   12805     }
   12806 
   12807     /**
   12808      * Sets the base elevation of this view, in pixels.
   12809      *
   12810      * @attr ref android.R.styleable#View_elevation
   12811      */
   12812     public void setElevation(float elevation) {
   12813         if (elevation != getElevation()) {
   12814             invalidateViewProperty(true, false);
   12815             mRenderNode.setElevation(elevation);
   12816             invalidateViewProperty(false, true);
   12817 
   12818             invalidateParentIfNeededAndWasQuickRejected();
   12819         }
   12820     }
   12821 
   12822     /**
   12823      * The horizontal location of this view relative to its {@link #getLeft() left} position.
   12824      * This position is post-layout, in addition to wherever the object's
   12825      * layout placed it.
   12826      *
   12827      * @return The horizontal position of this view relative to its left position, in pixels.
   12828      */
   12829     @ViewDebug.ExportedProperty(category = "drawing")
   12830     public float getTranslationX() {
   12831         return mRenderNode.getTranslationX();
   12832     }
   12833 
   12834     /**
   12835      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
   12836      * This effectively positions the object post-layout, in addition to wherever the object's
   12837      * layout placed it.
   12838      *
   12839      * @param translationX The horizontal position of this view relative to its left position,
   12840      * in pixels.
   12841      *
   12842      * @attr ref android.R.styleable#View_translationX
   12843      */
   12844     public void setTranslationX(float translationX) {
   12845         if (translationX != getTranslationX()) {
   12846             invalidateViewProperty(true, false);
   12847             mRenderNode.setTranslationX(translationX);
   12848             invalidateViewProperty(false, true);
   12849 
   12850             invalidateParentIfNeededAndWasQuickRejected();
   12851             notifySubtreeAccessibilityStateChangedIfNeeded();
   12852         }
   12853     }
   12854 
   12855     /**
   12856      * The vertical location of this view relative to its {@link #getTop() top} position.
   12857      * This position is post-layout, in addition to wherever the object's
   12858      * layout placed it.
   12859      *
   12860      * @return The vertical position of this view relative to its top position,
   12861      * in pixels.
   12862      */
   12863     @ViewDebug.ExportedProperty(category = "drawing")
   12864     public float getTranslationY() {
   12865         return mRenderNode.getTranslationY();
   12866     }
   12867 
   12868     /**
   12869      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
   12870      * This effectively positions the object post-layout, in addition to wherever the object's
   12871      * layout placed it.
   12872      *
   12873      * @param translationY The vertical position of this view relative to its top position,
   12874      * in pixels.
   12875      *
   12876      * @attr ref android.R.styleable#View_translationY
   12877      */
   12878     public void setTranslationY(float translationY) {
   12879         if (translationY != getTranslationY()) {
   12880             invalidateViewProperty(true, false);
   12881             mRenderNode.setTranslationY(translationY);
   12882             invalidateViewProperty(false, true);
   12883 
   12884             invalidateParentIfNeededAndWasQuickRejected();
   12885             notifySubtreeAccessibilityStateChangedIfNeeded();
   12886         }
   12887     }
   12888 
   12889     /**
   12890      * The depth location of this view relative to its {@link #getElevation() elevation}.
   12891      *
   12892      * @return The depth of this view relative to its elevation.
   12893      */
   12894     @ViewDebug.ExportedProperty(category = "drawing")
   12895     public float getTranslationZ() {
   12896         return mRenderNode.getTranslationZ();
   12897     }
   12898 
   12899     /**
   12900      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
   12901      *
   12902      * @attr ref android.R.styleable#View_translationZ
   12903      */
   12904     public void setTranslationZ(float translationZ) {
   12905         if (translationZ != getTranslationZ()) {
   12906             invalidateViewProperty(true, false);
   12907             mRenderNode.setTranslationZ(translationZ);
   12908             invalidateViewProperty(false, true);
   12909 
   12910             invalidateParentIfNeededAndWasQuickRejected();
   12911         }
   12912     }
   12913 
   12914     /** @hide */
   12915     public void setAnimationMatrix(Matrix matrix) {
   12916         invalidateViewProperty(true, false);
   12917         mRenderNode.setAnimationMatrix(matrix);
   12918         invalidateViewProperty(false, true);
   12919 
   12920         invalidateParentIfNeededAndWasQuickRejected();
   12921     }
   12922 
   12923     /**
   12924      * Returns the current StateListAnimator if exists.
   12925      *
   12926      * @return StateListAnimator or null if it does not exists
   12927      * @see    #setStateListAnimator(android.animation.StateListAnimator)
   12928      */
   12929     public StateListAnimator getStateListAnimator() {
   12930         return mStateListAnimator;
   12931     }
   12932 
   12933     /**
   12934      * Attaches the provided StateListAnimator to this View.
   12935      * <p>
   12936      * Any previously attached StateListAnimator will be detached.
   12937      *
   12938      * @param stateListAnimator The StateListAnimator to update the view
   12939      * @see {@link android.animation.StateListAnimator}
   12940      */
   12941     public void setStateListAnimator(StateListAnimator stateListAnimator) {
   12942         if (mStateListAnimator == stateListAnimator) {
   12943             return;
   12944         }
   12945         if (mStateListAnimator != null) {
   12946             mStateListAnimator.setTarget(null);
   12947         }
   12948         mStateListAnimator = stateListAnimator;
   12949         if (stateListAnimator != null) {
   12950             stateListAnimator.setTarget(this);
   12951             if (isAttachedToWindow()) {
   12952                 stateListAnimator.setState(getDrawableState());
   12953             }
   12954         }
   12955     }
   12956 
   12957     /**
   12958      * Returns whether the Outline should be used to clip the contents of the View.
   12959      * <p>
   12960      * Note that this flag will only be respected if the View's Outline returns true from
   12961      * {@link Outline#canClip()}.
   12962      *
   12963      * @see #setOutlineProvider(ViewOutlineProvider)
   12964      * @see #setClipToOutline(boolean)
   12965      */
   12966     public final boolean getClipToOutline() {
   12967         return mRenderNode.getClipToOutline();
   12968     }
   12969 
   12970     /**
   12971      * Sets whether the View's Outline should be used to clip the contents of the View.
   12972      * <p>
   12973      * Only a single non-rectangular clip can be applied on a View at any time.
   12974      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
   12975      * circular reveal} animation take priority over Outline clipping, and
   12976      * child Outline clipping takes priority over Outline clipping done by a
   12977      * parent.
   12978      * <p>
   12979      * Note that this flag will only be respected if the View's Outline returns true from
   12980      * {@link Outline#canClip()}.
   12981      *
   12982      * @see #setOutlineProvider(ViewOutlineProvider)
   12983      * @see #getClipToOutline()
   12984      */
   12985     public void setClipToOutline(boolean clipToOutline) {
   12986         damageInParent();
   12987         if (getClipToOutline() != clipToOutline) {
   12988             mRenderNode.setClipToOutline(clipToOutline);
   12989         }
   12990     }
   12991 
   12992     // correspond to the enum values of View_outlineProvider
   12993     private static final int PROVIDER_BACKGROUND = 0;
   12994     private static final int PROVIDER_NONE = 1;
   12995     private static final int PROVIDER_BOUNDS = 2;
   12996     private static final int PROVIDER_PADDED_BOUNDS = 3;
   12997     private void setOutlineProviderFromAttribute(int providerInt) {
   12998         switch (providerInt) {
   12999             case PROVIDER_BACKGROUND:
   13000                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
   13001                 break;
   13002             case PROVIDER_NONE:
   13003                 setOutlineProvider(null);
   13004                 break;
   13005             case PROVIDER_BOUNDS:
   13006                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
   13007                 break;
   13008             case PROVIDER_PADDED_BOUNDS:
   13009                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
   13010                 break;
   13011         }
   13012     }
   13013 
   13014     /**
   13015      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
   13016      * the shape of the shadow it casts, and enables outline clipping.
   13017      * <p>
   13018      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
   13019      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
   13020      * outline provider with this method allows this behavior to be overridden.
   13021      * <p>
   13022      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
   13023      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
   13024      * <p>
   13025      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
   13026      *
   13027      * @see #setClipToOutline(boolean)
   13028      * @see #getClipToOutline()
   13029      * @see #getOutlineProvider()
   13030      */
   13031     public void setOutlineProvider(ViewOutlineProvider provider) {
   13032         mOutlineProvider = provider;
   13033         invalidateOutline();
   13034     }
   13035 
   13036     /**
   13037      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
   13038      * that defines the shape of the shadow it casts, and enables outline clipping.
   13039      *
   13040      * @see #setOutlineProvider(ViewOutlineProvider)
   13041      */
   13042     public ViewOutlineProvider getOutlineProvider() {
   13043         return mOutlineProvider;
   13044     }
   13045 
   13046     /**
   13047      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
   13048      *
   13049      * @see #setOutlineProvider(ViewOutlineProvider)
   13050      */
   13051     public void invalidateOutline() {
   13052         rebuildOutline();
   13053 
   13054         notifySubtreeAccessibilityStateChangedIfNeeded();
   13055         invalidateViewProperty(false, false);
   13056     }
   13057 
   13058     /**
   13059      * Internal version of {@link #invalidateOutline()} which invalidates the
   13060      * outline without invalidating the view itself. This is intended to be called from
   13061      * within methods in the View class itself which are the result of the view being
   13062      * invalidated already. For example, when we are drawing the background of a View,
   13063      * we invalidate the outline in case it changed in the meantime, but we do not
   13064      * need to invalidate the view because we're already drawing the background as part
   13065      * of drawing the view in response to an earlier invalidation of the view.
   13066      */
   13067     private void rebuildOutline() {
   13068         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
   13069         if (mAttachInfo == null) return;
   13070 
   13071         if (mOutlineProvider == null) {
   13072             // no provider, remove outline
   13073             mRenderNode.setOutline(null);
   13074         } else {
   13075             final Outline outline = mAttachInfo.mTmpOutline;
   13076             outline.setEmpty();
   13077             outline.setAlpha(1.0f);
   13078 
   13079             mOutlineProvider.getOutline(this, outline);
   13080             mRenderNode.setOutline(outline);
   13081         }
   13082     }
   13083 
   13084     /**
   13085      * HierarchyViewer only
   13086      *
   13087      * @hide
   13088      */
   13089     @ViewDebug.ExportedProperty(category = "drawing")
   13090     public boolean hasShadow() {
   13091         return mRenderNode.hasShadow();
   13092     }
   13093 
   13094 
   13095     /** @hide */
   13096     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
   13097         mRenderNode.setRevealClip(shouldClip, x, y, radius);
   13098         invalidateViewProperty(false, false);
   13099     }
   13100 
   13101     /**
   13102      * Hit rectangle in parent's coordinates
   13103      *
   13104      * @param outRect The hit rectangle of the view.
   13105      */
   13106     public void getHitRect(Rect outRect) {
   13107         if (hasIdentityMatrix() || mAttachInfo == null) {
   13108             outRect.set(mLeft, mTop, mRight, mBottom);
   13109         } else {
   13110             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
   13111             tmpRect.set(0, 0, getWidth(), getHeight());
   13112             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
   13113             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
   13114                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
   13115         }
   13116     }
   13117 
   13118     /**
   13119      * Determines whether the given point, in local coordinates is inside the view.
   13120      */
   13121     /*package*/ final boolean pointInView(float localX, float localY) {
   13122         return pointInView(localX, localY, 0);
   13123     }
   13124 
   13125     /**
   13126      * Utility method to determine whether the given point, in local coordinates,
   13127      * is inside the view, where the area of the view is expanded by the slop factor.
   13128      * This method is called while processing touch-move events to determine if the event
   13129      * is still within the view.
   13130      *
   13131      * @hide
   13132      */
   13133     public boolean pointInView(float localX, float localY, float slop) {
   13134         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
   13135                 localY < ((mBottom - mTop) + slop);
   13136     }
   13137 
   13138     /**
   13139      * When a view has focus and the user navigates away from it, the next view is searched for
   13140      * starting from the rectangle filled in by this method.
   13141      *
   13142      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
   13143      * of the view.  However, if your view maintains some idea of internal selection,
   13144      * such as a cursor, or a selected row or column, you should override this method and
   13145      * fill in a more specific rectangle.
   13146      *
   13147      * @param r The rectangle to fill in, in this view's coordinates.
   13148      */
   13149     public void getFocusedRect(Rect r) {
   13150         getDrawingRect(r);
   13151     }
   13152 
   13153     /**
   13154      * If some part of this view is not clipped by any of its parents, then
   13155      * return that area in r in global (root) coordinates. To convert r to local
   13156      * coordinates (without taking possible View rotations into account), offset
   13157      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
   13158      * If the view is completely clipped or translated out, return false.
   13159      *
   13160      * @param r If true is returned, r holds the global coordinates of the
   13161      *        visible portion of this view.
   13162      * @param globalOffset If true is returned, globalOffset holds the dx,dy
   13163      *        between this view and its root. globalOffet may be null.
   13164      * @return true if r is non-empty (i.e. part of the view is visible at the
   13165      *         root level.
   13166      */
   13167     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
   13168         int width = mRight - mLeft;
   13169         int height = mBottom - mTop;
   13170         if (width > 0 && height > 0) {
   13171             r.set(0, 0, width, height);
   13172             if (globalOffset != null) {
   13173                 globalOffset.set(-mScrollX, -mScrollY);
   13174             }
   13175             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
   13176         }
   13177         return false;
   13178     }
   13179 
   13180     public final boolean getGlobalVisibleRect(Rect r) {
   13181         return getGlobalVisibleRect(r, null);
   13182     }
   13183 
   13184     public final boolean getLocalVisibleRect(Rect r) {
   13185         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
   13186         if (getGlobalVisibleRect(r, offset)) {
   13187             r.offset(-offset.x, -offset.y); // make r local
   13188             return true;
   13189         }
   13190         return false;
   13191     }
   13192 
   13193     /**
   13194      * Offset this view's vertical location by the specified number of pixels.
   13195      *
   13196      * @param offset the number of pixels to offset the view by
   13197      */
   13198     public void offsetTopAndBottom(int offset) {
   13199         if (offset != 0) {
   13200             final boolean matrixIsIdentity = hasIdentityMatrix();
   13201             if (matrixIsIdentity) {
   13202                 if (isHardwareAccelerated()) {
   13203                     invalidateViewProperty(false, false);
   13204                 } else {
   13205                     final ViewParent p = mParent;
   13206                     if (p != null && mAttachInfo != null) {
   13207                         final Rect r = mAttachInfo.mTmpInvalRect;
   13208                         int minTop;
   13209                         int maxBottom;
   13210                         int yLoc;
   13211                         if (offset < 0) {
   13212                             minTop = mTop + offset;
   13213                             maxBottom = mBottom;
   13214                             yLoc = offset;
   13215                         } else {
   13216                             minTop = mTop;
   13217                             maxBottom = mBottom + offset;
   13218                             yLoc = 0;
   13219                         }
   13220                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
   13221                         p.invalidateChild(this, r);
   13222                     }
   13223                 }
   13224             } else {
   13225                 invalidateViewProperty(false, false);
   13226             }
   13227 
   13228             mTop += offset;
   13229             mBottom += offset;
   13230             mRenderNode.offsetTopAndBottom(offset);
   13231             if (isHardwareAccelerated()) {
   13232                 invalidateViewProperty(false, false);
   13233                 invalidateParentIfNeededAndWasQuickRejected();
   13234             } else {
   13235                 if (!matrixIsIdentity) {
   13236                     invalidateViewProperty(false, true);
   13237                 }
   13238                 invalidateParentIfNeeded();
   13239             }
   13240             notifySubtreeAccessibilityStateChangedIfNeeded();
   13241         }
   13242     }
   13243 
   13244     /**
   13245      * Offset this view's horizontal location by the specified amount of pixels.
   13246      *
   13247      * @param offset the number of pixels to offset the view by
   13248      */
   13249     public void offsetLeftAndRight(int offset) {
   13250         if (offset != 0) {
   13251             final boolean matrixIsIdentity = hasIdentityMatrix();
   13252             if (matrixIsIdentity) {
   13253                 if (isHardwareAccelerated()) {
   13254                     invalidateViewProperty(false, false);
   13255                 } else {
   13256                     final ViewParent p = mParent;
   13257                     if (p != null && mAttachInfo != null) {
   13258                         final Rect r = mAttachInfo.mTmpInvalRect;
   13259                         int minLeft;
   13260                         int maxRight;
   13261                         if (offset < 0) {
   13262                             minLeft = mLeft + offset;
   13263                             maxRight = mRight;
   13264                         } else {
   13265                             minLeft = mLeft;
   13266                             maxRight = mRight + offset;
   13267                         }
   13268                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
   13269                         p.invalidateChild(this, r);
   13270                     }
   13271                 }
   13272             } else {
   13273                 invalidateViewProperty(false, false);
   13274             }
   13275 
   13276             mLeft += offset;
   13277             mRight += offset;
   13278             mRenderNode.offsetLeftAndRight(offset);
   13279             if (isHardwareAccelerated()) {
   13280                 invalidateViewProperty(false, false);
   13281                 invalidateParentIfNeededAndWasQuickRejected();
   13282             } else {
   13283                 if (!matrixIsIdentity) {
   13284                     invalidateViewProperty(false, true);
   13285                 }
   13286                 invalidateParentIfNeeded();
   13287             }
   13288             notifySubtreeAccessibilityStateChangedIfNeeded();
   13289         }
   13290     }
   13291 
   13292     /**
   13293      * Get the LayoutParams associated with this view. All views should have
   13294      * layout parameters. These supply parameters to the <i>parent</i> of this
   13295      * view specifying how it should be arranged. There are many subclasses of
   13296      * ViewGroup.LayoutParams, and these correspond to the different subclasses
   13297      * of ViewGroup that are responsible for arranging their children.
   13298      *
   13299      * This method may return null if this View is not attached to a parent
   13300      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
   13301      * was not invoked successfully. When a View is attached to a parent
   13302      * ViewGroup, this method must not return null.
   13303      *
   13304      * @return The LayoutParams associated with this view, or null if no
   13305      *         parameters have been set yet
   13306      */
   13307     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
   13308     public ViewGroup.LayoutParams getLayoutParams() {
   13309         return mLayoutParams;
   13310     }
   13311 
   13312     /**
   13313      * Set the layout parameters associated with this view. These supply
   13314      * parameters to the <i>parent</i> of this view specifying how it should be
   13315      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
   13316      * correspond to the different subclasses of ViewGroup that are responsible
   13317      * for arranging their children.
   13318      *
   13319      * @param params The layout parameters for this view, cannot be null
   13320      */
   13321     public void setLayoutParams(ViewGroup.LayoutParams params) {
   13322         if (params == null) {
   13323             throw new NullPointerException("Layout parameters cannot be null");
   13324         }
   13325         mLayoutParams = params;
   13326         resolveLayoutParams();
   13327         if (mParent instanceof ViewGroup) {
   13328             ((ViewGroup) mParent).onSetLayoutParams(this, params);
   13329         }
   13330         requestLayout();
   13331     }
   13332 
   13333     /**
   13334      * Resolve the layout parameters depending on the resolved layout direction
   13335      *
   13336      * @hide
   13337      */
   13338     public void resolveLayoutParams() {
   13339         if (mLayoutParams != null) {
   13340             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
   13341         }
   13342     }
   13343 
   13344     /**
   13345      * Set the scrolled position of your view. This will cause a call to
   13346      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   13347      * invalidated.
   13348      * @param x the x position to scroll to
   13349      * @param y the y position to scroll to
   13350      */
   13351     public void scrollTo(int x, int y) {
   13352         if (mScrollX != x || mScrollY != y) {
   13353             int oldX = mScrollX;
   13354             int oldY = mScrollY;
   13355             mScrollX = x;
   13356             mScrollY = y;
   13357             invalidateParentCaches();
   13358             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
   13359             if (!awakenScrollBars()) {
   13360                 postInvalidateOnAnimation();
   13361             }
   13362         }
   13363     }
   13364 
   13365     /**
   13366      * Move the scrolled position of your view. This will cause a call to
   13367      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   13368      * invalidated.
   13369      * @param x the amount of pixels to scroll by horizontally
   13370      * @param y the amount of pixels to scroll by vertically
   13371      */
   13372     public void scrollBy(int x, int y) {
   13373         scrollTo(mScrollX + x, mScrollY + y);
   13374     }
   13375 
   13376     /**
   13377      * <p>Trigger the scrollbars to draw. When invoked this method starts an
   13378      * animation to fade the scrollbars out after a default delay. If a subclass
   13379      * provides animated scrolling, the start delay should equal the duration
   13380      * of the scrolling animation.</p>
   13381      *
   13382      * <p>The animation starts only if at least one of the scrollbars is
   13383      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
   13384      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   13385      * this method returns true, and false otherwise. If the animation is
   13386      * started, this method calls {@link #invalidate()}; in that case the
   13387      * caller should not call {@link #invalidate()}.</p>
   13388      *
   13389      * <p>This method should be invoked every time a subclass directly updates
   13390      * the scroll parameters.</p>
   13391      *
   13392      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
   13393      * and {@link #scrollTo(int, int)}.</p>
   13394      *
   13395      * @return true if the animation is played, false otherwise
   13396      *
   13397      * @see #awakenScrollBars(int)
   13398      * @see #scrollBy(int, int)
   13399      * @see #scrollTo(int, int)
   13400      * @see #isHorizontalScrollBarEnabled()
   13401      * @see #isVerticalScrollBarEnabled()
   13402      * @see #setHorizontalScrollBarEnabled(boolean)
   13403      * @see #setVerticalScrollBarEnabled(boolean)
   13404      */
   13405     protected boolean awakenScrollBars() {
   13406         return mScrollCache != null &&
   13407                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
   13408     }
   13409 
   13410     /**
   13411      * Trigger the scrollbars to draw.
   13412      * This method differs from awakenScrollBars() only in its default duration.
   13413      * initialAwakenScrollBars() will show the scroll bars for longer than
   13414      * usual to give the user more of a chance to notice them.
   13415      *
   13416      * @return true if the animation is played, false otherwise.
   13417      */
   13418     private boolean initialAwakenScrollBars() {
   13419         return mScrollCache != null &&
   13420                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
   13421     }
   13422 
   13423     /**
   13424      * <p>
   13425      * Trigger the scrollbars to draw. When invoked this method starts an
   13426      * animation to fade the scrollbars out after a fixed delay. If a subclass
   13427      * provides animated scrolling, the start delay should equal the duration of
   13428      * the scrolling animation.
   13429      * </p>
   13430      *
   13431      * <p>
   13432      * The animation starts only if at least one of the scrollbars is enabled,
   13433      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   13434      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   13435      * this method returns true, and false otherwise. If the animation is
   13436      * started, this method calls {@link #invalidate()}; in that case the caller
   13437      * should not call {@link #invalidate()}.
   13438      * </p>
   13439      *
   13440      * <p>
   13441      * This method should be invoked every time a subclass directly updates the
   13442      * scroll parameters.
   13443      * </p>
   13444      *
   13445      * @param startDelay the delay, in milliseconds, after which the animation
   13446      *        should start; when the delay is 0, the animation starts
   13447      *        immediately
   13448      * @return true if the animation is played, false otherwise
   13449      *
   13450      * @see #scrollBy(int, int)
   13451      * @see #scrollTo(int, int)
   13452      * @see #isHorizontalScrollBarEnabled()
   13453      * @see #isVerticalScrollBarEnabled()
   13454      * @see #setHorizontalScrollBarEnabled(boolean)
   13455      * @see #setVerticalScrollBarEnabled(boolean)
   13456      */
   13457     protected boolean awakenScrollBars(int startDelay) {
   13458         return awakenScrollBars(startDelay, true);
   13459     }
   13460 
   13461     /**
   13462      * <p>
   13463      * Trigger the scrollbars to draw. When invoked this method starts an
   13464      * animation to fade the scrollbars out after a fixed delay. If a subclass
   13465      * provides animated scrolling, the start delay should equal the duration of
   13466      * the scrolling animation.
   13467      * </p>
   13468      *
   13469      * <p>
   13470      * The animation starts only if at least one of the scrollbars is enabled,
   13471      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   13472      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   13473      * this method returns true, and false otherwise. If the animation is
   13474      * started, this method calls {@link #invalidate()} if the invalidate parameter
   13475      * is set to true; in that case the caller
   13476      * should not call {@link #invalidate()}.
   13477      * </p>
   13478      *
   13479      * <p>
   13480      * This method should be invoked every time a subclass directly updates the
   13481      * scroll parameters.
   13482      * </p>
   13483      *
   13484      * @param startDelay the delay, in milliseconds, after which the animation
   13485      *        should start; when the delay is 0, the animation starts
   13486      *        immediately
   13487      *
   13488      * @param invalidate Whether this method should call invalidate
   13489      *
   13490      * @return true if the animation is played, false otherwise
   13491      *
   13492      * @see #scrollBy(int, int)
   13493      * @see #scrollTo(int, int)
   13494      * @see #isHorizontalScrollBarEnabled()
   13495      * @see #isVerticalScrollBarEnabled()
   13496      * @see #setHorizontalScrollBarEnabled(boolean)
   13497      * @see #setVerticalScrollBarEnabled(boolean)
   13498      */
   13499     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
   13500         final ScrollabilityCache scrollCache = mScrollCache;
   13501 
   13502         if (scrollCache == null || !scrollCache.fadeScrollBars) {
   13503             return false;
   13504         }
   13505 
   13506         if (scrollCache.scrollBar == null) {
   13507             scrollCache.scrollBar = new ScrollBarDrawable();
   13508             scrollCache.scrollBar.setState(getDrawableState());
   13509             scrollCache.scrollBar.setCallback(this);
   13510         }
   13511 
   13512         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
   13513 
   13514             if (invalidate) {
   13515                 // Invalidate to show the scrollbars
   13516                 postInvalidateOnAnimation();
   13517             }
   13518 
   13519             if (scrollCache.state == ScrollabilityCache.OFF) {
   13520                 // FIXME: this is copied from WindowManagerService.
   13521                 // We should get this value from the system when it
   13522                 // is possible to do so.
   13523                 final int KEY_REPEAT_FIRST_DELAY = 750;
   13524                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
   13525             }
   13526 
   13527             // Tell mScrollCache when we should start fading. This may
   13528             // extend the fade start time if one was already scheduled
   13529             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
   13530             scrollCache.fadeStartTime = fadeStartTime;
   13531             scrollCache.state = ScrollabilityCache.ON;
   13532 
   13533             // Schedule our fader to run, unscheduling any old ones first
   13534             if (mAttachInfo != null) {
   13535                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
   13536                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
   13537             }
   13538 
   13539             return true;
   13540         }
   13541 
   13542         return false;
   13543     }
   13544 
   13545     /**
   13546      * Do not invalidate views which are not visible and which are not running an animation. They
   13547      * will not get drawn and they should not set dirty flags as if they will be drawn
   13548      */
   13549     private boolean skipInvalidate() {
   13550         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
   13551                 (!(mParent instanceof ViewGroup) ||
   13552                         !((ViewGroup) mParent).isViewTransitioning(this));
   13553     }
   13554 
   13555     /**
   13556      * Mark the area defined by dirty as needing to be drawn. If the view is
   13557      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   13558      * point in the future.
   13559      * <p>
   13560      * This must be called from a UI thread. To call from a non-UI thread, call
   13561      * {@link #postInvalidate()}.
   13562      * <p>
   13563      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
   13564      * {@code dirty}.
   13565      *
   13566      * @param dirty the rectangle representing the bounds of the dirty region
   13567      */
   13568     public void invalidate(Rect dirty) {
   13569         final int scrollX = mScrollX;
   13570         final int scrollY = mScrollY;
   13571         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
   13572                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
   13573     }
   13574 
   13575     /**
   13576      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
   13577      * coordinates of the dirty rect are relative to the view. If the view is
   13578      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   13579      * point in the future.
   13580      * <p>
   13581      * This must be called from a UI thread. To call from a non-UI thread, call
   13582      * {@link #postInvalidate()}.
   13583      *
   13584      * @param l the left position of the dirty region
   13585      * @param t the top position of the dirty region
   13586      * @param r the right position of the dirty region
   13587      * @param b the bottom position of the dirty region
   13588      */
   13589     public void invalidate(int l, int t, int r, int b) {
   13590         final int scrollX = mScrollX;
   13591         final int scrollY = mScrollY;
   13592         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
   13593     }
   13594 
   13595     /**
   13596      * Invalidate the whole view. If the view is visible,
   13597      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
   13598      * the future.
   13599      * <p>
   13600      * This must be called from a UI thread. To call from a non-UI thread, call
   13601      * {@link #postInvalidate()}.
   13602      */
   13603     public void invalidate() {
   13604         invalidate(true);
   13605     }
   13606 
   13607     /**
   13608      * This is where the invalidate() work actually happens. A full invalidate()
   13609      * causes the drawing cache to be invalidated, but this function can be
   13610      * called with invalidateCache set to false to skip that invalidation step
   13611      * for cases that do not need it (for example, a component that remains at
   13612      * the same dimensions with the same content).
   13613      *
   13614      * @param invalidateCache Whether the drawing cache for this view should be
   13615      *            invalidated as well. This is usually true for a full
   13616      *            invalidate, but may be set to false if the View's contents or
   13617      *            dimensions have not changed.
   13618      */
   13619     void invalidate(boolean invalidateCache) {
   13620         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
   13621     }
   13622 
   13623     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
   13624             boolean fullInvalidate) {
   13625         if (mGhostView != null) {
   13626             mGhostView.invalidate(true);
   13627             return;
   13628         }
   13629 
   13630         if (skipInvalidate()) {
   13631             return;
   13632         }
   13633 
   13634         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
   13635                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
   13636                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
   13637                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
   13638             if (fullInvalidate) {
   13639                 mLastIsOpaque = isOpaque();
   13640                 mPrivateFlags &= ~PFLAG_DRAWN;
   13641             }
   13642 
   13643             mPrivateFlags |= PFLAG_DIRTY;
   13644 
   13645             if (invalidateCache) {
   13646                 mPrivateFlags |= PFLAG_INVALIDATED;
   13647                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   13648             }
   13649 
   13650             // Propagate the damage rectangle to the parent view.
   13651             final AttachInfo ai = mAttachInfo;
   13652             final ViewParent p = mParent;
   13653             if (p != null && ai != null && l < r && t < b) {
   13654                 final Rect damage = ai.mTmpInvalRect;
   13655                 damage.set(l, t, r, b);
   13656                 p.invalidateChild(this, damage);
   13657             }
   13658 
   13659             // Damage the entire projection receiver, if necessary.
   13660             if (mBackground != null && mBackground.isProjected()) {
   13661                 final View receiver = getProjectionReceiver();
   13662                 if (receiver != null) {
   13663                     receiver.damageInParent();
   13664                 }
   13665             }
   13666 
   13667             // Damage the entire IsolatedZVolume receiving this view's shadow.
   13668             if (isHardwareAccelerated() && getZ() != 0) {
   13669                 damageShadowReceiver();
   13670             }
   13671         }
   13672     }
   13673 
   13674     /**
   13675      * @return this view's projection receiver, or {@code null} if none exists
   13676      */
   13677     private View getProjectionReceiver() {
   13678         ViewParent p = getParent();
   13679         while (p != null && p instanceof View) {
   13680             final View v = (View) p;
   13681             if (v.isProjectionReceiver()) {
   13682                 return v;
   13683             }
   13684             p = p.getParent();
   13685         }
   13686 
   13687         return null;
   13688     }
   13689 
   13690     /**
   13691      * @return whether the view is a projection receiver
   13692      */
   13693     private boolean isProjectionReceiver() {
   13694         return mBackground != null;
   13695     }
   13696 
   13697     /**
   13698      * Damage area of the screen that can be covered by this View's shadow.
   13699      *
   13700      * This method will guarantee that any changes to shadows cast by a View
   13701      * are damaged on the screen for future redraw.
   13702      */
   13703     private void damageShadowReceiver() {
   13704         final AttachInfo ai = mAttachInfo;
   13705         if (ai != null) {
   13706             ViewParent p = getParent();
   13707             if (p != null && p instanceof ViewGroup) {
   13708                 final ViewGroup vg = (ViewGroup) p;
   13709                 vg.damageInParent();
   13710             }
   13711         }
   13712     }
   13713 
   13714     /**
   13715      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
   13716      * set any flags or handle all of the cases handled by the default invalidation methods.
   13717      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
   13718      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
   13719      * walk up the hierarchy, transforming the dirty rect as necessary.
   13720      *
   13721      * The method also handles normal invalidation logic if display list properties are not
   13722      * being used in this view. The invalidateParent and forceRedraw flags are used by that
   13723      * backup approach, to handle these cases used in the various property-setting methods.
   13724      *
   13725      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
   13726      * are not being used in this view
   13727      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
   13728      * list properties are not being used in this view
   13729      */
   13730     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
   13731         if (!isHardwareAccelerated()
   13732                 || !mRenderNode.isValid()
   13733                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
   13734             if (invalidateParent) {
   13735                 invalidateParentCaches();
   13736             }
   13737             if (forceRedraw) {
   13738                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   13739             }
   13740             invalidate(false);
   13741         } else {
   13742             damageInParent();
   13743         }
   13744         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
   13745             damageShadowReceiver();
   13746         }
   13747     }
   13748 
   13749     /**
   13750      * Tells the parent view to damage this view's bounds.
   13751      *
   13752      * @hide
   13753      */
   13754     protected void damageInParent() {
   13755         final AttachInfo ai = mAttachInfo;
   13756         final ViewParent p = mParent;
   13757         if (p != null && ai != null) {
   13758             final Rect r = ai.mTmpInvalRect;
   13759             r.set(0, 0, mRight - mLeft, mBottom - mTop);
   13760             if (mParent instanceof ViewGroup) {
   13761                 ((ViewGroup) mParent).damageChild(this, r);
   13762             } else {
   13763                 mParent.invalidateChild(this, r);
   13764             }
   13765         }
   13766     }
   13767 
   13768     /**
   13769      * Utility method to transform a given Rect by the current matrix of this view.
   13770      */
   13771     void transformRect(final Rect rect) {
   13772         if (!getMatrix().isIdentity()) {
   13773             RectF boundingRect = mAttachInfo.mTmpTransformRect;
   13774             boundingRect.set(rect);
   13775             getMatrix().mapRect(boundingRect);
   13776             rect.set((int) Math.floor(boundingRect.left),
   13777                     (int) Math.floor(boundingRect.top),
   13778                     (int) Math.ceil(boundingRect.right),
   13779                     (int) Math.ceil(boundingRect.bottom));
   13780         }
   13781     }
   13782 
   13783     /**
   13784      * Used to indicate that the parent of this view should clear its caches. This functionality
   13785      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   13786      * which is necessary when various parent-managed properties of the view change, such as
   13787      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
   13788      * clears the parent caches and does not causes an invalidate event.
   13789      *
   13790      * @hide
   13791      */
   13792     protected void invalidateParentCaches() {
   13793         if (mParent instanceof View) {
   13794             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
   13795         }
   13796     }
   13797 
   13798     /**
   13799      * Used to indicate that the parent of this view should be invalidated. This functionality
   13800      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   13801      * which is necessary when various parent-managed properties of the view change, such as
   13802      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
   13803      * an invalidation event to the parent.
   13804      *
   13805      * @hide
   13806      */
   13807     protected void invalidateParentIfNeeded() {
   13808         if (isHardwareAccelerated() && mParent instanceof View) {
   13809             ((View) mParent).invalidate(true);
   13810         }
   13811     }
   13812 
   13813     /**
   13814      * @hide
   13815      */
   13816     protected void invalidateParentIfNeededAndWasQuickRejected() {
   13817         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
   13818             // View was rejected last time it was drawn by its parent; this may have changed
   13819             invalidateParentIfNeeded();
   13820         }
   13821     }
   13822 
   13823     /**
   13824      * Indicates whether this View is opaque. An opaque View guarantees that it will
   13825      * draw all the pixels overlapping its bounds using a fully opaque color.
   13826      *
   13827      * Subclasses of View should override this method whenever possible to indicate
   13828      * whether an instance is opaque. Opaque Views are treated in a special way by
   13829      * the View hierarchy, possibly allowing it to perform optimizations during
   13830      * invalidate/draw passes.
   13831      *
   13832      * @return True if this View is guaranteed to be fully opaque, false otherwise.
   13833      */
   13834     @ViewDebug.ExportedProperty(category = "drawing")
   13835     public boolean isOpaque() {
   13836         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
   13837                 getFinalAlpha() >= 1.0f;
   13838     }
   13839 
   13840     /**
   13841      * @hide
   13842      */
   13843     protected void computeOpaqueFlags() {
   13844         // Opaque if:
   13845         //   - Has a background
   13846         //   - Background is opaque
   13847         //   - Doesn't have scrollbars or scrollbars overlay
   13848 
   13849         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
   13850             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
   13851         } else {
   13852             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
   13853         }
   13854 
   13855         final int flags = mViewFlags;
   13856         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
   13857                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
   13858                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
   13859             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
   13860         } else {
   13861             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
   13862         }
   13863     }
   13864 
   13865     /**
   13866      * @hide
   13867      */
   13868     protected boolean hasOpaqueScrollbars() {
   13869         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
   13870     }
   13871 
   13872     /**
   13873      * @return A handler associated with the thread running the View. This
   13874      * handler can be used to pump events in the UI events queue.
   13875      */
   13876     public Handler getHandler() {
   13877         final AttachInfo attachInfo = mAttachInfo;
   13878         if (attachInfo != null) {
   13879             return attachInfo.mHandler;
   13880         }
   13881         return null;
   13882     }
   13883 
   13884     /**
   13885      * Returns the queue of runnable for this view.
   13886      *
   13887      * @return the queue of runnables for this view
   13888      */
   13889     private HandlerActionQueue getRunQueue() {
   13890         if (mRunQueue == null) {
   13891             mRunQueue = new HandlerActionQueue();
   13892         }
   13893         return mRunQueue;
   13894     }
   13895 
   13896     /**
   13897      * Gets the view root associated with the View.
   13898      * @return The view root, or null if none.
   13899      * @hide
   13900      */
   13901     public ViewRootImpl getViewRootImpl() {
   13902         if (mAttachInfo != null) {
   13903             return mAttachInfo.mViewRootImpl;
   13904         }
   13905         return null;
   13906     }
   13907 
   13908     /**
   13909      * @hide
   13910      */
   13911     public ThreadedRenderer getHardwareRenderer() {
   13912         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
   13913     }
   13914 
   13915     /**
   13916      * <p>Causes the Runnable to be added to the message queue.
   13917      * The runnable will be run on the user interface thread.</p>
   13918      *
   13919      * @param action The Runnable that will be executed.
   13920      *
   13921      * @return Returns true if the Runnable was successfully placed in to the
   13922      *         message queue.  Returns false on failure, usually because the
   13923      *         looper processing the message queue is exiting.
   13924      *
   13925      * @see #postDelayed
   13926      * @see #removeCallbacks
   13927      */
   13928     public boolean post(Runnable action) {
   13929         final AttachInfo attachInfo = mAttachInfo;
   13930         if (attachInfo != null) {
   13931             return attachInfo.mHandler.post(action);
   13932         }
   13933 
   13934         // Postpone the runnable until we know on which thread it needs to run.
   13935         // Assume that the runnable will be successfully placed after attach.
   13936         getRunQueue().post(action);
   13937         return true;
   13938     }
   13939 
   13940     /**
   13941      * <p>Causes the Runnable to be added to the message queue, to be run
   13942      * after the specified amount of time elapses.
   13943      * The runnable will be run on the user interface thread.</p>
   13944      *
   13945      * @param action The Runnable that will be executed.
   13946      * @param delayMillis The delay (in milliseconds) until the Runnable
   13947      *        will be executed.
   13948      *
   13949      * @return true if the Runnable was successfully placed in to the
   13950      *         message queue.  Returns false on failure, usually because the
   13951      *         looper processing the message queue is exiting.  Note that a
   13952      *         result of true does not mean the Runnable will be processed --
   13953      *         if the looper is quit before the delivery time of the message
   13954      *         occurs then the message will be dropped.
   13955      *
   13956      * @see #post
   13957      * @see #removeCallbacks
   13958      */
   13959     public boolean postDelayed(Runnable action, long delayMillis) {
   13960         final AttachInfo attachInfo = mAttachInfo;
   13961         if (attachInfo != null) {
   13962             return attachInfo.mHandler.postDelayed(action, delayMillis);
   13963         }
   13964 
   13965         // Postpone the runnable until we know on which thread it needs to run.
   13966         // Assume that the runnable will be successfully placed after attach.
   13967         getRunQueue().postDelayed(action, delayMillis);
   13968         return true;
   13969     }
   13970 
   13971     /**
   13972      * <p>Causes the Runnable to execute on the next animation time step.
   13973      * The runnable will be run on the user interface thread.</p>
   13974      *
   13975      * @param action The Runnable that will be executed.
   13976      *
   13977      * @see #postOnAnimationDelayed
   13978      * @see #removeCallbacks
   13979      */
   13980     public void postOnAnimation(Runnable action) {
   13981         final AttachInfo attachInfo = mAttachInfo;
   13982         if (attachInfo != null) {
   13983             attachInfo.mViewRootImpl.mChoreographer.postCallback(
   13984                     Choreographer.CALLBACK_ANIMATION, action, null);
   13985         } else {
   13986             // Postpone the runnable until we know
   13987             // on which thread it needs to run.
   13988             getRunQueue().post(action);
   13989         }
   13990     }
   13991 
   13992     /**
   13993      * <p>Causes the Runnable to execute on the next animation time step,
   13994      * after the specified amount of time elapses.
   13995      * The runnable will be run on the user interface thread.</p>
   13996      *
   13997      * @param action The Runnable that will be executed.
   13998      * @param delayMillis The delay (in milliseconds) until the Runnable
   13999      *        will be executed.
   14000      *
   14001      * @see #postOnAnimation
   14002      * @see #removeCallbacks
   14003      */
   14004     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
   14005         final AttachInfo attachInfo = mAttachInfo;
   14006         if (attachInfo != null) {
   14007             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   14008                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
   14009         } else {
   14010             // Postpone the runnable until we know
   14011             // on which thread it needs to run.
   14012             getRunQueue().postDelayed(action, delayMillis);
   14013         }
   14014     }
   14015 
   14016     /**
   14017      * <p>Removes the specified Runnable from the message queue.</p>
   14018      *
   14019      * @param action The Runnable to remove from the message handling queue
   14020      *
   14021      * @return true if this view could ask the Handler to remove the Runnable,
   14022      *         false otherwise. When the returned value is true, the Runnable
   14023      *         may or may not have been actually removed from the message queue
   14024      *         (for instance, if the Runnable was not in the queue already.)
   14025      *
   14026      * @see #post
   14027      * @see #postDelayed
   14028      * @see #postOnAnimation
   14029      * @see #postOnAnimationDelayed
   14030      */
   14031     public boolean removeCallbacks(Runnable action) {
   14032         if (action != null) {
   14033             final AttachInfo attachInfo = mAttachInfo;
   14034             if (attachInfo != null) {
   14035                 attachInfo.mHandler.removeCallbacks(action);
   14036                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   14037                         Choreographer.CALLBACK_ANIMATION, action, null);
   14038             }
   14039             getRunQueue().removeCallbacks(action);
   14040         }
   14041         return true;
   14042     }
   14043 
   14044     /**
   14045      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
   14046      * Use this to invalidate the View from a non-UI thread.</p>
   14047      *
   14048      * <p>This method can be invoked from outside of the UI thread
   14049      * only when this View is attached to a window.</p>
   14050      *
   14051      * @see #invalidate()
   14052      * @see #postInvalidateDelayed(long)
   14053      */
   14054     public void postInvalidate() {
   14055         postInvalidateDelayed(0);
   14056     }
   14057 
   14058     /**
   14059      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   14060      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
   14061      *
   14062      * <p>This method can be invoked from outside of the UI thread
   14063      * only when this View is attached to a window.</p>
   14064      *
   14065      * @param left The left coordinate of the rectangle to invalidate.
   14066      * @param top The top coordinate of the rectangle to invalidate.
   14067      * @param right The right coordinate of the rectangle to invalidate.
   14068      * @param bottom The bottom coordinate of the rectangle to invalidate.
   14069      *
   14070      * @see #invalidate(int, int, int, int)
   14071      * @see #invalidate(Rect)
   14072      * @see #postInvalidateDelayed(long, int, int, int, int)
   14073      */
   14074     public void postInvalidate(int left, int top, int right, int bottom) {
   14075         postInvalidateDelayed(0, left, top, right, bottom);
   14076     }
   14077 
   14078     /**
   14079      * <p>Cause an invalidate to happen on a subsequent cycle through the event
   14080      * loop. Waits for the specified amount of time.</p>
   14081      *
   14082      * <p>This method can be invoked from outside of the UI thread
   14083      * only when this View is attached to a window.</p>
   14084      *
   14085      * @param delayMilliseconds the duration in milliseconds to delay the
   14086      *         invalidation by
   14087      *
   14088      * @see #invalidate()
   14089      * @see #postInvalidate()
   14090      */
   14091     public void postInvalidateDelayed(long delayMilliseconds) {
   14092         // We try only with the AttachInfo because there's no point in invalidating
   14093         // if we are not attached to our window
   14094         final AttachInfo attachInfo = mAttachInfo;
   14095         if (attachInfo != null) {
   14096             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
   14097         }
   14098     }
   14099 
   14100     /**
   14101      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   14102      * through the event loop. Waits for the specified amount of time.</p>
   14103      *
   14104      * <p>This method can be invoked from outside of the UI thread
   14105      * only when this View is attached to a window.</p>
   14106      *
   14107      * @param delayMilliseconds the duration in milliseconds to delay the
   14108      *         invalidation by
   14109      * @param left The left coordinate of the rectangle to invalidate.
   14110      * @param top The top coordinate of the rectangle to invalidate.
   14111      * @param right The right coordinate of the rectangle to invalidate.
   14112      * @param bottom The bottom coordinate of the rectangle to invalidate.
   14113      *
   14114      * @see #invalidate(int, int, int, int)
   14115      * @see #invalidate(Rect)
   14116      * @see #postInvalidate(int, int, int, int)
   14117      */
   14118     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
   14119             int right, int bottom) {
   14120 
   14121         // We try only with the AttachInfo because there's no point in invalidating
   14122         // if we are not attached to our window
   14123         final AttachInfo attachInfo = mAttachInfo;
   14124         if (attachInfo != null) {
   14125             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   14126             info.target = this;
   14127             info.left = left;
   14128             info.top = top;
   14129             info.right = right;
   14130             info.bottom = bottom;
   14131 
   14132             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
   14133         }
   14134     }
   14135 
   14136     /**
   14137      * <p>Cause an invalidate to happen on the next animation time step, typically the
   14138      * next display frame.</p>
   14139      *
   14140      * <p>This method can be invoked from outside of the UI thread
   14141      * only when this View is attached to a window.</p>
   14142      *
   14143      * @see #invalidate()
   14144      */
   14145     public void postInvalidateOnAnimation() {
   14146         // We try only with the AttachInfo because there's no point in invalidating
   14147         // if we are not attached to our window
   14148         final AttachInfo attachInfo = mAttachInfo;
   14149         if (attachInfo != null) {
   14150             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
   14151         }
   14152     }
   14153 
   14154     /**
   14155      * <p>Cause an invalidate of the specified area to happen on the next animation
   14156      * time step, typically the next display frame.</p>
   14157      *
   14158      * <p>This method can be invoked from outside of the UI thread
   14159      * only when this View is attached to a window.</p>
   14160      *
   14161      * @param left The left coordinate of the rectangle to invalidate.
   14162      * @param top The top coordinate of the rectangle to invalidate.
   14163      * @param right The right coordinate of the rectangle to invalidate.
   14164      * @param bottom The bottom coordinate of the rectangle to invalidate.
   14165      *
   14166      * @see #invalidate(int, int, int, int)
   14167      * @see #invalidate(Rect)
   14168      */
   14169     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
   14170         // We try only with the AttachInfo because there's no point in invalidating
   14171         // if we are not attached to our window
   14172         final AttachInfo attachInfo = mAttachInfo;
   14173         if (attachInfo != null) {
   14174             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   14175             info.target = this;
   14176             info.left = left;
   14177             info.top = top;
   14178             info.right = right;
   14179             info.bottom = bottom;
   14180 
   14181             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
   14182         }
   14183     }
   14184 
   14185     /**
   14186      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
   14187      * This event is sent at most once every
   14188      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
   14189      */
   14190     private void postSendViewScrolledAccessibilityEventCallback() {
   14191         if (mSendViewScrolledAccessibilityEvent == null) {
   14192             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
   14193         }
   14194         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
   14195             mSendViewScrolledAccessibilityEvent.mIsPending = true;
   14196             postDelayed(mSendViewScrolledAccessibilityEvent,
   14197                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
   14198         }
   14199     }
   14200 
   14201     /**
   14202      * Called by a parent to request that a child update its values for mScrollX
   14203      * and mScrollY if necessary. This will typically be done if the child is
   14204      * animating a scroll using a {@link android.widget.Scroller Scroller}
   14205      * object.
   14206      */
   14207     public void computeScroll() {
   14208     }
   14209 
   14210     /**
   14211      * <p>Indicate whether the horizontal edges are faded when the view is
   14212      * scrolled horizontally.</p>
   14213      *
   14214      * @return true if the horizontal edges should are faded on scroll, false
   14215      *         otherwise
   14216      *
   14217      * @see #setHorizontalFadingEdgeEnabled(boolean)
   14218      *
   14219      * @attr ref android.R.styleable#View_requiresFadingEdge
   14220      */
   14221     public boolean isHorizontalFadingEdgeEnabled() {
   14222         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
   14223     }
   14224 
   14225     /**
   14226      * <p>Define whether the horizontal edges should be faded when this view
   14227      * is scrolled horizontally.</p>
   14228      *
   14229      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
   14230      *                                    be faded when the view is scrolled
   14231      *                                    horizontally
   14232      *
   14233      * @see #isHorizontalFadingEdgeEnabled()
   14234      *
   14235      * @attr ref android.R.styleable#View_requiresFadingEdge
   14236      */
   14237     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
   14238         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
   14239             if (horizontalFadingEdgeEnabled) {
   14240                 initScrollCache();
   14241             }
   14242 
   14243             mViewFlags ^= FADING_EDGE_HORIZONTAL;
   14244         }
   14245     }
   14246 
   14247     /**
   14248      * <p>Indicate whether the vertical edges are faded when the view is
   14249      * scrolled horizontally.</p>
   14250      *
   14251      * @return true if the vertical edges should are faded on scroll, false
   14252      *         otherwise
   14253      *
   14254      * @see #setVerticalFadingEdgeEnabled(boolean)
   14255      *
   14256      * @attr ref android.R.styleable#View_requiresFadingEdge
   14257      */
   14258     public boolean isVerticalFadingEdgeEnabled() {
   14259         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
   14260     }
   14261 
   14262     /**
   14263      * <p>Define whether the vertical edges should be faded when this view
   14264      * is scrolled vertically.</p>
   14265      *
   14266      * @param verticalFadingEdgeEnabled true if the vertical edges should
   14267      *                                  be faded when the view is scrolled
   14268      *                                  vertically
   14269      *
   14270      * @see #isVerticalFadingEdgeEnabled()
   14271      *
   14272      * @attr ref android.R.styleable#View_requiresFadingEdge
   14273      */
   14274     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
   14275         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
   14276             if (verticalFadingEdgeEnabled) {
   14277                 initScrollCache();
   14278             }
   14279 
   14280             mViewFlags ^= FADING_EDGE_VERTICAL;
   14281         }
   14282     }
   14283 
   14284     /**
   14285      * Returns the strength, or intensity, of the top faded edge. The strength is
   14286      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   14287      * returns 0.0 or 1.0 but no value in between.
   14288      *
   14289      * Subclasses should override this method to provide a smoother fade transition
   14290      * when scrolling occurs.
   14291      *
   14292      * @return the intensity of the top fade as a float between 0.0f and 1.0f
   14293      */
   14294     protected float getTopFadingEdgeStrength() {
   14295         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
   14296     }
   14297 
   14298     /**
   14299      * Returns the strength, or intensity, of the bottom faded edge. The strength is
   14300      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   14301      * returns 0.0 or 1.0 but no value in between.
   14302      *
   14303      * Subclasses should override this method to provide a smoother fade transition
   14304      * when scrolling occurs.
   14305      *
   14306      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
   14307      */
   14308     protected float getBottomFadingEdgeStrength() {
   14309         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
   14310                 computeVerticalScrollRange() ? 1.0f : 0.0f;
   14311     }
   14312 
   14313     /**
   14314      * Returns the strength, or intensity, of the left faded edge. The strength is
   14315      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   14316      * returns 0.0 or 1.0 but no value in between.
   14317      *
   14318      * Subclasses should override this method to provide a smoother fade transition
   14319      * when scrolling occurs.
   14320      *
   14321      * @return the intensity of the left fade as a float between 0.0f and 1.0f
   14322      */
   14323     protected float getLeftFadingEdgeStrength() {
   14324         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
   14325     }
   14326 
   14327     /**
   14328      * Returns the strength, or intensity, of the right faded edge. The strength is
   14329      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   14330      * returns 0.0 or 1.0 but no value in between.
   14331      *
   14332      * Subclasses should override this method to provide a smoother fade transition
   14333      * when scrolling occurs.
   14334      *
   14335      * @return the intensity of the right fade as a float between 0.0f and 1.0f
   14336      */
   14337     protected float getRightFadingEdgeStrength() {
   14338         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
   14339                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
   14340     }
   14341 
   14342     /**
   14343      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
   14344      * scrollbar is not drawn by default.</p>
   14345      *
   14346      * @return true if the horizontal scrollbar should be painted, false
   14347      *         otherwise
   14348      *
   14349      * @see #setHorizontalScrollBarEnabled(boolean)
   14350      */
   14351     public boolean isHorizontalScrollBarEnabled() {
   14352         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   14353     }
   14354 
   14355     /**
   14356      * <p>Define whether the horizontal scrollbar should be drawn or not. The
   14357      * scrollbar is not drawn by default.</p>
   14358      *
   14359      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
   14360      *                                   be painted
   14361      *
   14362      * @see #isHorizontalScrollBarEnabled()
   14363      */
   14364     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
   14365         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
   14366             mViewFlags ^= SCROLLBARS_HORIZONTAL;
   14367             computeOpaqueFlags();
   14368             resolvePadding();
   14369         }
   14370     }
   14371 
   14372     /**
   14373      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
   14374      * scrollbar is not drawn by default.</p>
   14375      *
   14376      * @return true if the vertical scrollbar should be painted, false
   14377      *         otherwise
   14378      *
   14379      * @see #setVerticalScrollBarEnabled(boolean)
   14380      */
   14381     public boolean isVerticalScrollBarEnabled() {
   14382         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
   14383     }
   14384 
   14385     /**
   14386      * <p>Define whether the vertical scrollbar should be drawn or not. The
   14387      * scrollbar is not drawn by default.</p>
   14388      *
   14389      * @param verticalScrollBarEnabled true if the vertical scrollbar should
   14390      *                                 be painted
   14391      *
   14392      * @see #isVerticalScrollBarEnabled()
   14393      */
   14394     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
   14395         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
   14396             mViewFlags ^= SCROLLBARS_VERTICAL;
   14397             computeOpaqueFlags();
   14398             resolvePadding();
   14399         }
   14400     }
   14401 
   14402     /**
   14403      * @hide
   14404      */
   14405     protected void recomputePadding() {
   14406         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   14407     }
   14408 
   14409     /**
   14410      * Define whether scrollbars will fade when the view is not scrolling.
   14411      *
   14412      * @param fadeScrollbars whether to enable fading
   14413      *
   14414      * @attr ref android.R.styleable#View_fadeScrollbars
   14415      */
   14416     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
   14417         initScrollCache();
   14418         final ScrollabilityCache scrollabilityCache = mScrollCache;
   14419         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   14420         if (fadeScrollbars) {
   14421             scrollabilityCache.state = ScrollabilityCache.OFF;
   14422         } else {
   14423             scrollabilityCache.state = ScrollabilityCache.ON;
   14424         }
   14425     }
   14426 
   14427     /**
   14428      *
   14429      * Returns true if scrollbars will fade when this view is not scrolling
   14430      *
   14431      * @return true if scrollbar fading is enabled
   14432      *
   14433      * @attr ref android.R.styleable#View_fadeScrollbars
   14434      */
   14435     public boolean isScrollbarFadingEnabled() {
   14436         return mScrollCache != null && mScrollCache.fadeScrollBars;
   14437     }
   14438 
   14439     /**
   14440      *
   14441      * Returns the delay before scrollbars fade.
   14442      *
   14443      * @return the delay before scrollbars fade
   14444      *
   14445      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   14446      */
   14447     public int getScrollBarDefaultDelayBeforeFade() {
   14448         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
   14449                 mScrollCache.scrollBarDefaultDelayBeforeFade;
   14450     }
   14451 
   14452     /**
   14453      * Define the delay before scrollbars fade.
   14454      *
   14455      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
   14456      *
   14457      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   14458      */
   14459     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
   14460         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
   14461     }
   14462 
   14463     /**
   14464      *
   14465      * Returns the scrollbar fade duration.
   14466      *
   14467      * @return the scrollbar fade duration
   14468      *
   14469      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   14470      */
   14471     public int getScrollBarFadeDuration() {
   14472         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
   14473                 mScrollCache.scrollBarFadeDuration;
   14474     }
   14475 
   14476     /**
   14477      * Define the scrollbar fade duration.
   14478      *
   14479      * @param scrollBarFadeDuration - the scrollbar fade duration
   14480      *
   14481      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   14482      */
   14483     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
   14484         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
   14485     }
   14486 
   14487     /**
   14488      *
   14489      * Returns the scrollbar size.
   14490      *
   14491      * @return the scrollbar size
   14492      *
   14493      * @attr ref android.R.styleable#View_scrollbarSize
   14494      */
   14495     public int getScrollBarSize() {
   14496         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
   14497                 mScrollCache.scrollBarSize;
   14498     }
   14499 
   14500     /**
   14501      * Define the scrollbar size.
   14502      *
   14503      * @param scrollBarSize - the scrollbar size
   14504      *
   14505      * @attr ref android.R.styleable#View_scrollbarSize
   14506      */
   14507     public void setScrollBarSize(int scrollBarSize) {
   14508         getScrollCache().scrollBarSize = scrollBarSize;
   14509     }
   14510 
   14511     /**
   14512      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
   14513      * inset. When inset, they add to the padding of the view. And the scrollbars
   14514      * can be drawn inside the padding area or on the edge of the view. For example,
   14515      * if a view has a background drawable and you want to draw the scrollbars
   14516      * inside the padding specified by the drawable, you can use
   14517      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
   14518      * appear at the edge of the view, ignoring the padding, then you can use
   14519      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
   14520      * @param style the style of the scrollbars. Should be one of
   14521      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
   14522      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
   14523      * @see #SCROLLBARS_INSIDE_OVERLAY
   14524      * @see #SCROLLBARS_INSIDE_INSET
   14525      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   14526      * @see #SCROLLBARS_OUTSIDE_INSET
   14527      *
   14528      * @attr ref android.R.styleable#View_scrollbarStyle
   14529      */
   14530     public void setScrollBarStyle(@ScrollBarStyle int style) {
   14531         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
   14532             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
   14533             computeOpaqueFlags();
   14534             resolvePadding();
   14535         }
   14536     }
   14537 
   14538     /**
   14539      * <p>Returns the current scrollbar style.</p>
   14540      * @return the current scrollbar style
   14541      * @see #SCROLLBARS_INSIDE_OVERLAY
   14542      * @see #SCROLLBARS_INSIDE_INSET
   14543      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   14544      * @see #SCROLLBARS_OUTSIDE_INSET
   14545      *
   14546      * @attr ref android.R.styleable#View_scrollbarStyle
   14547      */
   14548     @ViewDebug.ExportedProperty(mapping = {
   14549             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
   14550             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
   14551             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
   14552             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
   14553     })
   14554     @ScrollBarStyle
   14555     public int getScrollBarStyle() {
   14556         return mViewFlags & SCROLLBARS_STYLE_MASK;
   14557     }
   14558 
   14559     /**
   14560      * <p>Compute the horizontal range that the horizontal scrollbar
   14561      * represents.</p>
   14562      *
   14563      * <p>The range is expressed in arbitrary units that must be the same as the
   14564      * units used by {@link #computeHorizontalScrollExtent()} and
   14565      * {@link #computeHorizontalScrollOffset()}.</p>
   14566      *
   14567      * <p>The default range is the drawing width of this view.</p>
   14568      *
   14569      * @return the total horizontal range represented by the horizontal
   14570      *         scrollbar
   14571      *
   14572      * @see #computeHorizontalScrollExtent()
   14573      * @see #computeHorizontalScrollOffset()
   14574      * @see android.widget.ScrollBarDrawable
   14575      */
   14576     protected int computeHorizontalScrollRange() {
   14577         return getWidth();
   14578     }
   14579 
   14580     /**
   14581      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
   14582      * within the horizontal range. This value is used to compute the position
   14583      * of the thumb within the scrollbar's track.</p>
   14584      *
   14585      * <p>The range is expressed in arbitrary units that must be the same as the
   14586      * units used by {@link #computeHorizontalScrollRange()} and
   14587      * {@link #computeHorizontalScrollExtent()}.</p>
   14588      *
   14589      * <p>The default offset is the scroll offset of this view.</p>
   14590      *
   14591      * @return the horizontal offset of the scrollbar's thumb
   14592      *
   14593      * @see #computeHorizontalScrollRange()
   14594      * @see #computeHorizontalScrollExtent()
   14595      * @see android.widget.ScrollBarDrawable
   14596      */
   14597     protected int computeHorizontalScrollOffset() {
   14598         return mScrollX;
   14599     }
   14600 
   14601     /**
   14602      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
   14603      * within the horizontal range. This value is used to compute the length
   14604      * of the thumb within the scrollbar's track.</p>
   14605      *
   14606      * <p>The range is expressed in arbitrary units that must be the same as the
   14607      * units used by {@link #computeHorizontalScrollRange()} and
   14608      * {@link #computeHorizontalScrollOffset()}.</p>
   14609      *
   14610      * <p>The default extent is the drawing width of this view.</p>
   14611      *
   14612      * @return the horizontal extent of the scrollbar's thumb
   14613      *
   14614      * @see #computeHorizontalScrollRange()
   14615      * @see #computeHorizontalScrollOffset()
   14616      * @see android.widget.ScrollBarDrawable
   14617      */
   14618     protected int computeHorizontalScrollExtent() {
   14619         return getWidth();
   14620     }
   14621 
   14622     /**
   14623      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
   14624      *
   14625      * <p>The range is expressed in arbitrary units that must be the same as the
   14626      * units used by {@link #computeVerticalScrollExtent()} and
   14627      * {@link #computeVerticalScrollOffset()}.</p>
   14628      *
   14629      * @return the total vertical range represented by the vertical scrollbar
   14630      *
   14631      * <p>The default range is the drawing height of this view.</p>
   14632      *
   14633      * @see #computeVerticalScrollExtent()
   14634      * @see #computeVerticalScrollOffset()
   14635      * @see android.widget.ScrollBarDrawable
   14636      */
   14637     protected int computeVerticalScrollRange() {
   14638         return getHeight();
   14639     }
   14640 
   14641     /**
   14642      * <p>Compute the vertical offset of the vertical scrollbar's thumb
   14643      * within the horizontal range. This value is used to compute the position
   14644      * of the thumb within the scrollbar's track.</p>
   14645      *
   14646      * <p>The range is expressed in arbitrary units that must be the same as the
   14647      * units used by {@link #computeVerticalScrollRange()} and
   14648      * {@link #computeVerticalScrollExtent()}.</p>
   14649      *
   14650      * <p>The default offset is the scroll offset of this view.</p>
   14651      *
   14652      * @return the vertical offset of the scrollbar's thumb
   14653      *
   14654      * @see #computeVerticalScrollRange()
   14655      * @see #computeVerticalScrollExtent()
   14656      * @see android.widget.ScrollBarDrawable
   14657      */
   14658     protected int computeVerticalScrollOffset() {
   14659         return mScrollY;
   14660     }
   14661 
   14662     /**
   14663      * <p>Compute the vertical extent of the vertical scrollbar's thumb
   14664      * within the vertical range. This value is used to compute the length
   14665      * of the thumb within the scrollbar's track.</p>
   14666      *
   14667      * <p>The range is expressed in arbitrary units that must be the same as the
   14668      * units used by {@link #computeVerticalScrollRange()} and
   14669      * {@link #computeVerticalScrollOffset()}.</p>
   14670      *
   14671      * <p>The default extent is the drawing height of this view.</p>
   14672      *
   14673      * @return the vertical extent of the scrollbar's thumb
   14674      *
   14675      * @see #computeVerticalScrollRange()
   14676      * @see #computeVerticalScrollOffset()
   14677      * @see android.widget.ScrollBarDrawable
   14678      */
   14679     protected int computeVerticalScrollExtent() {
   14680         return getHeight();
   14681     }
   14682 
   14683     /**
   14684      * Check if this view can be scrolled horizontally in a certain direction.
   14685      *
   14686      * @param direction Negative to check scrolling left, positive to check scrolling right.
   14687      * @return true if this view can be scrolled in the specified direction, false otherwise.
   14688      */
   14689     public boolean canScrollHorizontally(int direction) {
   14690         final int offset = computeHorizontalScrollOffset();
   14691         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
   14692         if (range == 0) return false;
   14693         if (direction < 0) {
   14694             return offset > 0;
   14695         } else {
   14696             return offset < range - 1;
   14697         }
   14698     }
   14699 
   14700     /**
   14701      * Check if this view can be scrolled vertically in a certain direction.
   14702      *
   14703      * @param direction Negative to check scrolling up, positive to check scrolling down.
   14704      * @return true if this view can be scrolled in the specified direction, false otherwise.
   14705      */
   14706     public boolean canScrollVertically(int direction) {
   14707         final int offset = computeVerticalScrollOffset();
   14708         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
   14709         if (range == 0) return false;
   14710         if (direction < 0) {
   14711             return offset > 0;
   14712         } else {
   14713             return offset < range - 1;
   14714         }
   14715     }
   14716 
   14717     void getScrollIndicatorBounds(@NonNull Rect out) {
   14718         out.left = mScrollX;
   14719         out.right = mScrollX + mRight - mLeft;
   14720         out.top = mScrollY;
   14721         out.bottom = mScrollY + mBottom - mTop;
   14722     }
   14723 
   14724     private void onDrawScrollIndicators(Canvas c) {
   14725         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
   14726             // No scroll indicators enabled.
   14727             return;
   14728         }
   14729 
   14730         final Drawable dr = mScrollIndicatorDrawable;
   14731         if (dr == null) {
   14732             // Scroll indicators aren't supported here.
   14733             return;
   14734         }
   14735 
   14736         final int h = dr.getIntrinsicHeight();
   14737         final int w = dr.getIntrinsicWidth();
   14738         final Rect rect = mAttachInfo.mTmpInvalRect;
   14739         getScrollIndicatorBounds(rect);
   14740 
   14741         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
   14742             final boolean canScrollUp = canScrollVertically(-1);
   14743             if (canScrollUp) {
   14744                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
   14745                 dr.draw(c);
   14746             }
   14747         }
   14748 
   14749         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
   14750             final boolean canScrollDown = canScrollVertically(1);
   14751             if (canScrollDown) {
   14752                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
   14753                 dr.draw(c);
   14754             }
   14755         }
   14756 
   14757         final int leftRtl;
   14758         final int rightRtl;
   14759         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   14760             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
   14761             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
   14762         } else {
   14763             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
   14764             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
   14765         }
   14766 
   14767         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
   14768         if ((mPrivateFlags3 & leftMask) != 0) {
   14769             final boolean canScrollLeft = canScrollHorizontally(-1);
   14770             if (canScrollLeft) {
   14771                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
   14772                 dr.draw(c);
   14773             }
   14774         }
   14775 
   14776         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
   14777         if ((mPrivateFlags3 & rightMask) != 0) {
   14778             final boolean canScrollRight = canScrollHorizontally(1);
   14779             if (canScrollRight) {
   14780                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
   14781                 dr.draw(c);
   14782             }
   14783         }
   14784     }
   14785 
   14786     private void getHorizontalScrollBarBounds(Rect bounds) {
   14787         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   14788         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
   14789                 && !isVerticalScrollBarHidden();
   14790         final int size = getHorizontalScrollbarHeight();
   14791         final int verticalScrollBarGap = drawVerticalScrollBar ?
   14792                 getVerticalScrollbarWidth() : 0;
   14793         final int width = mRight - mLeft;
   14794         final int height = mBottom - mTop;
   14795         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
   14796         bounds.left = mScrollX + (mPaddingLeft & inside);
   14797         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
   14798         bounds.bottom = bounds.top + size;
   14799     }
   14800 
   14801     private void getVerticalScrollBarBounds(Rect bounds) {
   14802         if (mRoundScrollbarRenderer == null) {
   14803             getStraightVerticalScrollBarBounds(bounds);
   14804         } else {
   14805             getRoundVerticalScrollBarBounds(bounds);
   14806         }
   14807     }
   14808 
   14809     private void getRoundVerticalScrollBarBounds(Rect bounds) {
   14810         final int width = mRight - mLeft;
   14811         final int height = mBottom - mTop;
   14812         // Do not take padding into account as we always want the scrollbars
   14813         // to hug the screen for round wearable devices.
   14814         bounds.left = mScrollX;
   14815         bounds.top = mScrollY;
   14816         bounds.right = bounds.left + width;
   14817         bounds.bottom = mScrollY + height;
   14818     }
   14819 
   14820     private void getStraightVerticalScrollBarBounds(Rect bounds) {
   14821         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   14822         final int size = getVerticalScrollbarWidth();
   14823         int verticalScrollbarPosition = mVerticalScrollbarPosition;
   14824         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
   14825             verticalScrollbarPosition = isLayoutRtl() ?
   14826                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
   14827         }
   14828         final int width = mRight - mLeft;
   14829         final int height = mBottom - mTop;
   14830         switch (verticalScrollbarPosition) {
   14831             default:
   14832             case SCROLLBAR_POSITION_RIGHT:
   14833                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
   14834                 break;
   14835             case SCROLLBAR_POSITION_LEFT:
   14836                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
   14837                 break;
   14838         }
   14839         bounds.top = mScrollY + (mPaddingTop & inside);
   14840         bounds.right = bounds.left + size;
   14841         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
   14842     }
   14843 
   14844     /**
   14845      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
   14846      * scrollbars are painted only if they have been awakened first.</p>
   14847      *
   14848      * @param canvas the canvas on which to draw the scrollbars
   14849      *
   14850      * @see #awakenScrollBars(int)
   14851      */
   14852     protected final void onDrawScrollBars(Canvas canvas) {
   14853         // scrollbars are drawn only when the animation is running
   14854         final ScrollabilityCache cache = mScrollCache;
   14855 
   14856         if (cache != null) {
   14857 
   14858             int state = cache.state;
   14859 
   14860             if (state == ScrollabilityCache.OFF) {
   14861                 return;
   14862             }
   14863 
   14864             boolean invalidate = false;
   14865 
   14866             if (state == ScrollabilityCache.FADING) {
   14867                 // We're fading -- get our fade interpolation
   14868                 if (cache.interpolatorValues == null) {
   14869                     cache.interpolatorValues = new float[1];
   14870                 }
   14871 
   14872                 float[] values = cache.interpolatorValues;
   14873 
   14874                 // Stops the animation if we're done
   14875                 if (cache.scrollBarInterpolator.timeToValues(values) ==
   14876                         Interpolator.Result.FREEZE_END) {
   14877                     cache.state = ScrollabilityCache.OFF;
   14878                 } else {
   14879                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
   14880                 }
   14881 
   14882                 // This will make the scroll bars inval themselves after
   14883                 // drawing. We only want this when we're fading so that
   14884                 // we prevent excessive redraws
   14885                 invalidate = true;
   14886             } else {
   14887                 // We're just on -- but we may have been fading before so
   14888                 // reset alpha
   14889                 cache.scrollBar.mutate().setAlpha(255);
   14890             }
   14891 
   14892             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
   14893             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
   14894                     && !isVerticalScrollBarHidden();
   14895 
   14896             // Fork out the scroll bar drawing for round wearable devices.
   14897             if (mRoundScrollbarRenderer != null) {
   14898                 if (drawVerticalScrollBar) {
   14899                     final Rect bounds = cache.mScrollBarBounds;
   14900                     getVerticalScrollBarBounds(bounds);
   14901                     mRoundScrollbarRenderer.drawRoundScrollbars(
   14902                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
   14903                     if (invalidate) {
   14904                         invalidate();
   14905                     }
   14906                 }
   14907                 // Do not draw horizontal scroll bars for round wearable devices.
   14908             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
   14909                 final ScrollBarDrawable scrollBar = cache.scrollBar;
   14910 
   14911                 if (drawHorizontalScrollBar) {
   14912                     scrollBar.setParameters(computeHorizontalScrollRange(),
   14913                             computeHorizontalScrollOffset(),
   14914                             computeHorizontalScrollExtent(), false);
   14915                     final Rect bounds = cache.mScrollBarBounds;
   14916                     getHorizontalScrollBarBounds(bounds);
   14917                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
   14918                             bounds.right, bounds.bottom);
   14919                     if (invalidate) {
   14920                         invalidate(bounds);
   14921                     }
   14922                 }
   14923 
   14924                 if (drawVerticalScrollBar) {
   14925                     scrollBar.setParameters(computeVerticalScrollRange(),
   14926                             computeVerticalScrollOffset(),
   14927                             computeVerticalScrollExtent(), true);
   14928                     final Rect bounds = cache.mScrollBarBounds;
   14929                     getVerticalScrollBarBounds(bounds);
   14930                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
   14931                             bounds.right, bounds.bottom);
   14932                     if (invalidate) {
   14933                         invalidate(bounds);
   14934                     }
   14935                 }
   14936             }
   14937         }
   14938     }
   14939 
   14940     /**
   14941      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
   14942      * FastScroller is visible.
   14943      * @return whether to temporarily hide the vertical scrollbar
   14944      * @hide
   14945      */
   14946     protected boolean isVerticalScrollBarHidden() {
   14947         return false;
   14948     }
   14949 
   14950     /**
   14951      * <p>Draw the horizontal scrollbar if
   14952      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
   14953      *
   14954      * @param canvas the canvas on which to draw the scrollbar
   14955      * @param scrollBar the scrollbar's drawable
   14956      *
   14957      * @see #isHorizontalScrollBarEnabled()
   14958      * @see #computeHorizontalScrollRange()
   14959      * @see #computeHorizontalScrollExtent()
   14960      * @see #computeHorizontalScrollOffset()
   14961      * @see android.widget.ScrollBarDrawable
   14962      * @hide
   14963      */
   14964     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
   14965             int l, int t, int r, int b) {
   14966         scrollBar.setBounds(l, t, r, b);
   14967         scrollBar.draw(canvas);
   14968     }
   14969 
   14970     /**
   14971      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
   14972      * returns true.</p>
   14973      *
   14974      * @param canvas the canvas on which to draw the scrollbar
   14975      * @param scrollBar the scrollbar's drawable
   14976      *
   14977      * @see #isVerticalScrollBarEnabled()
   14978      * @see #computeVerticalScrollRange()
   14979      * @see #computeVerticalScrollExtent()
   14980      * @see #computeVerticalScrollOffset()
   14981      * @see android.widget.ScrollBarDrawable
   14982      * @hide
   14983      */
   14984     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
   14985             int l, int t, int r, int b) {
   14986         scrollBar.setBounds(l, t, r, b);
   14987         scrollBar.draw(canvas);
   14988     }
   14989 
   14990     /**
   14991      * Implement this to do your drawing.
   14992      *
   14993      * @param canvas the canvas on which the background will be drawn
   14994      */
   14995     protected void onDraw(Canvas canvas) {
   14996     }
   14997 
   14998     /*
   14999      * Caller is responsible for calling requestLayout if necessary.
   15000      * (This allows addViewInLayout to not request a new layout.)
   15001      */
   15002     void assignParent(ViewParent parent) {
   15003         if (mParent == null) {
   15004             mParent = parent;
   15005         } else if (parent == null) {
   15006             mParent = null;
   15007         } else {
   15008             throw new RuntimeException("view " + this + " being added, but"
   15009                     + " it already has a parent");
   15010         }
   15011     }
   15012 
   15013     /**
   15014      * This is called when the view is attached to a window.  At this point it
   15015      * has a Surface and will start drawing.  Note that this function is
   15016      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
   15017      * however it may be called any time before the first onDraw -- including
   15018      * before or after {@link #onMeasure(int, int)}.
   15019      *
   15020      * @see #onDetachedFromWindow()
   15021      */
   15022     @CallSuper
   15023     protected void onAttachedToWindow() {
   15024         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
   15025             mParent.requestTransparentRegion(this);
   15026         }
   15027 
   15028         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   15029 
   15030         jumpDrawablesToCurrentState();
   15031 
   15032         resetSubtreeAccessibilityStateChanged();
   15033 
   15034         // rebuild, since Outline not maintained while View is detached
   15035         rebuildOutline();
   15036 
   15037         if (isFocused()) {
   15038             InputMethodManager imm = InputMethodManager.peekInstance();
   15039             if (imm != null) {
   15040                 imm.focusIn(this);
   15041             }
   15042         }
   15043     }
   15044 
   15045     /**
   15046      * Resolve all RTL related properties.
   15047      *
   15048      * @return true if resolution of RTL properties has been done
   15049      *
   15050      * @hide
   15051      */
   15052     public boolean resolveRtlPropertiesIfNeeded() {
   15053         if (!needRtlPropertiesResolution()) return false;
   15054 
   15055         // Order is important here: LayoutDirection MUST be resolved first
   15056         if (!isLayoutDirectionResolved()) {
   15057             resolveLayoutDirection();
   15058             resolveLayoutParams();
   15059         }
   15060         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
   15061         if (!isTextDirectionResolved()) {
   15062             resolveTextDirection();
   15063         }
   15064         if (!isTextAlignmentResolved()) {
   15065             resolveTextAlignment();
   15066         }
   15067         // Should resolve Drawables before Padding because we need the layout direction of the
   15068         // Drawable to correctly resolve Padding.
   15069         if (!areDrawablesResolved()) {
   15070             resolveDrawables();
   15071         }
   15072         if (!isPaddingResolved()) {
   15073             resolvePadding();
   15074         }
   15075         onRtlPropertiesChanged(getLayoutDirection());
   15076         return true;
   15077     }
   15078 
   15079     /**
   15080      * Reset resolution of all RTL related properties.
   15081      *
   15082      * @hide
   15083      */
   15084     public void resetRtlProperties() {
   15085         resetResolvedLayoutDirection();
   15086         resetResolvedTextDirection();
   15087         resetResolvedTextAlignment();
   15088         resetResolvedPadding();
   15089         resetResolvedDrawables();
   15090     }
   15091 
   15092     /**
   15093      * @see #onScreenStateChanged(int)
   15094      */
   15095     void dispatchScreenStateChanged(int screenState) {
   15096         onScreenStateChanged(screenState);
   15097     }
   15098 
   15099     /**
   15100      * This method is called whenever the state of the screen this view is
   15101      * attached to changes. A state change will usually occurs when the screen
   15102      * turns on or off (whether it happens automatically or the user does it
   15103      * manually.)
   15104      *
   15105      * @param screenState The new state of the screen. Can be either
   15106      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
   15107      */
   15108     public void onScreenStateChanged(int screenState) {
   15109     }
   15110 
   15111     /**
   15112      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
   15113      */
   15114     private boolean hasRtlSupport() {
   15115         return mContext.getApplicationInfo().hasRtlSupport();
   15116     }
   15117 
   15118     /**
   15119      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
   15120      * RTL not supported)
   15121      */
   15122     private boolean isRtlCompatibilityMode() {
   15123         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   15124         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
   15125     }
   15126 
   15127     /**
   15128      * @return true if RTL properties need resolution.
   15129      *
   15130      */
   15131     private boolean needRtlPropertiesResolution() {
   15132         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
   15133     }
   15134 
   15135     /**
   15136      * Called when any RTL property (layout direction or text direction or text alignment) has
   15137      * been changed.
   15138      *
   15139      * Subclasses need to override this method to take care of cached information that depends on the
   15140      * resolved layout direction, or to inform child views that inherit their layout direction.
   15141      *
   15142      * The default implementation does nothing.
   15143      *
   15144      * @param layoutDirection the direction of the layout
   15145      *
   15146      * @see #LAYOUT_DIRECTION_LTR
   15147      * @see #LAYOUT_DIRECTION_RTL
   15148      */
   15149     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
   15150     }
   15151 
   15152     /**
   15153      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
   15154      * that the parent directionality can and will be resolved before its children.
   15155      *
   15156      * @return true if resolution has been done, false otherwise.
   15157      *
   15158      * @hide
   15159      */
   15160     public boolean resolveLayoutDirection() {
   15161         // Clear any previous layout direction resolution
   15162         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   15163 
   15164         if (hasRtlSupport()) {
   15165             // Set resolved depending on layout direction
   15166             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
   15167                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
   15168                 case LAYOUT_DIRECTION_INHERIT:
   15169                     // We cannot resolve yet. LTR is by default and let the resolution happen again
   15170                     // later to get the correct resolved value
   15171                     if (!canResolveLayoutDirection()) return false;
   15172 
   15173                     // Parent has not yet resolved, LTR is still the default
   15174                     try {
   15175                         if (!mParent.isLayoutDirectionResolved()) return false;
   15176 
   15177                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   15178                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   15179                         }
   15180                     } catch (AbstractMethodError e) {
   15181                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   15182                                 " does not fully implement ViewParent", e);
   15183                     }
   15184                     break;
   15185                 case LAYOUT_DIRECTION_RTL:
   15186                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   15187                     break;
   15188                 case LAYOUT_DIRECTION_LOCALE:
   15189                     if((LAYOUT_DIRECTION_RTL ==
   15190                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
   15191                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   15192                     }
   15193                     break;
   15194                 default:
   15195                     // Nothing to do, LTR by default
   15196             }
   15197         }
   15198 
   15199         // Set to resolved
   15200         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   15201         return true;
   15202     }
   15203 
   15204     /**
   15205      * Check if layout direction resolution can be done.
   15206      *
   15207      * @return true if layout direction resolution can be done otherwise return false.
   15208      */
   15209     public boolean canResolveLayoutDirection() {
   15210         switch (getRawLayoutDirection()) {
   15211             case LAYOUT_DIRECTION_INHERIT:
   15212                 if (mParent != null) {
   15213                     try {
   15214                         return mParent.canResolveLayoutDirection();
   15215                     } catch (AbstractMethodError e) {
   15216                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   15217                                 " does not fully implement ViewParent", e);
   15218                     }
   15219                 }
   15220                 return false;
   15221 
   15222             default:
   15223                 return true;
   15224         }
   15225     }
   15226 
   15227     /**
   15228      * Reset the resolved layout direction. Layout direction will be resolved during a call to
   15229      * {@link #onMeasure(int, int)}.
   15230      *
   15231      * @hide
   15232      */
   15233     public void resetResolvedLayoutDirection() {
   15234         // Reset the current resolved bits
   15235         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   15236     }
   15237 
   15238     /**
   15239      * @return true if the layout direction is inherited.
   15240      *
   15241      * @hide
   15242      */
   15243     public boolean isLayoutDirectionInherited() {
   15244         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
   15245     }
   15246 
   15247     /**
   15248      * @return true if layout direction has been resolved.
   15249      */
   15250     public boolean isLayoutDirectionResolved() {
   15251         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   15252     }
   15253 
   15254     /**
   15255      * Return if padding has been resolved
   15256      *
   15257      * @hide
   15258      */
   15259     boolean isPaddingResolved() {
   15260         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
   15261     }
   15262 
   15263     /**
   15264      * Resolves padding depending on layout direction, if applicable, and
   15265      * recomputes internal padding values to adjust for scroll bars.
   15266      *
   15267      * @hide
   15268      */
   15269     public void resolvePadding() {
   15270         final int resolvedLayoutDirection = getLayoutDirection();
   15271 
   15272         if (!isRtlCompatibilityMode()) {
   15273             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
   15274             // If start / end padding are defined, they will be resolved (hence overriding) to
   15275             // left / right or right / left depending on the resolved layout direction.
   15276             // If start / end padding are not defined, use the left / right ones.
   15277             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
   15278                 Rect padding = sThreadLocal.get();
   15279                 if (padding == null) {
   15280                     padding = new Rect();
   15281                     sThreadLocal.set(padding);
   15282                 }
   15283                 mBackground.getPadding(padding);
   15284                 if (!mLeftPaddingDefined) {
   15285                     mUserPaddingLeftInitial = padding.left;
   15286                 }
   15287                 if (!mRightPaddingDefined) {
   15288                     mUserPaddingRightInitial = padding.right;
   15289                 }
   15290             }
   15291             switch (resolvedLayoutDirection) {
   15292                 case LAYOUT_DIRECTION_RTL:
   15293                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   15294                         mUserPaddingRight = mUserPaddingStart;
   15295                     } else {
   15296                         mUserPaddingRight = mUserPaddingRightInitial;
   15297                     }
   15298                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   15299                         mUserPaddingLeft = mUserPaddingEnd;
   15300                     } else {
   15301                         mUserPaddingLeft = mUserPaddingLeftInitial;
   15302                     }
   15303                     break;
   15304                 case LAYOUT_DIRECTION_LTR:
   15305                 default:
   15306                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   15307                         mUserPaddingLeft = mUserPaddingStart;
   15308                     } else {
   15309                         mUserPaddingLeft = mUserPaddingLeftInitial;
   15310                     }
   15311                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   15312                         mUserPaddingRight = mUserPaddingEnd;
   15313                     } else {
   15314                         mUserPaddingRight = mUserPaddingRightInitial;
   15315                     }
   15316             }
   15317 
   15318             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
   15319         }
   15320 
   15321         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   15322         onRtlPropertiesChanged(resolvedLayoutDirection);
   15323 
   15324         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
   15325     }
   15326 
   15327     /**
   15328      * Reset the resolved layout direction.
   15329      *
   15330      * @hide
   15331      */
   15332     public void resetResolvedPadding() {
   15333         resetResolvedPaddingInternal();
   15334     }
   15335 
   15336     /**
   15337      * Used when we only want to reset *this* view's padding and not trigger overrides
   15338      * in ViewGroup that reset children too.
   15339      */
   15340     void resetResolvedPaddingInternal() {
   15341         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
   15342     }
   15343 
   15344     /**
   15345      * This is called when the view is detached from a window.  At this point it
   15346      * no longer has a surface for drawing.
   15347      *
   15348      * @see #onAttachedToWindow()
   15349      */
   15350     @CallSuper
   15351     protected void onDetachedFromWindow() {
   15352     }
   15353 
   15354     /**
   15355      * This is a framework-internal mirror of onDetachedFromWindow() that's called
   15356      * after onDetachedFromWindow().
   15357      *
   15358      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
   15359      * The super method should be called at the end of the overridden method to ensure
   15360      * subclasses are destroyed first
   15361      *
   15362      * @hide
   15363      */
   15364     @CallSuper
   15365     protected void onDetachedFromWindowInternal() {
   15366         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
   15367         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   15368         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
   15369 
   15370         removeUnsetPressCallback();
   15371         removeLongPressCallback();
   15372         removePerformClickCallback();
   15373         removeSendViewScrolledAccessibilityEventCallback();
   15374         stopNestedScroll();
   15375 
   15376         // Anything that started animating right before detach should already
   15377         // be in its final state when re-attached.
   15378         jumpDrawablesToCurrentState();
   15379 
   15380         destroyDrawingCache();
   15381 
   15382         cleanupDraw();
   15383         mCurrentAnimation = null;
   15384     }
   15385 
   15386     private void cleanupDraw() {
   15387         resetDisplayList();
   15388         if (mAttachInfo != null) {
   15389             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
   15390         }
   15391     }
   15392 
   15393     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
   15394     }
   15395 
   15396     /**
   15397      * @return The number of times this view has been attached to a window
   15398      */
   15399     protected int getWindowAttachCount() {
   15400         return mWindowAttachCount;
   15401     }
   15402 
   15403     /**
   15404      * Retrieve a unique token identifying the window this view is attached to.
   15405      * @return Return the window's token for use in
   15406      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
   15407      */
   15408     public IBinder getWindowToken() {
   15409         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
   15410     }
   15411 
   15412     /**
   15413      * Retrieve the {@link WindowId} for the window this view is
   15414      * currently attached to.
   15415      */
   15416     public WindowId getWindowId() {
   15417         if (mAttachInfo == null) {
   15418             return null;
   15419         }
   15420         if (mAttachInfo.mWindowId == null) {
   15421             try {
   15422                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
   15423                         mAttachInfo.mWindowToken);
   15424                 mAttachInfo.mWindowId = new WindowId(
   15425                         mAttachInfo.mIWindowId);
   15426             } catch (RemoteException e) {
   15427             }
   15428         }
   15429         return mAttachInfo.mWindowId;
   15430     }
   15431 
   15432     /**
   15433      * Retrieve a unique token identifying the top-level "real" window of
   15434      * the window that this view is attached to.  That is, this is like
   15435      * {@link #getWindowToken}, except if the window this view in is a panel
   15436      * window (attached to another containing window), then the token of
   15437      * the containing window is returned instead.
   15438      *
   15439      * @return Returns the associated window token, either
   15440      * {@link #getWindowToken()} or the containing window's token.
   15441      */
   15442     public IBinder getApplicationWindowToken() {
   15443         AttachInfo ai = mAttachInfo;
   15444         if (ai != null) {
   15445             IBinder appWindowToken = ai.mPanelParentWindowToken;
   15446             if (appWindowToken == null) {
   15447                 appWindowToken = ai.mWindowToken;
   15448             }
   15449             return appWindowToken;
   15450         }
   15451         return null;
   15452     }
   15453 
   15454     /**
   15455      * Gets the logical display to which the view's window has been attached.
   15456      *
   15457      * @return The logical display, or null if the view is not currently attached to a window.
   15458      */
   15459     public Display getDisplay() {
   15460         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
   15461     }
   15462 
   15463     /**
   15464      * Retrieve private session object this view hierarchy is using to
   15465      * communicate with the window manager.
   15466      * @return the session object to communicate with the window manager
   15467      */
   15468     /*package*/ IWindowSession getWindowSession() {
   15469         return mAttachInfo != null ? mAttachInfo.mSession : null;
   15470     }
   15471 
   15472     /**
   15473      * Return the visibility value of the least visible component passed.
   15474      */
   15475     int combineVisibility(int vis1, int vis2) {
   15476         // This works because VISIBLE < INVISIBLE < GONE.
   15477         return Math.max(vis1, vis2);
   15478     }
   15479 
   15480     /**
   15481      * @param info the {@link android.view.View.AttachInfo} to associated with
   15482      *        this view
   15483      */
   15484     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
   15485         mAttachInfo = info;
   15486         if (mOverlay != null) {
   15487             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
   15488         }
   15489         mWindowAttachCount++;
   15490         // We will need to evaluate the drawable state at least once.
   15491         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   15492         if (mFloatingTreeObserver != null) {
   15493             info.mTreeObserver.merge(mFloatingTreeObserver);
   15494             mFloatingTreeObserver = null;
   15495         }
   15496 
   15497         registerPendingFrameMetricsObservers();
   15498 
   15499         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
   15500             mAttachInfo.mScrollContainers.add(this);
   15501             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   15502         }
   15503         // Transfer all pending runnables.
   15504         if (mRunQueue != null) {
   15505             mRunQueue.executeActions(info.mHandler);
   15506             mRunQueue = null;
   15507         }
   15508         performCollectViewAttributes(mAttachInfo, visibility);
   15509         onAttachedToWindow();
   15510 
   15511         ListenerInfo li = mListenerInfo;
   15512         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   15513                 li != null ? li.mOnAttachStateChangeListeners : null;
   15514         if (listeners != null && listeners.size() > 0) {
   15515             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   15516             // perform the dispatching. The iterator is a safe guard against listeners that
   15517             // could mutate the list by calling the various add/remove methods. This prevents
   15518             // the array from being modified while we iterate it.
   15519             for (OnAttachStateChangeListener listener : listeners) {
   15520                 listener.onViewAttachedToWindow(this);
   15521             }
   15522         }
   15523 
   15524         int vis = info.mWindowVisibility;
   15525         if (vis != GONE) {
   15526             onWindowVisibilityChanged(vis);
   15527             if (isShown()) {
   15528                 // Calling onVisibilityAggregated directly here since the subtree will also
   15529                 // receive dispatchAttachedToWindow and this same call
   15530                 onVisibilityAggregated(vis == VISIBLE);
   15531             }
   15532         }
   15533 
   15534         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
   15535         // As all views in the subtree will already receive dispatchAttachedToWindow
   15536         // traversing the subtree again here is not desired.
   15537         onVisibilityChanged(this, visibility);
   15538 
   15539         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
   15540             // If nobody has evaluated the drawable state yet, then do it now.
   15541             refreshDrawableState();
   15542         }
   15543         needGlobalAttributesUpdate(false);
   15544     }
   15545 
   15546     void dispatchDetachedFromWindow() {
   15547         AttachInfo info = mAttachInfo;
   15548         if (info != null) {
   15549             int vis = info.mWindowVisibility;
   15550             if (vis != GONE) {
   15551                 onWindowVisibilityChanged(GONE);
   15552                 if (isShown()) {
   15553                     // Invoking onVisibilityAggregated directly here since the subtree
   15554                     // will also receive detached from window
   15555                     onVisibilityAggregated(false);
   15556                 }
   15557             }
   15558         }
   15559 
   15560         onDetachedFromWindow();
   15561         onDetachedFromWindowInternal();
   15562 
   15563         InputMethodManager imm = InputMethodManager.peekInstance();
   15564         if (imm != null) {
   15565             imm.onViewDetachedFromWindow(this);
   15566         }
   15567 
   15568         ListenerInfo li = mListenerInfo;
   15569         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   15570                 li != null ? li.mOnAttachStateChangeListeners : null;
   15571         if (listeners != null && listeners.size() > 0) {
   15572             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   15573             // perform the dispatching. The iterator is a safe guard against listeners that
   15574             // could mutate the list by calling the various add/remove methods. This prevents
   15575             // the array from being modified while we iterate it.
   15576             for (OnAttachStateChangeListener listener : listeners) {
   15577                 listener.onViewDetachedFromWindow(this);
   15578             }
   15579         }
   15580 
   15581         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   15582             mAttachInfo.mScrollContainers.remove(this);
   15583             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
   15584         }
   15585 
   15586         mAttachInfo = null;
   15587         if (mOverlay != null) {
   15588             mOverlay.getOverlayView().dispatchDetachedFromWindow();
   15589         }
   15590     }
   15591 
   15592     /**
   15593      * Cancel any deferred high-level input events that were previously posted to the event queue.
   15594      *
   15595      * <p>Many views post high-level events such as click handlers to the event queue
   15596      * to run deferred in order to preserve a desired user experience - clearing visible
   15597      * pressed states before executing, etc. This method will abort any events of this nature
   15598      * that are currently in flight.</p>
   15599      *
   15600      * <p>Custom views that generate their own high-level deferred input events should override
   15601      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
   15602      *
   15603      * <p>This will also cancel pending input events for any child views.</p>
   15604      *
   15605      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
   15606      * This will not impact newer events posted after this call that may occur as a result of
   15607      * lower-level input events still waiting in the queue. If you are trying to prevent
   15608      * double-submitted  events for the duration of some sort of asynchronous transaction
   15609      * you should also take other steps to protect against unexpected double inputs e.g. calling
   15610      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
   15611      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
   15612      */
   15613     public final void cancelPendingInputEvents() {
   15614         dispatchCancelPendingInputEvents();
   15615     }
   15616 
   15617     /**
   15618      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
   15619      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
   15620      */
   15621     void dispatchCancelPendingInputEvents() {
   15622         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
   15623         onCancelPendingInputEvents();
   15624         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
   15625             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
   15626                     " did not call through to super.onCancelPendingInputEvents()");
   15627         }
   15628     }
   15629 
   15630     /**
   15631      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
   15632      * a parent view.
   15633      *
   15634      * <p>This method is responsible for removing any pending high-level input events that were
   15635      * posted to the event queue to run later. Custom view classes that post their own deferred
   15636      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
   15637      * {@link android.os.Handler} should override this method, call
   15638      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
   15639      * </p>
   15640      */
   15641     public void onCancelPendingInputEvents() {
   15642         removePerformClickCallback();
   15643         cancelLongPress();
   15644         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
   15645     }
   15646 
   15647     /**
   15648      * Store this view hierarchy's frozen state into the given container.
   15649      *
   15650      * @param container The SparseArray in which to save the view's state.
   15651      *
   15652      * @see #restoreHierarchyState(android.util.SparseArray)
   15653      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   15654      * @see #onSaveInstanceState()
   15655      */
   15656     public void saveHierarchyState(SparseArray<Parcelable> container) {
   15657         dispatchSaveInstanceState(container);
   15658     }
   15659 
   15660     /**
   15661      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
   15662      * this view and its children. May be overridden to modify how freezing happens to a
   15663      * view's children; for example, some views may want to not store state for their children.
   15664      *
   15665      * @param container The SparseArray in which to save the view's state.
   15666      *
   15667      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   15668      * @see #saveHierarchyState(android.util.SparseArray)
   15669      * @see #onSaveInstanceState()
   15670      */
   15671     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
   15672         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
   15673             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   15674             Parcelable state = onSaveInstanceState();
   15675             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   15676                 throw new IllegalStateException(
   15677                         "Derived class did not call super.onSaveInstanceState()");
   15678             }
   15679             if (state != null) {
   15680                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
   15681                 // + ": " + state);
   15682                 container.put(mID, state);
   15683             }
   15684         }
   15685     }
   15686 
   15687     /**
   15688      * Hook allowing a view to generate a representation of its internal state
   15689      * that can later be used to create a new instance with that same state.
   15690      * This state should only contain information that is not persistent or can
   15691      * not be reconstructed later. For example, you will never store your
   15692      * current position on screen because that will be computed again when a
   15693      * new instance of the view is placed in its view hierarchy.
   15694      * <p>
   15695      * Some examples of things you may store here: the current cursor position
   15696      * in a text view (but usually not the text itself since that is stored in a
   15697      * content provider or other persistent storage), the currently selected
   15698      * item in a list view.
   15699      *
   15700      * @return Returns a Parcelable object containing the view's current dynamic
   15701      *         state, or null if there is nothing interesting to save. The
   15702      *         default implementation returns null.
   15703      * @see #onRestoreInstanceState(android.os.Parcelable)
   15704      * @see #saveHierarchyState(android.util.SparseArray)
   15705      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   15706      * @see #setSaveEnabled(boolean)
   15707      */
   15708     @CallSuper
   15709     protected Parcelable onSaveInstanceState() {
   15710         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   15711         if (mStartActivityRequestWho != null) {
   15712             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
   15713             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
   15714             return state;
   15715         }
   15716         return BaseSavedState.EMPTY_STATE;
   15717     }
   15718 
   15719     /**
   15720      * Restore this view hierarchy's frozen state from the given container.
   15721      *
   15722      * @param container The SparseArray which holds previously frozen states.
   15723      *
   15724      * @see #saveHierarchyState(android.util.SparseArray)
   15725      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   15726      * @see #onRestoreInstanceState(android.os.Parcelable)
   15727      */
   15728     public void restoreHierarchyState(SparseArray<Parcelable> container) {
   15729         dispatchRestoreInstanceState(container);
   15730     }
   15731 
   15732     /**
   15733      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
   15734      * state for this view and its children. May be overridden to modify how restoring
   15735      * happens to a view's children; for example, some views may want to not store state
   15736      * for their children.
   15737      *
   15738      * @param container The SparseArray which holds previously saved state.
   15739      *
   15740      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   15741      * @see #restoreHierarchyState(android.util.SparseArray)
   15742      * @see #onRestoreInstanceState(android.os.Parcelable)
   15743      */
   15744     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
   15745         if (mID != NO_ID) {
   15746             Parcelable state = container.get(mID);
   15747             if (state != null) {
   15748                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
   15749                 // + ": " + state);
   15750                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   15751                 onRestoreInstanceState(state);
   15752                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   15753                     throw new IllegalStateException(
   15754                             "Derived class did not call super.onRestoreInstanceState()");
   15755                 }
   15756             }
   15757         }
   15758     }
   15759 
   15760     /**
   15761      * Hook allowing a view to re-apply a representation of its internal state that had previously
   15762      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
   15763      * null state.
   15764      *
   15765      * @param state The frozen state that had previously been returned by
   15766      *        {@link #onSaveInstanceState}.
   15767      *
   15768      * @see #onSaveInstanceState()
   15769      * @see #restoreHierarchyState(android.util.SparseArray)
   15770      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   15771      */
   15772     @CallSuper
   15773     protected void onRestoreInstanceState(Parcelable state) {
   15774         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   15775         if (state != null && !(state instanceof AbsSavedState)) {
   15776             throw new IllegalArgumentException("Wrong state class, expecting View State but "
   15777                     + "received " + state.getClass().toString() + " instead. This usually happens "
   15778                     + "when two views of different type have the same id in the same hierarchy. "
   15779                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
   15780                     + "other views do not use the same id.");
   15781         }
   15782         if (state != null && state instanceof BaseSavedState) {
   15783             mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
   15784         }
   15785     }
   15786 
   15787     /**
   15788      * <p>Return the time at which the drawing of the view hierarchy started.</p>
   15789      *
   15790      * @return the drawing start time in milliseconds
   15791      */
   15792     public long getDrawingTime() {
   15793         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
   15794     }
   15795 
   15796     /**
   15797      * <p>Enables or disables the duplication of the parent's state into this view. When
   15798      * duplication is enabled, this view gets its drawable state from its parent rather
   15799      * than from its own internal properties.</p>
   15800      *
   15801      * <p>Note: in the current implementation, setting this property to true after the
   15802      * view was added to a ViewGroup might have no effect at all. This property should
   15803      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
   15804      *
   15805      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
   15806      * property is enabled, an exception will be thrown.</p>
   15807      *
   15808      * <p>Note: if the child view uses and updates additional states which are unknown to the
   15809      * parent, these states should not be affected by this method.</p>
   15810      *
   15811      * @param enabled True to enable duplication of the parent's drawable state, false
   15812      *                to disable it.
   15813      *
   15814      * @see #getDrawableState()
   15815      * @see #isDuplicateParentStateEnabled()
   15816      */
   15817     public void setDuplicateParentStateEnabled(boolean enabled) {
   15818         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
   15819     }
   15820 
   15821     /**
   15822      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
   15823      *
   15824      * @return True if this view's drawable state is duplicated from the parent,
   15825      *         false otherwise
   15826      *
   15827      * @see #getDrawableState()
   15828      * @see #setDuplicateParentStateEnabled(boolean)
   15829      */
   15830     public boolean isDuplicateParentStateEnabled() {
   15831         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
   15832     }
   15833 
   15834     /**
   15835      * <p>Specifies the type of layer backing this view. The layer can be
   15836      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   15837      * {@link #LAYER_TYPE_HARDWARE}.</p>
   15838      *
   15839      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   15840      * instance that controls how the layer is composed on screen. The following
   15841      * properties of the paint are taken into account when composing the layer:</p>
   15842      * <ul>
   15843      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   15844      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   15845      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   15846      * </ul>
   15847      *
   15848      * <p>If this view has an alpha value set to < 1.0 by calling
   15849      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
   15850      * by this view's alpha value.</p>
   15851      *
   15852      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
   15853      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
   15854      * for more information on when and how to use layers.</p>
   15855      *
   15856      * @param layerType The type of layer to use with this view, must be one of
   15857      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   15858      *        {@link #LAYER_TYPE_HARDWARE}
   15859      * @param paint The paint used to compose the layer. This argument is optional
   15860      *        and can be null. It is ignored when the layer type is
   15861      *        {@link #LAYER_TYPE_NONE}
   15862      *
   15863      * @see #getLayerType()
   15864      * @see #LAYER_TYPE_NONE
   15865      * @see #LAYER_TYPE_SOFTWARE
   15866      * @see #LAYER_TYPE_HARDWARE
   15867      * @see #setAlpha(float)
   15868      *
   15869      * @attr ref android.R.styleable#View_layerType
   15870      */
   15871     public void setLayerType(int layerType, @Nullable Paint paint) {
   15872         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
   15873             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
   15874                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
   15875         }
   15876 
   15877         boolean typeChanged = mRenderNode.setLayerType(layerType);
   15878 
   15879         if (!typeChanged) {
   15880             setLayerPaint(paint);
   15881             return;
   15882         }
   15883 
   15884         if (layerType != LAYER_TYPE_SOFTWARE) {
   15885             // Destroy any previous software drawing cache if present
   15886             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
   15887             // drawing cache created in View#draw when drawing to a SW canvas.
   15888             destroyDrawingCache();
   15889         }
   15890 
   15891         mLayerType = layerType;
   15892         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
   15893         mRenderNode.setLayerPaint(mLayerPaint);
   15894 
   15895         // draw() behaves differently if we are on a layer, so we need to
   15896         // invalidate() here
   15897         invalidateParentCaches();
   15898         invalidate(true);
   15899     }
   15900 
   15901     /**
   15902      * Updates the {@link Paint} object used with the current layer (used only if the current
   15903      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
   15904      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
   15905      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
   15906      * ensure that the view gets redrawn immediately.
   15907      *
   15908      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   15909      * instance that controls how the layer is composed on screen. The following
   15910      * properties of the paint are taken into account when composing the layer:</p>
   15911      * <ul>
   15912      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   15913      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   15914      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   15915      * </ul>
   15916      *
   15917      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
   15918      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
   15919      *
   15920      * @param paint The paint used to compose the layer. This argument is optional
   15921      *        and can be null. It is ignored when the layer type is
   15922      *        {@link #LAYER_TYPE_NONE}
   15923      *
   15924      * @see #setLayerType(int, android.graphics.Paint)
   15925      */
   15926     public void setLayerPaint(@Nullable Paint paint) {
   15927         int layerType = getLayerType();
   15928         if (layerType != LAYER_TYPE_NONE) {
   15929             mLayerPaint = paint;
   15930             if (layerType == LAYER_TYPE_HARDWARE) {
   15931                 if (mRenderNode.setLayerPaint(paint)) {
   15932                     invalidateViewProperty(false, false);
   15933                 }
   15934             } else {
   15935                 invalidate();
   15936             }
   15937         }
   15938     }
   15939 
   15940     /**
   15941      * Indicates what type of layer is currently associated with this view. By default
   15942      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
   15943      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
   15944      * for more information on the different types of layers.
   15945      *
   15946      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   15947      *         {@link #LAYER_TYPE_HARDWARE}
   15948      *
   15949      * @see #setLayerType(int, android.graphics.Paint)
   15950      * @see #buildLayer()
   15951      * @see #LAYER_TYPE_NONE
   15952      * @see #LAYER_TYPE_SOFTWARE
   15953      * @see #LAYER_TYPE_HARDWARE
   15954      */
   15955     public int getLayerType() {
   15956         return mLayerType;
   15957     }
   15958 
   15959     /**
   15960      * Forces this view's layer to be created and this view to be rendered
   15961      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
   15962      * invoking this method will have no effect.
   15963      *
   15964      * This method can for instance be used to render a view into its layer before
   15965      * starting an animation. If this view is complex, rendering into the layer
   15966      * before starting the animation will avoid skipping frames.
   15967      *
   15968      * @throws IllegalStateException If this view is not attached to a window
   15969      *
   15970      * @see #setLayerType(int, android.graphics.Paint)
   15971      */
   15972     public void buildLayer() {
   15973         if (mLayerType == LAYER_TYPE_NONE) return;
   15974 
   15975         final AttachInfo attachInfo = mAttachInfo;
   15976         if (attachInfo == null) {
   15977             throw new IllegalStateException("This view must be attached to a window first");
   15978         }
   15979 
   15980         if (getWidth() == 0 || getHeight() == 0) {
   15981             return;
   15982         }
   15983 
   15984         switch (mLayerType) {
   15985             case LAYER_TYPE_HARDWARE:
   15986                 updateDisplayListIfDirty();
   15987                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
   15988                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
   15989                 }
   15990                 break;
   15991             case LAYER_TYPE_SOFTWARE:
   15992                 buildDrawingCache(true);
   15993                 break;
   15994         }
   15995     }
   15996 
   15997     /**
   15998      * Destroys all hardware rendering resources. This method is invoked
   15999      * when the system needs to reclaim resources. Upon execution of this
   16000      * method, you should free any OpenGL resources created by the view.
   16001      *
   16002      * Note: you <strong>must</strong> call
   16003      * <code>super.destroyHardwareResources()</code> when overriding
   16004      * this method.
   16005      *
   16006      * @hide
   16007      */
   16008     @CallSuper
   16009     protected void destroyHardwareResources() {
   16010         // Although the Layer will be destroyed by RenderNode, we want to release
   16011         // the staging display list, which is also a signal to RenderNode that it's
   16012         // safe to free its copy of the display list as it knows that we will
   16013         // push an updated DisplayList if we try to draw again
   16014         resetDisplayList();
   16015     }
   16016 
   16017     /**
   16018      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
   16019      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
   16020      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
   16021      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
   16022      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
   16023      * null.</p>
   16024      *
   16025      * <p>Enabling the drawing cache is similar to
   16026      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
   16027      * acceleration is turned off. When hardware acceleration is turned on, enabling the
   16028      * drawing cache has no effect on rendering because the system uses a different mechanism
   16029      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
   16030      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
   16031      * for information on how to enable software and hardware layers.</p>
   16032      *
   16033      * <p>This API can be used to manually generate
   16034      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
   16035      * {@link #getDrawingCache()}.</p>
   16036      *
   16037      * @param enabled true to enable the drawing cache, false otherwise
   16038      *
   16039      * @see #isDrawingCacheEnabled()
   16040      * @see #getDrawingCache()
   16041      * @see #buildDrawingCache()
   16042      * @see #setLayerType(int, android.graphics.Paint)
   16043      */
   16044     public void setDrawingCacheEnabled(boolean enabled) {
   16045         mCachingFailed = false;
   16046         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
   16047     }
   16048 
   16049     /**
   16050      * <p>Indicates whether the drawing cache is enabled for this view.</p>
   16051      *
   16052      * @return true if the drawing cache is enabled
   16053      *
   16054      * @see #setDrawingCacheEnabled(boolean)
   16055      * @see #getDrawingCache()
   16056      */
   16057     @ViewDebug.ExportedProperty(category = "drawing")
   16058     public boolean isDrawingCacheEnabled() {
   16059         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
   16060     }
   16061 
   16062     /**
   16063      * Debugging utility which recursively outputs the dirty state of a view and its
   16064      * descendants.
   16065      *
   16066      * @hide
   16067      */
   16068     @SuppressWarnings({"UnusedDeclaration"})
   16069     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
   16070         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
   16071                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
   16072                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
   16073                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
   16074         if (clear) {
   16075             mPrivateFlags &= clearMask;
   16076         }
   16077         if (this instanceof ViewGroup) {
   16078             ViewGroup parent = (ViewGroup) this;
   16079             final int count = parent.getChildCount();
   16080             for (int i = 0; i < count; i++) {
   16081                 final View child = parent.getChildAt(i);
   16082                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
   16083             }
   16084         }
   16085     }
   16086 
   16087     /**
   16088      * This method is used by ViewGroup to cause its children to restore or recreate their
   16089      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
   16090      * to recreate its own display list, which would happen if it went through the normal
   16091      * draw/dispatchDraw mechanisms.
   16092      *
   16093      * @hide
   16094      */
   16095     protected void dispatchGetDisplayList() {}
   16096 
   16097     /**
   16098      * A view that is not attached or hardware accelerated cannot create a display list.
   16099      * This method checks these conditions and returns the appropriate result.
   16100      *
   16101      * @return true if view has the ability to create a display list, false otherwise.
   16102      *
   16103      * @hide
   16104      */
   16105     public boolean canHaveDisplayList() {
   16106         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
   16107     }
   16108 
   16109     /**
   16110      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
   16111      * @hide
   16112      */
   16113     @NonNull
   16114     public RenderNode updateDisplayListIfDirty() {
   16115         final RenderNode renderNode = mRenderNode;
   16116         if (!canHaveDisplayList()) {
   16117             // can't populate RenderNode, don't try
   16118             return renderNode;
   16119         }
   16120 
   16121         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
   16122                 || !renderNode.isValid()
   16123                 || (mRecreateDisplayList)) {
   16124             // Don't need to recreate the display list, just need to tell our
   16125             // children to restore/recreate theirs
   16126             if (renderNode.isValid()
   16127                     && !mRecreateDisplayList) {
   16128                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   16129                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16130                 dispatchGetDisplayList();
   16131 
   16132                 return renderNode; // no work needed
   16133             }
   16134 
   16135             // If we got here, we're recreating it. Mark it as such to ensure that
   16136             // we copy in child display lists into ours in drawChild()
   16137             mRecreateDisplayList = true;
   16138 
   16139             int width = mRight - mLeft;
   16140             int height = mBottom - mTop;
   16141             int layerType = getLayerType();
   16142 
   16143             final DisplayListCanvas canvas = renderNode.start(width, height);
   16144             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
   16145 
   16146             try {
   16147                 if (layerType == LAYER_TYPE_SOFTWARE) {
   16148                     buildDrawingCache(true);
   16149                     Bitmap cache = getDrawingCache(true);
   16150                     if (cache != null) {
   16151                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
   16152                     }
   16153                 } else {
   16154                     computeScroll();
   16155 
   16156                     canvas.translate(-mScrollX, -mScrollY);
   16157                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   16158                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16159 
   16160                     // Fast path for layouts with no backgrounds
   16161                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   16162                         dispatchDraw(canvas);
   16163                         if (mOverlay != null && !mOverlay.isEmpty()) {
   16164                             mOverlay.getOverlayView().draw(canvas);
   16165                         }
   16166                     } else {
   16167                         draw(canvas);
   16168                     }
   16169                 }
   16170             } finally {
   16171                 renderNode.end(canvas);
   16172                 setDisplayListProperties(renderNode);
   16173             }
   16174         } else {
   16175             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   16176             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16177         }
   16178         return renderNode;
   16179     }
   16180 
   16181     private void resetDisplayList() {
   16182         if (mRenderNode.isValid()) {
   16183             mRenderNode.discardDisplayList();
   16184         }
   16185 
   16186         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
   16187             mBackgroundRenderNode.discardDisplayList();
   16188         }
   16189     }
   16190 
   16191     /**
   16192      * Called when the passed RenderNode is removed from the draw tree
   16193      * @hide
   16194      */
   16195     public void onRenderNodeDetached(RenderNode renderNode) {
   16196     }
   16197 
   16198     /**
   16199      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
   16200      *
   16201      * @return A non-scaled bitmap representing this view or null if cache is disabled.
   16202      *
   16203      * @see #getDrawingCache(boolean)
   16204      */
   16205     public Bitmap getDrawingCache() {
   16206         return getDrawingCache(false);
   16207     }
   16208 
   16209     /**
   16210      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
   16211      * is null when caching is disabled. If caching is enabled and the cache is not ready,
   16212      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
   16213      * draw from the cache when the cache is enabled. To benefit from the cache, you must
   16214      * request the drawing cache by calling this method and draw it on screen if the
   16215      * returned bitmap is not null.</p>
   16216      *
   16217      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   16218      * this method will create a bitmap of the same size as this view. Because this bitmap
   16219      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   16220      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   16221      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   16222      * size than the view. This implies that your application must be able to handle this
   16223      * size.</p>
   16224      *
   16225      * @param autoScale Indicates whether the generated bitmap should be scaled based on
   16226      *        the current density of the screen when the application is in compatibility
   16227      *        mode.
   16228      *
   16229      * @return A bitmap representing this view or null if cache is disabled.
   16230      *
   16231      * @see #setDrawingCacheEnabled(boolean)
   16232      * @see #isDrawingCacheEnabled()
   16233      * @see #buildDrawingCache(boolean)
   16234      * @see #destroyDrawingCache()
   16235      */
   16236     public Bitmap getDrawingCache(boolean autoScale) {
   16237         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
   16238             return null;
   16239         }
   16240         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
   16241             buildDrawingCache(autoScale);
   16242         }
   16243         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
   16244     }
   16245 
   16246     /**
   16247      * <p>Frees the resources used by the drawing cache. If you call
   16248      * {@link #buildDrawingCache()} manually without calling
   16249      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   16250      * should cleanup the cache with this method afterwards.</p>
   16251      *
   16252      * @see #setDrawingCacheEnabled(boolean)
   16253      * @see #buildDrawingCache()
   16254      * @see #getDrawingCache()
   16255      */
   16256     public void destroyDrawingCache() {
   16257         if (mDrawingCache != null) {
   16258             mDrawingCache.recycle();
   16259             mDrawingCache = null;
   16260         }
   16261         if (mUnscaledDrawingCache != null) {
   16262             mUnscaledDrawingCache.recycle();
   16263             mUnscaledDrawingCache = null;
   16264         }
   16265     }
   16266 
   16267     /**
   16268      * Setting a solid background color for the drawing cache's bitmaps will improve
   16269      * performance and memory usage. Note, though that this should only be used if this
   16270      * view will always be drawn on top of a solid color.
   16271      *
   16272      * @param color The background color to use for the drawing cache's bitmap
   16273      *
   16274      * @see #setDrawingCacheEnabled(boolean)
   16275      * @see #buildDrawingCache()
   16276      * @see #getDrawingCache()
   16277      */
   16278     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
   16279         if (color != mDrawingCacheBackgroundColor) {
   16280             mDrawingCacheBackgroundColor = color;
   16281             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   16282         }
   16283     }
   16284 
   16285     /**
   16286      * @see #setDrawingCacheBackgroundColor(int)
   16287      *
   16288      * @return The background color to used for the drawing cache's bitmap
   16289      */
   16290     @ColorInt
   16291     public int getDrawingCacheBackgroundColor() {
   16292         return mDrawingCacheBackgroundColor;
   16293     }
   16294 
   16295     /**
   16296      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
   16297      *
   16298      * @see #buildDrawingCache(boolean)
   16299      */
   16300     public void buildDrawingCache() {
   16301         buildDrawingCache(false);
   16302     }
   16303 
   16304     /**
   16305      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
   16306      *
   16307      * <p>If you call {@link #buildDrawingCache()} manually without calling
   16308      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   16309      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
   16310      *
   16311      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   16312      * this method will create a bitmap of the same size as this view. Because this bitmap
   16313      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   16314      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   16315      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   16316      * size than the view. This implies that your application must be able to handle this
   16317      * size.</p>
   16318      *
   16319      * <p>You should avoid calling this method when hardware acceleration is enabled. If
   16320      * you do not need the drawing cache bitmap, calling this method will increase memory
   16321      * usage and cause the view to be rendered in software once, thus negatively impacting
   16322      * performance.</p>
   16323      *
   16324      * @see #getDrawingCache()
   16325      * @see #destroyDrawingCache()
   16326      */
   16327     public void buildDrawingCache(boolean autoScale) {
   16328         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
   16329                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
   16330             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
   16331                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
   16332                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
   16333             }
   16334             try {
   16335                 buildDrawingCacheImpl(autoScale);
   16336             } finally {
   16337                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
   16338             }
   16339         }
   16340     }
   16341 
   16342     /**
   16343      * private, internal implementation of buildDrawingCache, used to enable tracing
   16344      */
   16345     private void buildDrawingCacheImpl(boolean autoScale) {
   16346         mCachingFailed = false;
   16347 
   16348         int width = mRight - mLeft;
   16349         int height = mBottom - mTop;
   16350 
   16351         final AttachInfo attachInfo = mAttachInfo;
   16352         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
   16353 
   16354         if (autoScale && scalingRequired) {
   16355             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
   16356             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
   16357         }
   16358 
   16359         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
   16360         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
   16361         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
   16362 
   16363         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
   16364         final long drawingCacheSize =
   16365                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
   16366         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
   16367             if (width > 0 && height > 0) {
   16368                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
   16369                         + " too large to fit into a software layer (or drawing cache), needs "
   16370                         + projectedBitmapSize + " bytes, only "
   16371                         + drawingCacheSize + " available");
   16372             }
   16373             destroyDrawingCache();
   16374             mCachingFailed = true;
   16375             return;
   16376         }
   16377 
   16378         boolean clear = true;
   16379         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
   16380 
   16381         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
   16382             Bitmap.Config quality;
   16383             if (!opaque) {
   16384                 // Never pick ARGB_4444 because it looks awful
   16385                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
   16386                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
   16387                     case DRAWING_CACHE_QUALITY_AUTO:
   16388                     case DRAWING_CACHE_QUALITY_LOW:
   16389                     case DRAWING_CACHE_QUALITY_HIGH:
   16390                     default:
   16391                         quality = Bitmap.Config.ARGB_8888;
   16392                         break;
   16393                 }
   16394             } else {
   16395                 // Optimization for translucent windows
   16396                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
   16397                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
   16398             }
   16399 
   16400             // Try to cleanup memory
   16401             if (bitmap != null) bitmap.recycle();
   16402 
   16403             try {
   16404                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
   16405                         width, height, quality);
   16406                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
   16407                 if (autoScale) {
   16408                     mDrawingCache = bitmap;
   16409                 } else {
   16410                     mUnscaledDrawingCache = bitmap;
   16411                 }
   16412                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
   16413             } catch (OutOfMemoryError e) {
   16414                 // If there is not enough memory to create the bitmap cache, just
   16415                 // ignore the issue as bitmap caches are not required to draw the
   16416                 // view hierarchy
   16417                 if (autoScale) {
   16418                     mDrawingCache = null;
   16419                 } else {
   16420                     mUnscaledDrawingCache = null;
   16421                 }
   16422                 mCachingFailed = true;
   16423                 return;
   16424             }
   16425 
   16426             clear = drawingCacheBackgroundColor != 0;
   16427         }
   16428 
   16429         Canvas canvas;
   16430         if (attachInfo != null) {
   16431             canvas = attachInfo.mCanvas;
   16432             if (canvas == null) {
   16433                 canvas = new Canvas();
   16434             }
   16435             canvas.setBitmap(bitmap);
   16436             // Temporarily clobber the cached Canvas in case one of our children
   16437             // is also using a drawing cache. Without this, the children would
   16438             // steal the canvas by attaching their own bitmap to it and bad, bad
   16439             // thing would happen (invisible views, corrupted drawings, etc.)
   16440             attachInfo.mCanvas = null;
   16441         } else {
   16442             // This case should hopefully never or seldom happen
   16443             canvas = new Canvas(bitmap);
   16444         }
   16445 
   16446         if (clear) {
   16447             bitmap.eraseColor(drawingCacheBackgroundColor);
   16448         }
   16449 
   16450         computeScroll();
   16451         final int restoreCount = canvas.save();
   16452 
   16453         if (autoScale && scalingRequired) {
   16454             final float scale = attachInfo.mApplicationScale;
   16455             canvas.scale(scale, scale);
   16456         }
   16457 
   16458         canvas.translate(-mScrollX, -mScrollY);
   16459 
   16460         mPrivateFlags |= PFLAG_DRAWN;
   16461         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
   16462                 mLayerType != LAYER_TYPE_NONE) {
   16463             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
   16464         }
   16465 
   16466         // Fast path for layouts with no backgrounds
   16467         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   16468             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16469             dispatchDraw(canvas);
   16470             if (mOverlay != null && !mOverlay.isEmpty()) {
   16471                 mOverlay.getOverlayView().draw(canvas);
   16472             }
   16473         } else {
   16474             draw(canvas);
   16475         }
   16476 
   16477         canvas.restoreToCount(restoreCount);
   16478         canvas.setBitmap(null);
   16479 
   16480         if (attachInfo != null) {
   16481             // Restore the cached Canvas for our siblings
   16482             attachInfo.mCanvas = canvas;
   16483         }
   16484     }
   16485 
   16486     /**
   16487      * Create a snapshot of the view into a bitmap.  We should probably make
   16488      * some form of this public, but should think about the API.
   16489      *
   16490      * @hide
   16491      */
   16492     public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
   16493         int width = mRight - mLeft;
   16494         int height = mBottom - mTop;
   16495 
   16496         final AttachInfo attachInfo = mAttachInfo;
   16497         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
   16498         width = (int) ((width * scale) + 0.5f);
   16499         height = (int) ((height * scale) + 0.5f);
   16500 
   16501         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
   16502                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
   16503         if (bitmap == null) {
   16504             throw new OutOfMemoryError();
   16505         }
   16506 
   16507         Resources resources = getResources();
   16508         if (resources != null) {
   16509             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
   16510         }
   16511 
   16512         Canvas canvas;
   16513         if (attachInfo != null) {
   16514             canvas = attachInfo.mCanvas;
   16515             if (canvas == null) {
   16516                 canvas = new Canvas();
   16517             }
   16518             canvas.setBitmap(bitmap);
   16519             // Temporarily clobber the cached Canvas in case one of our children
   16520             // is also using a drawing cache. Without this, the children would
   16521             // steal the canvas by attaching their own bitmap to it and bad, bad
   16522             // things would happen (invisible views, corrupted drawings, etc.)
   16523             attachInfo.mCanvas = null;
   16524         } else {
   16525             // This case should hopefully never or seldom happen
   16526             canvas = new Canvas(bitmap);
   16527         }
   16528 
   16529         if ((backgroundColor & 0xff000000) != 0) {
   16530             bitmap.eraseColor(backgroundColor);
   16531         }
   16532 
   16533         computeScroll();
   16534         final int restoreCount = canvas.save();
   16535         canvas.scale(scale, scale);
   16536         canvas.translate(-mScrollX, -mScrollY);
   16537 
   16538         // Temporarily remove the dirty mask
   16539         int flags = mPrivateFlags;
   16540         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16541 
   16542         // Fast path for layouts with no backgrounds
   16543         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   16544             dispatchDraw(canvas);
   16545             if (mOverlay != null && !mOverlay.isEmpty()) {
   16546                 mOverlay.getOverlayView().draw(canvas);
   16547             }
   16548         } else {
   16549             draw(canvas);
   16550         }
   16551 
   16552         mPrivateFlags = flags;
   16553 
   16554         canvas.restoreToCount(restoreCount);
   16555         canvas.setBitmap(null);
   16556 
   16557         if (attachInfo != null) {
   16558             // Restore the cached Canvas for our siblings
   16559             attachInfo.mCanvas = canvas;
   16560         }
   16561 
   16562         return bitmap;
   16563     }
   16564 
   16565     /**
   16566      * Indicates whether this View is currently in edit mode. A View is usually
   16567      * in edit mode when displayed within a developer tool. For instance, if
   16568      * this View is being drawn by a visual user interface builder, this method
   16569      * should return true.
   16570      *
   16571      * Subclasses should check the return value of this method to provide
   16572      * different behaviors if their normal behavior might interfere with the
   16573      * host environment. For instance: the class spawns a thread in its
   16574      * constructor, the drawing code relies on device-specific features, etc.
   16575      *
   16576      * This method is usually checked in the drawing code of custom widgets.
   16577      *
   16578      * @return True if this View is in edit mode, false otherwise.
   16579      */
   16580     public boolean isInEditMode() {
   16581         return false;
   16582     }
   16583 
   16584     /**
   16585      * If the View draws content inside its padding and enables fading edges,
   16586      * it needs to support padding offsets. Padding offsets are added to the
   16587      * fading edges to extend the length of the fade so that it covers pixels
   16588      * drawn inside the padding.
   16589      *
   16590      * Subclasses of this class should override this method if they need
   16591      * to draw content inside the padding.
   16592      *
   16593      * @return True if padding offset must be applied, false otherwise.
   16594      *
   16595      * @see #getLeftPaddingOffset()
   16596      * @see #getRightPaddingOffset()
   16597      * @see #getTopPaddingOffset()
   16598      * @see #getBottomPaddingOffset()
   16599      *
   16600      * @since CURRENT
   16601      */
   16602     protected boolean isPaddingOffsetRequired() {
   16603         return false;
   16604     }
   16605 
   16606     /**
   16607      * Amount by which to extend the left fading region. Called only when
   16608      * {@link #isPaddingOffsetRequired()} returns true.
   16609      *
   16610      * @return The left padding offset in pixels.
   16611      *
   16612      * @see #isPaddingOffsetRequired()
   16613      *
   16614      * @since CURRENT
   16615      */
   16616     protected int getLeftPaddingOffset() {
   16617         return 0;
   16618     }
   16619 
   16620     /**
   16621      * Amount by which to extend the right fading region. Called only when
   16622      * {@link #isPaddingOffsetRequired()} returns true.
   16623      *
   16624      * @return The right padding offset in pixels.
   16625      *
   16626      * @see #isPaddingOffsetRequired()
   16627      *
   16628      * @since CURRENT
   16629      */
   16630     protected int getRightPaddingOffset() {
   16631         return 0;
   16632     }
   16633 
   16634     /**
   16635      * Amount by which to extend the top fading region. Called only when
   16636      * {@link #isPaddingOffsetRequired()} returns true.
   16637      *
   16638      * @return The top padding offset in pixels.
   16639      *
   16640      * @see #isPaddingOffsetRequired()
   16641      *
   16642      * @since CURRENT
   16643      */
   16644     protected int getTopPaddingOffset() {
   16645         return 0;
   16646     }
   16647 
   16648     /**
   16649      * Amount by which to extend the bottom fading region. Called only when
   16650      * {@link #isPaddingOffsetRequired()} returns true.
   16651      *
   16652      * @return The bottom padding offset in pixels.
   16653      *
   16654      * @see #isPaddingOffsetRequired()
   16655      *
   16656      * @since CURRENT
   16657      */
   16658     protected int getBottomPaddingOffset() {
   16659         return 0;
   16660     }
   16661 
   16662     /**
   16663      * @hide
   16664      * @param offsetRequired
   16665      */
   16666     protected int getFadeTop(boolean offsetRequired) {
   16667         int top = mPaddingTop;
   16668         if (offsetRequired) top += getTopPaddingOffset();
   16669         return top;
   16670     }
   16671 
   16672     /**
   16673      * @hide
   16674      * @param offsetRequired
   16675      */
   16676     protected int getFadeHeight(boolean offsetRequired) {
   16677         int padding = mPaddingTop;
   16678         if (offsetRequired) padding += getTopPaddingOffset();
   16679         return mBottom - mTop - mPaddingBottom - padding;
   16680     }
   16681 
   16682     /**
   16683      * <p>Indicates whether this view is attached to a hardware accelerated
   16684      * window or not.</p>
   16685      *
   16686      * <p>Even if this method returns true, it does not mean that every call
   16687      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
   16688      * accelerated {@link android.graphics.Canvas}. For instance, if this view
   16689      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
   16690      * window is hardware accelerated,
   16691      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
   16692      * return false, and this method will return true.</p>
   16693      *
   16694      * @return True if the view is attached to a window and the window is
   16695      *         hardware accelerated; false in any other case.
   16696      */
   16697     @ViewDebug.ExportedProperty(category = "drawing")
   16698     public boolean isHardwareAccelerated() {
   16699         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
   16700     }
   16701 
   16702     /**
   16703      * Sets a rectangular area on this view to which the view will be clipped
   16704      * when it is drawn. Setting the value to null will remove the clip bounds
   16705      * and the view will draw normally, using its full bounds.
   16706      *
   16707      * @param clipBounds The rectangular area, in the local coordinates of
   16708      * this view, to which future drawing operations will be clipped.
   16709      */
   16710     public void setClipBounds(Rect clipBounds) {
   16711         if (clipBounds == mClipBounds
   16712                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
   16713             return;
   16714         }
   16715         if (clipBounds != null) {
   16716             if (mClipBounds == null) {
   16717                 mClipBounds = new Rect(clipBounds);
   16718             } else {
   16719                 mClipBounds.set(clipBounds);
   16720             }
   16721         } else {
   16722             mClipBounds = null;
   16723         }
   16724         mRenderNode.setClipBounds(mClipBounds);
   16725         invalidateViewProperty(false, false);
   16726     }
   16727 
   16728     /**
   16729      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
   16730      *
   16731      * @return A copy of the current clip bounds if clip bounds are set,
   16732      * otherwise null.
   16733      */
   16734     public Rect getClipBounds() {
   16735         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
   16736     }
   16737 
   16738 
   16739     /**
   16740      * Populates an output rectangle with the clip bounds of the view,
   16741      * returning {@code true} if successful or {@code false} if the view's
   16742      * clip bounds are {@code null}.
   16743      *
   16744      * @param outRect rectangle in which to place the clip bounds of the view
   16745      * @return {@code true} if successful or {@code false} if the view's
   16746      *         clip bounds are {@code null}
   16747      */
   16748     public boolean getClipBounds(Rect outRect) {
   16749         if (mClipBounds != null) {
   16750             outRect.set(mClipBounds);
   16751             return true;
   16752         }
   16753         return false;
   16754     }
   16755 
   16756     /**
   16757      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
   16758      * case of an active Animation being run on the view.
   16759      */
   16760     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
   16761             Animation a, boolean scalingRequired) {
   16762         Transformation invalidationTransform;
   16763         final int flags = parent.mGroupFlags;
   16764         final boolean initialized = a.isInitialized();
   16765         if (!initialized) {
   16766             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
   16767             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
   16768             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
   16769             onAnimationStart();
   16770         }
   16771 
   16772         final Transformation t = parent.getChildTransformation();
   16773         boolean more = a.getTransformation(drawingTime, t, 1f);
   16774         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
   16775             if (parent.mInvalidationTransformation == null) {
   16776                 parent.mInvalidationTransformation = new Transformation();
   16777             }
   16778             invalidationTransform = parent.mInvalidationTransformation;
   16779             a.getTransformation(drawingTime, invalidationTransform, 1f);
   16780         } else {
   16781             invalidationTransform = t;
   16782         }
   16783 
   16784         if (more) {
   16785             if (!a.willChangeBounds()) {
   16786                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
   16787                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
   16788                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
   16789                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
   16790                     // The child need to draw an animation, potentially offscreen, so
   16791                     // make sure we do not cancel invalidate requests
   16792                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   16793                     parent.invalidate(mLeft, mTop, mRight, mBottom);
   16794                 }
   16795             } else {
   16796                 if (parent.mInvalidateRegion == null) {
   16797                     parent.mInvalidateRegion = new RectF();
   16798                 }
   16799                 final RectF region = parent.mInvalidateRegion;
   16800                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
   16801                         invalidationTransform);
   16802 
   16803                 // The child need to draw an animation, potentially offscreen, so
   16804                 // make sure we do not cancel invalidate requests
   16805                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   16806 
   16807                 final int left = mLeft + (int) region.left;
   16808                 final int top = mTop + (int) region.top;
   16809                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
   16810                         top + (int) (region.height() + .5f));
   16811             }
   16812         }
   16813         return more;
   16814     }
   16815 
   16816     /**
   16817      * This method is called by getDisplayList() when a display list is recorded for a View.
   16818      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
   16819      */
   16820     void setDisplayListProperties(RenderNode renderNode) {
   16821         if (renderNode != null) {
   16822             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
   16823             renderNode.setClipToBounds(mParent instanceof ViewGroup
   16824                     && ((ViewGroup) mParent).getClipChildren());
   16825 
   16826             float alpha = 1;
   16827             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
   16828                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   16829                 ViewGroup parentVG = (ViewGroup) mParent;
   16830                 final Transformation t = parentVG.getChildTransformation();
   16831                 if (parentVG.getChildStaticTransformation(this, t)) {
   16832                     final int transformType = t.getTransformationType();
   16833                     if (transformType != Transformation.TYPE_IDENTITY) {
   16834                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
   16835                             alpha = t.getAlpha();
   16836                         }
   16837                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
   16838                             renderNode.setStaticMatrix(t.getMatrix());
   16839                         }
   16840                     }
   16841                 }
   16842             }
   16843             if (mTransformationInfo != null) {
   16844                 alpha *= getFinalAlpha();
   16845                 if (alpha < 1) {
   16846                     final int multipliedAlpha = (int) (255 * alpha);
   16847                     if (onSetAlpha(multipliedAlpha)) {
   16848                         alpha = 1;
   16849                     }
   16850                 }
   16851                 renderNode.setAlpha(alpha);
   16852             } else if (alpha < 1) {
   16853                 renderNode.setAlpha(alpha);
   16854             }
   16855         }
   16856     }
   16857 
   16858     /**
   16859      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
   16860      *
   16861      * This is where the View specializes rendering behavior based on layer type,
   16862      * and hardware acceleration.
   16863      */
   16864     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
   16865         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
   16866         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
   16867          *
   16868          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
   16869          * HW accelerated, it can't handle drawing RenderNodes.
   16870          */
   16871         boolean drawingWithRenderNode = mAttachInfo != null
   16872                 && mAttachInfo.mHardwareAccelerated
   16873                 && hardwareAcceleratedCanvas;
   16874 
   16875         boolean more = false;
   16876         final boolean childHasIdentityMatrix = hasIdentityMatrix();
   16877         final int parentFlags = parent.mGroupFlags;
   16878 
   16879         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
   16880             parent.getChildTransformation().clear();
   16881             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   16882         }
   16883 
   16884         Transformation transformToApply = null;
   16885         boolean concatMatrix = false;
   16886         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
   16887         final Animation a = getAnimation();
   16888         if (a != null) {
   16889             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
   16890             concatMatrix = a.willChangeTransformationMatrix();
   16891             if (concatMatrix) {
   16892                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   16893             }
   16894             transformToApply = parent.getChildTransformation();
   16895         } else {
   16896             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
   16897                 // No longer animating: clear out old animation matrix
   16898                 mRenderNode.setAnimationMatrix(null);
   16899                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   16900             }
   16901             if (!drawingWithRenderNode
   16902                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   16903                 final Transformation t = parent.getChildTransformation();
   16904                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
   16905                 if (hasTransform) {
   16906                     final int transformType = t.getTransformationType();
   16907                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
   16908                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
   16909                 }
   16910             }
   16911         }
   16912 
   16913         concatMatrix |= !childHasIdentityMatrix;
   16914 
   16915         // Sets the flag as early as possible to allow draw() implementations
   16916         // to call invalidate() successfully when doing animations
   16917         mPrivateFlags |= PFLAG_DRAWN;
   16918 
   16919         if (!concatMatrix &&
   16920                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
   16921                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
   16922                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
   16923                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
   16924             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
   16925             return more;
   16926         }
   16927         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
   16928 
   16929         if (hardwareAcceleratedCanvas) {
   16930             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
   16931             // retain the flag's value temporarily in the mRecreateDisplayList flag
   16932             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
   16933             mPrivateFlags &= ~PFLAG_INVALIDATED;
   16934         }
   16935 
   16936         RenderNode renderNode = null;
   16937         Bitmap cache = null;
   16938         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
   16939         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
   16940              if (layerType != LAYER_TYPE_NONE) {
   16941                  // If not drawing with RenderNode, treat HW layers as SW
   16942                  layerType = LAYER_TYPE_SOFTWARE;
   16943                  buildDrawingCache(true);
   16944             }
   16945             cache = getDrawingCache(true);
   16946         }
   16947 
   16948         if (drawingWithRenderNode) {
   16949             // Delay getting the display list until animation-driven alpha values are
   16950             // set up and possibly passed on to the view
   16951             renderNode = updateDisplayListIfDirty();
   16952             if (!renderNode.isValid()) {
   16953                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
   16954                 // to getDisplayList(), the display list will be marked invalid and we should not
   16955                 // try to use it again.
   16956                 renderNode = null;
   16957                 drawingWithRenderNode = false;
   16958             }
   16959         }
   16960 
   16961         int sx = 0;
   16962         int sy = 0;
   16963         if (!drawingWithRenderNode) {
   16964             computeScroll();
   16965             sx = mScrollX;
   16966             sy = mScrollY;
   16967         }
   16968 
   16969         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
   16970         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
   16971 
   16972         int restoreTo = -1;
   16973         if (!drawingWithRenderNode || transformToApply != null) {
   16974             restoreTo = canvas.save();
   16975         }
   16976         if (offsetForScroll) {
   16977             canvas.translate(mLeft - sx, mTop - sy);
   16978         } else {
   16979             if (!drawingWithRenderNode) {
   16980                 canvas.translate(mLeft, mTop);
   16981             }
   16982             if (scalingRequired) {
   16983                 if (drawingWithRenderNode) {
   16984                     // TODO: Might not need this if we put everything inside the DL
   16985                     restoreTo = canvas.save();
   16986                 }
   16987                 // mAttachInfo cannot be null, otherwise scalingRequired == false
   16988                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
   16989                 canvas.scale(scale, scale);
   16990             }
   16991         }
   16992 
   16993         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
   16994         if (transformToApply != null
   16995                 || alpha < 1
   16996                 || !hasIdentityMatrix()
   16997                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   16998             if (transformToApply != null || !childHasIdentityMatrix) {
   16999                 int transX = 0;
   17000                 int transY = 0;
   17001 
   17002                 if (offsetForScroll) {
   17003                     transX = -sx;
   17004                     transY = -sy;
   17005                 }
   17006 
   17007                 if (transformToApply != null) {
   17008                     if (concatMatrix) {
   17009                         if (drawingWithRenderNode) {
   17010                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
   17011                         } else {
   17012                             // Undo the scroll translation, apply the transformation matrix,
   17013                             // then redo the scroll translate to get the correct result.
   17014                             canvas.translate(-transX, -transY);
   17015                             canvas.concat(transformToApply.getMatrix());
   17016                             canvas.translate(transX, transY);
   17017                         }
   17018                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   17019                     }
   17020 
   17021                     float transformAlpha = transformToApply.getAlpha();
   17022                     if (transformAlpha < 1) {
   17023                         alpha *= transformAlpha;
   17024                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   17025                     }
   17026                 }
   17027 
   17028                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
   17029                     canvas.translate(-transX, -transY);
   17030                     canvas.concat(getMatrix());
   17031                     canvas.translate(transX, transY);
   17032                 }
   17033             }
   17034 
   17035             // Deal with alpha if it is or used to be <1
   17036             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   17037                 if (alpha < 1) {
   17038                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   17039                 } else {
   17040                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   17041                 }
   17042                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   17043                 if (!drawingWithDrawingCache) {
   17044                     final int multipliedAlpha = (int) (255 * alpha);
   17045                     if (!onSetAlpha(multipliedAlpha)) {
   17046                         if (drawingWithRenderNode) {
   17047                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
   17048                         } else if (layerType == LAYER_TYPE_NONE) {
   17049                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
   17050                                     multipliedAlpha);
   17051                         }
   17052                     } else {
   17053                         // Alpha is handled by the child directly, clobber the layer's alpha
   17054                         mPrivateFlags |= PFLAG_ALPHA_SET;
   17055                     }
   17056                 }
   17057             }
   17058         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   17059             onSetAlpha(255);
   17060             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   17061         }
   17062 
   17063         if (!drawingWithRenderNode) {
   17064             // apply clips directly, since RenderNode won't do it for this draw
   17065             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
   17066                 if (offsetForScroll) {
   17067                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
   17068                 } else {
   17069                     if (!scalingRequired || cache == null) {
   17070                         canvas.clipRect(0, 0, getWidth(), getHeight());
   17071                     } else {
   17072                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
   17073                     }
   17074                 }
   17075             }
   17076 
   17077             if (mClipBounds != null) {
   17078                 // clip bounds ignore scroll
   17079                 canvas.clipRect(mClipBounds);
   17080             }
   17081         }
   17082 
   17083         if (!drawingWithDrawingCache) {
   17084             if (drawingWithRenderNode) {
   17085                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   17086                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
   17087             } else {
   17088                 // Fast path for layouts with no backgrounds
   17089                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   17090                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   17091                     dispatchDraw(canvas);
   17092                 } else {
   17093                     draw(canvas);
   17094                 }
   17095             }
   17096         } else if (cache != null) {
   17097             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   17098             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
   17099                 // no layer paint, use temporary paint to draw bitmap
   17100                 Paint cachePaint = parent.mCachePaint;
   17101                 if (cachePaint == null) {
   17102                     cachePaint = new Paint();
   17103                     cachePaint.setDither(false);
   17104                     parent.mCachePaint = cachePaint;
   17105                 }
   17106                 cachePaint.setAlpha((int) (alpha * 255));
   17107                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
   17108             } else {
   17109                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
   17110                 int layerPaintAlpha = mLayerPaint.getAlpha();
   17111                 if (alpha < 1) {
   17112                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
   17113                 }
   17114                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
   17115                 if (alpha < 1) {
   17116                     mLayerPaint.setAlpha(layerPaintAlpha);
   17117                 }
   17118             }
   17119         }
   17120 
   17121         if (restoreTo >= 0) {
   17122             canvas.restoreToCount(restoreTo);
   17123         }
   17124 
   17125         if (a != null && !more) {
   17126             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
   17127                 onSetAlpha(255);
   17128             }
   17129             parent.finishAnimatingView(this, a);
   17130         }
   17131 
   17132         if (more && hardwareAcceleratedCanvas) {
   17133             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   17134                 // alpha animations should cause the child to recreate its display list
   17135                 invalidate(true);
   17136             }
   17137         }
   17138 
   17139         mRecreateDisplayList = false;
   17140 
   17141         return more;
   17142     }
   17143 
   17144     /**
   17145      * Manually render this view (and all of its children) to the given Canvas.
   17146      * The view must have already done a full layout before this function is
   17147      * called.  When implementing a view, implement
   17148      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
   17149      * If you do need to override this method, call the superclass version.
   17150      *
   17151      * @param canvas The Canvas to which the View is rendered.
   17152      */
   17153     @CallSuper
   17154     public void draw(Canvas canvas) {
   17155         final int privateFlags = mPrivateFlags;
   17156         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
   17157                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
   17158         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
   17159 
   17160         /*
   17161          * Draw traversal performs several drawing steps which must be executed
   17162          * in the appropriate order:
   17163          *
   17164          *      1. Draw the background
   17165          *      2. If necessary, save the canvas' layers to prepare for fading
   17166          *      3. Draw view's content
   17167          *      4. Draw children
   17168          *      5. If necessary, draw the fading edges and restore layers
   17169          *      6. Draw decorations (scrollbars for instance)
   17170          */
   17171 
   17172         // Step 1, draw the background, if needed
   17173         int saveCount;
   17174 
   17175         if (!dirtyOpaque) {
   17176             drawBackground(canvas);
   17177         }
   17178 
   17179         // skip step 2 & 5 if possible (common case)
   17180         final int viewFlags = mViewFlags;
   17181         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
   17182         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
   17183         if (!verticalEdges && !horizontalEdges) {
   17184             // Step 3, draw the content
   17185             if (!dirtyOpaque) onDraw(canvas);
   17186 
   17187             // Step 4, draw the children
   17188             dispatchDraw(canvas);
   17189 
   17190             // Overlay is part of the content and draws beneath Foreground
   17191             if (mOverlay != null && !mOverlay.isEmpty()) {
   17192                 mOverlay.getOverlayView().dispatchDraw(canvas);
   17193             }
   17194 
   17195             // Step 6, draw decorations (foreground, scrollbars)
   17196             onDrawForeground(canvas);
   17197 
   17198             // we're done...
   17199             return;
   17200         }
   17201 
   17202         /*
   17203          * Here we do the full fledged routine...
   17204          * (this is an uncommon case where speed matters less,
   17205          * this is why we repeat some of the tests that have been
   17206          * done above)
   17207          */
   17208 
   17209         boolean drawTop = false;
   17210         boolean drawBottom = false;
   17211         boolean drawLeft = false;
   17212         boolean drawRight = false;
   17213 
   17214         float topFadeStrength = 0.0f;
   17215         float bottomFadeStrength = 0.0f;
   17216         float leftFadeStrength = 0.0f;
   17217         float rightFadeStrength = 0.0f;
   17218 
   17219         // Step 2, save the canvas' layers
   17220         int paddingLeft = mPaddingLeft;
   17221 
   17222         final boolean offsetRequired = isPaddingOffsetRequired();
   17223         if (offsetRequired) {
   17224             paddingLeft += getLeftPaddingOffset();
   17225         }
   17226 
   17227         int left = mScrollX + paddingLeft;
   17228         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
   17229         int top = mScrollY + getFadeTop(offsetRequired);
   17230         int bottom = top + getFadeHeight(offsetRequired);
   17231 
   17232         if (offsetRequired) {
   17233             right += getRightPaddingOffset();
   17234             bottom += getBottomPaddingOffset();
   17235         }
   17236 
   17237         final ScrollabilityCache scrollabilityCache = mScrollCache;
   17238         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
   17239         int length = (int) fadeHeight;
   17240 
   17241         // clip the fade length if top and bottom fades overlap
   17242         // overlapping fades produce odd-looking artifacts
   17243         if (verticalEdges && (top + length > bottom - length)) {
   17244             length = (bottom - top) / 2;
   17245         }
   17246 
   17247         // also clip horizontal fades if necessary
   17248         if (horizontalEdges && (left + length > right - length)) {
   17249             length = (right - left) / 2;
   17250         }
   17251 
   17252         if (verticalEdges) {
   17253             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
   17254             drawTop = topFadeStrength * fadeHeight > 1.0f;
   17255             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
   17256             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
   17257         }
   17258 
   17259         if (horizontalEdges) {
   17260             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
   17261             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
   17262             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
   17263             drawRight = rightFadeStrength * fadeHeight > 1.0f;
   17264         }
   17265 
   17266         saveCount = canvas.getSaveCount();
   17267 
   17268         int solidColor = getSolidColor();
   17269         if (solidColor == 0) {
   17270             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
   17271 
   17272             if (drawTop) {
   17273                 canvas.saveLayer(left, top, right, top + length, null, flags);
   17274             }
   17275 
   17276             if (drawBottom) {
   17277                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
   17278             }
   17279 
   17280             if (drawLeft) {
   17281                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
   17282             }
   17283 
   17284             if (drawRight) {
   17285                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
   17286             }
   17287         } else {
   17288             scrollabilityCache.setFadeColor(solidColor);
   17289         }
   17290 
   17291         // Step 3, draw the content
   17292         if (!dirtyOpaque) onDraw(canvas);
   17293 
   17294         // Step 4, draw the children
   17295         dispatchDraw(canvas);
   17296 
   17297         // Step 5, draw the fade effect and restore layers
   17298         final Paint p = scrollabilityCache.paint;
   17299         final Matrix matrix = scrollabilityCache.matrix;
   17300         final Shader fade = scrollabilityCache.shader;
   17301 
   17302         if (drawTop) {
   17303             matrix.setScale(1, fadeHeight * topFadeStrength);
   17304             matrix.postTranslate(left, top);
   17305             fade.setLocalMatrix(matrix);
   17306             p.setShader(fade);
   17307             canvas.drawRect(left, top, right, top + length, p);
   17308         }
   17309 
   17310         if (drawBottom) {
   17311             matrix.setScale(1, fadeHeight * bottomFadeStrength);
   17312             matrix.postRotate(180);
   17313             matrix.postTranslate(left, bottom);
   17314             fade.setLocalMatrix(matrix);
   17315             p.setShader(fade);
   17316             canvas.drawRect(left, bottom - length, right, bottom, p);
   17317         }
   17318 
   17319         if (drawLeft) {
   17320             matrix.setScale(1, fadeHeight * leftFadeStrength);
   17321             matrix.postRotate(-90);
   17322             matrix.postTranslate(left, top);
   17323             fade.setLocalMatrix(matrix);
   17324             p.setShader(fade);
   17325             canvas.drawRect(left, top, left + length, bottom, p);
   17326         }
   17327 
   17328         if (drawRight) {
   17329             matrix.setScale(1, fadeHeight * rightFadeStrength);
   17330             matrix.postRotate(90);
   17331             matrix.postTranslate(right, top);
   17332             fade.setLocalMatrix(matrix);
   17333             p.setShader(fade);
   17334             canvas.drawRect(right - length, top, right, bottom, p);
   17335         }
   17336 
   17337         canvas.restoreToCount(saveCount);
   17338 
   17339         // Overlay is part of the content and draws beneath Foreground
   17340         if (mOverlay != null && !mOverlay.isEmpty()) {
   17341             mOverlay.getOverlayView().dispatchDraw(canvas);
   17342         }
   17343 
   17344         // Step 6, draw decorations (foreground, scrollbars)
   17345         onDrawForeground(canvas);
   17346     }
   17347 
   17348     /**
   17349      * Draws the background onto the specified canvas.
   17350      *
   17351      * @param canvas Canvas on which to draw the background
   17352      */
   17353     private void drawBackground(Canvas canvas) {
   17354         final Drawable background = mBackground;
   17355         if (background == null) {
   17356             return;
   17357         }
   17358 
   17359         setBackgroundBounds();
   17360 
   17361         // Attempt to use a display list if requested.
   17362         if (canvas.isHardwareAccelerated() && mAttachInfo != null
   17363                 && mAttachInfo.mHardwareRenderer != null) {
   17364             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
   17365 
   17366             final RenderNode renderNode = mBackgroundRenderNode;
   17367             if (renderNode != null && renderNode.isValid()) {
   17368                 setBackgroundRenderNodeProperties(renderNode);
   17369                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
   17370                 return;
   17371             }
   17372         }
   17373 
   17374         final int scrollX = mScrollX;
   17375         final int scrollY = mScrollY;
   17376         if ((scrollX | scrollY) == 0) {
   17377             background.draw(canvas);
   17378         } else {
   17379             canvas.translate(scrollX, scrollY);
   17380             background.draw(canvas);
   17381             canvas.translate(-scrollX, -scrollY);
   17382         }
   17383     }
   17384 
   17385     /**
   17386      * Sets the correct background bounds and rebuilds the outline, if needed.
   17387      * <p/>
   17388      * This is called by LayoutLib.
   17389      */
   17390     void setBackgroundBounds() {
   17391         if (mBackgroundSizeChanged && mBackground != null) {
   17392             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
   17393             mBackgroundSizeChanged = false;
   17394             rebuildOutline();
   17395         }
   17396     }
   17397 
   17398     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
   17399         renderNode.setTranslationX(mScrollX);
   17400         renderNode.setTranslationY(mScrollY);
   17401     }
   17402 
   17403     /**
   17404      * Creates a new display list or updates the existing display list for the
   17405      * specified Drawable.
   17406      *
   17407      * @param drawable Drawable for which to create a display list
   17408      * @param renderNode Existing RenderNode, or {@code null}
   17409      * @return A valid display list for the specified drawable
   17410      */
   17411     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
   17412         if (renderNode == null) {
   17413             renderNode = RenderNode.create(drawable.getClass().getName(), this);
   17414         }
   17415 
   17416         final Rect bounds = drawable.getBounds();
   17417         final int width = bounds.width();
   17418         final int height = bounds.height();
   17419         final DisplayListCanvas canvas = renderNode.start(width, height);
   17420 
   17421         // Reverse left/top translation done by drawable canvas, which will
   17422         // instead be applied by rendernode's LTRB bounds below. This way, the
   17423         // drawable's bounds match with its rendernode bounds and its content
   17424         // will lie within those bounds in the rendernode tree.
   17425         canvas.translate(-bounds.left, -bounds.top);
   17426 
   17427         try {
   17428             drawable.draw(canvas);
   17429         } finally {
   17430             renderNode.end(canvas);
   17431         }
   17432 
   17433         // Set up drawable properties that are view-independent.
   17434         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
   17435         renderNode.setProjectBackwards(drawable.isProjected());
   17436         renderNode.setProjectionReceiver(true);
   17437         renderNode.setClipToBounds(false);
   17438         return renderNode;
   17439     }
   17440 
   17441     /**
   17442      * Returns the overlay for this view, creating it if it does not yet exist.
   17443      * Adding drawables to the overlay will cause them to be displayed whenever
   17444      * the view itself is redrawn. Objects in the overlay should be actively
   17445      * managed: remove them when they should not be displayed anymore. The
   17446      * overlay will always have the same size as its host view.
   17447      *
   17448      * <p>Note: Overlays do not currently work correctly with {@link
   17449      * SurfaceView} or {@link TextureView}; contents in overlays for these
   17450      * types of views may not display correctly.</p>
   17451      *
   17452      * @return The ViewOverlay object for this view.
   17453      * @see ViewOverlay
   17454      */
   17455     public ViewOverlay getOverlay() {
   17456         if (mOverlay == null) {
   17457             mOverlay = new ViewOverlay(mContext, this);
   17458         }
   17459         return mOverlay;
   17460     }
   17461 
   17462     /**
   17463      * Override this if your view is known to always be drawn on top of a solid color background,
   17464      * and needs to draw fading edges. Returning a non-zero color enables the view system to
   17465      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
   17466      * should be set to 0xFF.
   17467      *
   17468      * @see #setVerticalFadingEdgeEnabled(boolean)
   17469      * @see #setHorizontalFadingEdgeEnabled(boolean)
   17470      *
   17471      * @return The known solid color background for this view, or 0 if the color may vary
   17472      */
   17473     @ViewDebug.ExportedProperty(category = "drawing")
   17474     @ColorInt
   17475     public int getSolidColor() {
   17476         return 0;
   17477     }
   17478 
   17479     /**
   17480      * Build a human readable string representation of the specified view flags.
   17481      *
   17482      * @param flags the view flags to convert to a string
   17483      * @return a String representing the supplied flags
   17484      */
   17485     private static String printFlags(int flags) {
   17486         String output = "";
   17487         int numFlags = 0;
   17488         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
   17489             output += "TAKES_FOCUS";
   17490             numFlags++;
   17491         }
   17492 
   17493         switch (flags & VISIBILITY_MASK) {
   17494         case INVISIBLE:
   17495             if (numFlags > 0) {
   17496                 output += " ";
   17497             }
   17498             output += "INVISIBLE";
   17499             // USELESS HERE numFlags++;
   17500             break;
   17501         case GONE:
   17502             if (numFlags > 0) {
   17503                 output += " ";
   17504             }
   17505             output += "GONE";
   17506             // USELESS HERE numFlags++;
   17507             break;
   17508         default:
   17509             break;
   17510         }
   17511         return output;
   17512     }
   17513 
   17514     /**
   17515      * Build a human readable string representation of the specified private
   17516      * view flags.
   17517      *
   17518      * @param privateFlags the private view flags to convert to a string
   17519      * @return a String representing the supplied flags
   17520      */
   17521     private static String printPrivateFlags(int privateFlags) {
   17522         String output = "";
   17523         int numFlags = 0;
   17524 
   17525         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
   17526             output += "WANTS_FOCUS";
   17527             numFlags++;
   17528         }
   17529 
   17530         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
   17531             if (numFlags > 0) {
   17532                 output += " ";
   17533             }
   17534             output += "FOCUSED";
   17535             numFlags++;
   17536         }
   17537 
   17538         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
   17539             if (numFlags > 0) {
   17540                 output += " ";
   17541             }
   17542             output += "SELECTED";
   17543             numFlags++;
   17544         }
   17545 
   17546         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
   17547             if (numFlags > 0) {
   17548                 output += " ";
   17549             }
   17550             output += "IS_ROOT_NAMESPACE";
   17551             numFlags++;
   17552         }
   17553 
   17554         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
   17555             if (numFlags > 0) {
   17556                 output += " ";
   17557             }
   17558             output += "HAS_BOUNDS";
   17559             numFlags++;
   17560         }
   17561 
   17562         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
   17563             if (numFlags > 0) {
   17564                 output += " ";
   17565             }
   17566             output += "DRAWN";
   17567             // USELESS HERE numFlags++;
   17568         }
   17569         return output;
   17570     }
   17571 
   17572     /**
   17573      * <p>Indicates whether or not this view's layout will be requested during
   17574      * the next hierarchy layout pass.</p>
   17575      *
   17576      * @return true if the layout will be forced during next layout pass
   17577      */
   17578     public boolean isLayoutRequested() {
   17579         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   17580     }
   17581 
   17582     /**
   17583      * Return true if o is a ViewGroup that is laying out using optical bounds.
   17584      * @hide
   17585      */
   17586     public static boolean isLayoutModeOptical(Object o) {
   17587         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
   17588     }
   17589 
   17590     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
   17591         Insets parentInsets = mParent instanceof View ?
   17592                 ((View) mParent).getOpticalInsets() : Insets.NONE;
   17593         Insets childInsets = getOpticalInsets();
   17594         return setFrame(
   17595                 left   + parentInsets.left - childInsets.left,
   17596                 top    + parentInsets.top  - childInsets.top,
   17597                 right  + parentInsets.left + childInsets.right,
   17598                 bottom + parentInsets.top  + childInsets.bottom);
   17599     }
   17600 
   17601     /**
   17602      * Assign a size and position to a view and all of its
   17603      * descendants
   17604      *
   17605      * <p>This is the second phase of the layout mechanism.
   17606      * (The first is measuring). In this phase, each parent calls
   17607      * layout on all of its children to position them.
   17608      * This is typically done using the child measurements
   17609      * that were stored in the measure pass().</p>
   17610      *
   17611      * <p>Derived classes should not override this method.
   17612      * Derived classes with children should override
   17613      * onLayout. In that method, they should
   17614      * call layout on each of their children.</p>
   17615      *
   17616      * @param l Left position, relative to parent
   17617      * @param t Top position, relative to parent
   17618      * @param r Right position, relative to parent
   17619      * @param b Bottom position, relative to parent
   17620      */
   17621     @SuppressWarnings({"unchecked"})
   17622     public void layout(int l, int t, int r, int b) {
   17623         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
   17624             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
   17625             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   17626         }
   17627 
   17628         int oldL = mLeft;
   17629         int oldT = mTop;
   17630         int oldB = mBottom;
   17631         int oldR = mRight;
   17632 
   17633         boolean changed = isLayoutModeOptical(mParent) ?
   17634                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
   17635 
   17636         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
   17637             onLayout(changed, l, t, r, b);
   17638 
   17639             if (shouldDrawRoundScrollbar()) {
   17640                 if(mRoundScrollbarRenderer == null) {
   17641                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
   17642                 }
   17643             } else {
   17644                 mRoundScrollbarRenderer = null;
   17645             }
   17646 
   17647             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
   17648 
   17649             ListenerInfo li = mListenerInfo;
   17650             if (li != null && li.mOnLayoutChangeListeners != null) {
   17651                 ArrayList<OnLayoutChangeListener> listenersCopy =
   17652                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
   17653                 int numListeners = listenersCopy.size();
   17654                 for (int i = 0; i < numListeners; ++i) {
   17655                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
   17656                 }
   17657             }
   17658         }
   17659 
   17660         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
   17661         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
   17662     }
   17663 
   17664     /**
   17665      * Called from layout when this view should
   17666      * assign a size and position to each of its children.
   17667      *
   17668      * Derived classes with children should override
   17669      * this method and call layout on each of
   17670      * their children.
   17671      * @param changed This is a new size or position for this view
   17672      * @param left Left position, relative to parent
   17673      * @param top Top position, relative to parent
   17674      * @param right Right position, relative to parent
   17675      * @param bottom Bottom position, relative to parent
   17676      */
   17677     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   17678     }
   17679 
   17680     /**
   17681      * Assign a size and position to this view.
   17682      *
   17683      * This is called from layout.
   17684      *
   17685      * @param left Left position, relative to parent
   17686      * @param top Top position, relative to parent
   17687      * @param right Right position, relative to parent
   17688      * @param bottom Bottom position, relative to parent
   17689      * @return true if the new size and position are different than the
   17690      *         previous ones
   17691      * {@hide}
   17692      */
   17693     protected boolean setFrame(int left, int top, int right, int bottom) {
   17694         boolean changed = false;
   17695 
   17696         if (DBG) {
   17697             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
   17698                     + right + "," + bottom + ")");
   17699         }
   17700 
   17701         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
   17702             changed = true;
   17703 
   17704             // Remember our drawn bit
   17705             int drawn = mPrivateFlags & PFLAG_DRAWN;
   17706 
   17707             int oldWidth = mRight - mLeft;
   17708             int oldHeight = mBottom - mTop;
   17709             int newWidth = right - left;
   17710             int newHeight = bottom - top;
   17711             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
   17712 
   17713             // Invalidate our old position
   17714             invalidate(sizeChanged);
   17715 
   17716             mLeft = left;
   17717             mTop = top;
   17718             mRight = right;
   17719             mBottom = bottom;
   17720             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
   17721 
   17722             mPrivateFlags |= PFLAG_HAS_BOUNDS;
   17723 
   17724 
   17725             if (sizeChanged) {
   17726                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
   17727             }
   17728 
   17729             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
   17730                 // If we are visible, force the DRAWN bit to on so that
   17731                 // this invalidate will go through (at least to our parent).
   17732                 // This is because someone may have invalidated this view
   17733                 // before this call to setFrame came in, thereby clearing
   17734                 // the DRAWN bit.
   17735                 mPrivateFlags |= PFLAG_DRAWN;
   17736                 invalidate(sizeChanged);
   17737                 // parent display list may need to be recreated based on a change in the bounds
   17738                 // of any child
   17739                 invalidateParentCaches();
   17740             }
   17741 
   17742             // Reset drawn bit to original value (invalidate turns it off)
   17743             mPrivateFlags |= drawn;
   17744 
   17745             mBackgroundSizeChanged = true;
   17746             if (mForegroundInfo != null) {
   17747                 mForegroundInfo.mBoundsChanged = true;
   17748             }
   17749 
   17750             notifySubtreeAccessibilityStateChangedIfNeeded();
   17751         }
   17752         return changed;
   17753     }
   17754 
   17755     /**
   17756      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
   17757      * @hide
   17758      */
   17759     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
   17760         setFrame(left, top, right, bottom);
   17761     }
   17762 
   17763     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
   17764         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
   17765         if (mOverlay != null) {
   17766             mOverlay.getOverlayView().setRight(newWidth);
   17767             mOverlay.getOverlayView().setBottom(newHeight);
   17768         }
   17769         rebuildOutline();
   17770     }
   17771 
   17772     /**
   17773      * Finalize inflating a view from XML.  This is called as the last phase
   17774      * of inflation, after all child views have been added.
   17775      *
   17776      * <p>Even if the subclass overrides onFinishInflate, they should always be
   17777      * sure to call the super method, so that we get called.
   17778      */
   17779     @CallSuper
   17780     protected void onFinishInflate() {
   17781     }
   17782 
   17783     /**
   17784      * Returns the resources associated with this view.
   17785      *
   17786      * @return Resources object.
   17787      */
   17788     public Resources getResources() {
   17789         return mResources;
   17790     }
   17791 
   17792     /**
   17793      * Invalidates the specified Drawable.
   17794      *
   17795      * @param drawable the drawable to invalidate
   17796      */
   17797     @Override
   17798     public void invalidateDrawable(@NonNull Drawable drawable) {
   17799         if (verifyDrawable(drawable)) {
   17800             final Rect dirty = drawable.getDirtyBounds();
   17801             final int scrollX = mScrollX;
   17802             final int scrollY = mScrollY;
   17803 
   17804             invalidate(dirty.left + scrollX, dirty.top + scrollY,
   17805                     dirty.right + scrollX, dirty.bottom + scrollY);
   17806             rebuildOutline();
   17807         }
   17808     }
   17809 
   17810     /**
   17811      * Schedules an action on a drawable to occur at a specified time.
   17812      *
   17813      * @param who the recipient of the action
   17814      * @param what the action to run on the drawable
   17815      * @param when the time at which the action must occur. Uses the
   17816      *        {@link SystemClock#uptimeMillis} timebase.
   17817      */
   17818     @Override
   17819     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
   17820         if (verifyDrawable(who) && what != null) {
   17821             final long delay = when - SystemClock.uptimeMillis();
   17822             if (mAttachInfo != null) {
   17823                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   17824                         Choreographer.CALLBACK_ANIMATION, what, who,
   17825                         Choreographer.subtractFrameDelay(delay));
   17826             } else {
   17827                 // Postpone the runnable until we know
   17828                 // on which thread it needs to run.
   17829                 getRunQueue().postDelayed(what, delay);
   17830             }
   17831         }
   17832     }
   17833 
   17834     /**
   17835      * Cancels a scheduled action on a drawable.
   17836      *
   17837      * @param who the recipient of the action
   17838      * @param what the action to cancel
   17839      */
   17840     @Override
   17841     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
   17842         if (verifyDrawable(who) && what != null) {
   17843             if (mAttachInfo != null) {
   17844                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   17845                         Choreographer.CALLBACK_ANIMATION, what, who);
   17846             }
   17847             getRunQueue().removeCallbacks(what);
   17848         }
   17849     }
   17850 
   17851     /**
   17852      * Unschedule any events associated with the given Drawable.  This can be
   17853      * used when selecting a new Drawable into a view, so that the previous
   17854      * one is completely unscheduled.
   17855      *
   17856      * @param who The Drawable to unschedule.
   17857      *
   17858      * @see #drawableStateChanged
   17859      */
   17860     public void unscheduleDrawable(Drawable who) {
   17861         if (mAttachInfo != null && who != null) {
   17862             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   17863                     Choreographer.CALLBACK_ANIMATION, null, who);
   17864         }
   17865     }
   17866 
   17867     /**
   17868      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
   17869      * that the View directionality can and will be resolved before its Drawables.
   17870      *
   17871      * Will call {@link View#onResolveDrawables} when resolution is done.
   17872      *
   17873      * @hide
   17874      */
   17875     protected void resolveDrawables() {
   17876         // Drawables resolution may need to happen before resolving the layout direction (which is
   17877         // done only during the measure() call).
   17878         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
   17879         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
   17880         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
   17881         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
   17882         // direction to be resolved as its resolved value will be the same as its raw value.
   17883         if (!isLayoutDirectionResolved() &&
   17884                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
   17885             return;
   17886         }
   17887 
   17888         final int layoutDirection = isLayoutDirectionResolved() ?
   17889                 getLayoutDirection() : getRawLayoutDirection();
   17890 
   17891         if (mBackground != null) {
   17892             mBackground.setLayoutDirection(layoutDirection);
   17893         }
   17894         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   17895             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
   17896         }
   17897         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
   17898         onResolveDrawables(layoutDirection);
   17899     }
   17900 
   17901     boolean areDrawablesResolved() {
   17902         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
   17903     }
   17904 
   17905     /**
   17906      * Called when layout direction has been resolved.
   17907      *
   17908      * The default implementation does nothing.
   17909      *
   17910      * @param layoutDirection The resolved layout direction.
   17911      *
   17912      * @see #LAYOUT_DIRECTION_LTR
   17913      * @see #LAYOUT_DIRECTION_RTL
   17914      *
   17915      * @hide
   17916      */
   17917     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
   17918     }
   17919 
   17920     /**
   17921      * @hide
   17922      */
   17923     protected void resetResolvedDrawables() {
   17924         resetResolvedDrawablesInternal();
   17925     }
   17926 
   17927     void resetResolvedDrawablesInternal() {
   17928         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
   17929     }
   17930 
   17931     /**
   17932      * If your view subclass is displaying its own Drawable objects, it should
   17933      * override this function and return true for any Drawable it is
   17934      * displaying.  This allows animations for those drawables to be
   17935      * scheduled.
   17936      *
   17937      * <p>Be sure to call through to the super class when overriding this
   17938      * function.
   17939      *
   17940      * @param who The Drawable to verify.  Return true if it is one you are
   17941      *            displaying, else return the result of calling through to the
   17942      *            super class.
   17943      *
   17944      * @return boolean If true than the Drawable is being displayed in the
   17945      *         view; else false and it is not allowed to animate.
   17946      *
   17947      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
   17948      * @see #drawableStateChanged()
   17949      */
   17950     @CallSuper
   17951     protected boolean verifyDrawable(@NonNull Drawable who) {
   17952         // Avoid verifying the scroll bar drawable so that we don't end up in
   17953         // an invalidation loop. This effectively prevents the scroll bar
   17954         // drawable from triggering invalidations and scheduling runnables.
   17955         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
   17956     }
   17957 
   17958     /**
   17959      * This function is called whenever the state of the view changes in such
   17960      * a way that it impacts the state of drawables being shown.
   17961      * <p>
   17962      * If the View has a StateListAnimator, it will also be called to run necessary state
   17963      * change animations.
   17964      * <p>
   17965      * Be sure to call through to the superclass when overriding this function.
   17966      *
   17967      * @see Drawable#setState(int[])
   17968      */
   17969     @CallSuper
   17970     protected void drawableStateChanged() {
   17971         final int[] state = getDrawableState();
   17972         boolean changed = false;
   17973 
   17974         final Drawable bg = mBackground;
   17975         if (bg != null && bg.isStateful()) {
   17976             changed |= bg.setState(state);
   17977         }
   17978 
   17979         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   17980         if (fg != null && fg.isStateful()) {
   17981             changed |= fg.setState(state);
   17982         }
   17983 
   17984         if (mScrollCache != null) {
   17985             final Drawable scrollBar = mScrollCache.scrollBar;
   17986             if (scrollBar != null && scrollBar.isStateful()) {
   17987                 changed |= scrollBar.setState(state)
   17988                         && mScrollCache.state != ScrollabilityCache.OFF;
   17989             }
   17990         }
   17991 
   17992         if (mStateListAnimator != null) {
   17993             mStateListAnimator.setState(state);
   17994         }
   17995 
   17996         if (changed) {
   17997             invalidate();
   17998         }
   17999     }
   18000 
   18001     /**
   18002      * This function is called whenever the view hotspot changes and needs to
   18003      * be propagated to drawables or child views managed by the view.
   18004      * <p>
   18005      * Dispatching to child views is handled by
   18006      * {@link #dispatchDrawableHotspotChanged(float, float)}.
   18007      * <p>
   18008      * Be sure to call through to the superclass when overriding this function.
   18009      *
   18010      * @param x hotspot x coordinate
   18011      * @param y hotspot y coordinate
   18012      */
   18013     @CallSuper
   18014     public void drawableHotspotChanged(float x, float y) {
   18015         if (mBackground != null) {
   18016             mBackground.setHotspot(x, y);
   18017         }
   18018         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   18019             mForegroundInfo.mDrawable.setHotspot(x, y);
   18020         }
   18021 
   18022         dispatchDrawableHotspotChanged(x, y);
   18023     }
   18024 
   18025     /**
   18026      * Dispatches drawableHotspotChanged to all of this View's children.
   18027      *
   18028      * @param x hotspot x coordinate
   18029      * @param y hotspot y coordinate
   18030      * @see #drawableHotspotChanged(float, float)
   18031      */
   18032     public void dispatchDrawableHotspotChanged(float x, float y) {
   18033     }
   18034 
   18035     /**
   18036      * Call this to force a view to update its drawable state. This will cause
   18037      * drawableStateChanged to be called on this view. Views that are interested
   18038      * in the new state should call getDrawableState.
   18039      *
   18040      * @see #drawableStateChanged
   18041      * @see #getDrawableState
   18042      */
   18043     public void refreshDrawableState() {
   18044         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   18045         drawableStateChanged();
   18046 
   18047         ViewParent parent = mParent;
   18048         if (parent != null) {
   18049             parent.childDrawableStateChanged(this);
   18050         }
   18051     }
   18052 
   18053     /**
   18054      * Return an array of resource IDs of the drawable states representing the
   18055      * current state of the view.
   18056      *
   18057      * @return The current drawable state
   18058      *
   18059      * @see Drawable#setState(int[])
   18060      * @see #drawableStateChanged()
   18061      * @see #onCreateDrawableState(int)
   18062      */
   18063     public final int[] getDrawableState() {
   18064         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
   18065             return mDrawableState;
   18066         } else {
   18067             mDrawableState = onCreateDrawableState(0);
   18068             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
   18069             return mDrawableState;
   18070         }
   18071     }
   18072 
   18073     /**
   18074      * Generate the new {@link android.graphics.drawable.Drawable} state for
   18075      * this view. This is called by the view
   18076      * system when the cached Drawable state is determined to be invalid.  To
   18077      * retrieve the current state, you should use {@link #getDrawableState}.
   18078      *
   18079      * @param extraSpace if non-zero, this is the number of extra entries you
   18080      * would like in the returned array in which you can place your own
   18081      * states.
   18082      *
   18083      * @return Returns an array holding the current {@link Drawable} state of
   18084      * the view.
   18085      *
   18086      * @see #mergeDrawableStates(int[], int[])
   18087      */
   18088     protected int[] onCreateDrawableState(int extraSpace) {
   18089         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
   18090                 mParent instanceof View) {
   18091             return ((View) mParent).onCreateDrawableState(extraSpace);
   18092         }
   18093 
   18094         int[] drawableState;
   18095 
   18096         int privateFlags = mPrivateFlags;
   18097 
   18098         int viewStateIndex = 0;
   18099         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
   18100         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
   18101         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
   18102         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
   18103         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
   18104         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
   18105         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
   18106                 ThreadedRenderer.isAvailable()) {
   18107             // This is set if HW acceleration is requested, even if the current
   18108             // process doesn't allow it.  This is just to allow app preview
   18109             // windows to better match their app.
   18110             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
   18111         }
   18112         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
   18113 
   18114         final int privateFlags2 = mPrivateFlags2;
   18115         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
   18116             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
   18117         }
   18118         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
   18119             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
   18120         }
   18121 
   18122         drawableState = StateSet.get(viewStateIndex);
   18123 
   18124         //noinspection ConstantIfStatement
   18125         if (false) {
   18126             Log.i("View", "drawableStateIndex=" + viewStateIndex);
   18127             Log.i("View", toString()
   18128                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
   18129                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
   18130                     + " fo=" + hasFocus()
   18131                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
   18132                     + " wf=" + hasWindowFocus()
   18133                     + ": " + Arrays.toString(drawableState));
   18134         }
   18135 
   18136         if (extraSpace == 0) {
   18137             return drawableState;
   18138         }
   18139 
   18140         final int[] fullState;
   18141         if (drawableState != null) {
   18142             fullState = new int[drawableState.length + extraSpace];
   18143             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
   18144         } else {
   18145             fullState = new int[extraSpace];
   18146         }
   18147 
   18148         return fullState;
   18149     }
   18150 
   18151     /**
   18152      * Merge your own state values in <var>additionalState</var> into the base
   18153      * state values <var>baseState</var> that were returned by
   18154      * {@link #onCreateDrawableState(int)}.
   18155      *
   18156      * @param baseState The base state values returned by
   18157      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
   18158      * own additional state values.
   18159      *
   18160      * @param additionalState The additional state values you would like
   18161      * added to <var>baseState</var>; this array is not modified.
   18162      *
   18163      * @return As a convenience, the <var>baseState</var> array you originally
   18164      * passed into the function is returned.
   18165      *
   18166      * @see #onCreateDrawableState(int)
   18167      */
   18168     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
   18169         final int N = baseState.length;
   18170         int i = N - 1;
   18171         while (i >= 0 && baseState[i] == 0) {
   18172             i--;
   18173         }
   18174         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
   18175         return baseState;
   18176     }
   18177 
   18178     /**
   18179      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
   18180      * on all Drawable objects associated with this view.
   18181      * <p>
   18182      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
   18183      * attached to this view.
   18184      */
   18185     @CallSuper
   18186     public void jumpDrawablesToCurrentState() {
   18187         if (mBackground != null) {
   18188             mBackground.jumpToCurrentState();
   18189         }
   18190         if (mStateListAnimator != null) {
   18191             mStateListAnimator.jumpToCurrentState();
   18192         }
   18193         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   18194             mForegroundInfo.mDrawable.jumpToCurrentState();
   18195         }
   18196     }
   18197 
   18198     /**
   18199      * Sets the background color for this view.
   18200      * @param color the color of the background
   18201      */
   18202     @RemotableViewMethod
   18203     public void setBackgroundColor(@ColorInt int color) {
   18204         if (mBackground instanceof ColorDrawable) {
   18205             ((ColorDrawable) mBackground.mutate()).setColor(color);
   18206             computeOpaqueFlags();
   18207             mBackgroundResource = 0;
   18208         } else {
   18209             setBackground(new ColorDrawable(color));
   18210         }
   18211     }
   18212 
   18213     /**
   18214      * Set the background to a given resource. The resource should refer to
   18215      * a Drawable object or 0 to remove the background.
   18216      * @param resid The identifier of the resource.
   18217      *
   18218      * @attr ref android.R.styleable#View_background
   18219      */
   18220     @RemotableViewMethod
   18221     public void setBackgroundResource(@DrawableRes int resid) {
   18222         if (resid != 0 && resid == mBackgroundResource) {
   18223             return;
   18224         }
   18225 
   18226         Drawable d = null;
   18227         if (resid != 0) {
   18228             d = mContext.getDrawable(resid);
   18229         }
   18230         setBackground(d);
   18231 
   18232         mBackgroundResource = resid;
   18233     }
   18234 
   18235     /**
   18236      * Set the background to a given Drawable, or remove the background. If the
   18237      * background has padding, this View's padding is set to the background's
   18238      * padding. However, when a background is removed, this View's padding isn't
   18239      * touched. If setting the padding is desired, please use
   18240      * {@link #setPadding(int, int, int, int)}.
   18241      *
   18242      * @param background The Drawable to use as the background, or null to remove the
   18243      *        background
   18244      */
   18245     public void setBackground(Drawable background) {
   18246         //noinspection deprecation
   18247         setBackgroundDrawable(background);
   18248     }
   18249 
   18250     /**
   18251      * @deprecated use {@link #setBackground(Drawable)} instead
   18252      */
   18253     @Deprecated
   18254     public void setBackgroundDrawable(Drawable background) {
   18255         computeOpaqueFlags();
   18256 
   18257         if (background == mBackground) {
   18258             return;
   18259         }
   18260 
   18261         boolean requestLayout = false;
   18262 
   18263         mBackgroundResource = 0;
   18264 
   18265         /*
   18266          * Regardless of whether we're setting a new background or not, we want
   18267          * to clear the previous drawable. setVisible first while we still have the callback set.
   18268          */
   18269         if (mBackground != null) {
   18270             if (isAttachedToWindow()) {
   18271                 mBackground.setVisible(false, false);
   18272             }
   18273             mBackground.setCallback(null);
   18274             unscheduleDrawable(mBackground);
   18275         }
   18276 
   18277         if (background != null) {
   18278             Rect padding = sThreadLocal.get();
   18279             if (padding == null) {
   18280                 padding = new Rect();
   18281                 sThreadLocal.set(padding);
   18282             }
   18283             resetResolvedDrawablesInternal();
   18284             background.setLayoutDirection(getLayoutDirection());
   18285             if (background.getPadding(padding)) {
   18286                 resetResolvedPaddingInternal();
   18287                 switch (background.getLayoutDirection()) {
   18288                     case LAYOUT_DIRECTION_RTL:
   18289                         mUserPaddingLeftInitial = padding.right;
   18290                         mUserPaddingRightInitial = padding.left;
   18291                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
   18292                         break;
   18293                     case LAYOUT_DIRECTION_LTR:
   18294                     default:
   18295                         mUserPaddingLeftInitial = padding.left;
   18296                         mUserPaddingRightInitial = padding.right;
   18297                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
   18298                 }
   18299                 mLeftPaddingDefined = false;
   18300                 mRightPaddingDefined = false;
   18301             }
   18302 
   18303             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
   18304             // if it has a different minimum size, we should layout again
   18305             if (mBackground == null
   18306                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
   18307                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
   18308                 requestLayout = true;
   18309             }
   18310 
   18311             // Set mBackground before we set this as the callback and start making other
   18312             // background drawable state change calls. In particular, the setVisible call below
   18313             // can result in drawables attempting to start animations or otherwise invalidate,
   18314             // which requires the view set as the callback (us) to recognize the drawable as
   18315             // belonging to it as per verifyDrawable.
   18316             mBackground = background;
   18317             if (background.isStateful()) {
   18318                 background.setState(getDrawableState());
   18319             }
   18320             if (isAttachedToWindow()) {
   18321                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   18322             }
   18323 
   18324             applyBackgroundTint();
   18325 
   18326             // Set callback last, since the view may still be initializing.
   18327             background.setCallback(this);
   18328 
   18329             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   18330                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   18331                 requestLayout = true;
   18332             }
   18333         } else {
   18334             /* Remove the background */
   18335             mBackground = null;
   18336             if ((mViewFlags & WILL_NOT_DRAW) != 0
   18337                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
   18338                 mPrivateFlags |= PFLAG_SKIP_DRAW;
   18339             }
   18340 
   18341             /*
   18342              * When the background is set, we try to apply its padding to this
   18343              * View. When the background is removed, we don't touch this View's
   18344              * padding. This is noted in the Javadocs. Hence, we don't need to
   18345              * requestLayout(), the invalidate() below is sufficient.
   18346              */
   18347 
   18348             // The old background's minimum size could have affected this
   18349             // View's layout, so let's requestLayout
   18350             requestLayout = true;
   18351         }
   18352 
   18353         computeOpaqueFlags();
   18354 
   18355         if (requestLayout) {
   18356             requestLayout();
   18357         }
   18358 
   18359         mBackgroundSizeChanged = true;
   18360         invalidate(true);
   18361         invalidateOutline();
   18362     }
   18363 
   18364     /**
   18365      * Gets the background drawable
   18366      *
   18367      * @return The drawable used as the background for this view, if any.
   18368      *
   18369      * @see #setBackground(Drawable)
   18370      *
   18371      * @attr ref android.R.styleable#View_background
   18372      */
   18373     public Drawable getBackground() {
   18374         return mBackground;
   18375     }
   18376 
   18377     /**
   18378      * Applies a tint to the background drawable. Does not modify the current tint
   18379      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   18380      * <p>
   18381      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
   18382      * mutate the drawable and apply the specified tint and tint mode using
   18383      * {@link Drawable#setTintList(ColorStateList)}.
   18384      *
   18385      * @param tint the tint to apply, may be {@code null} to clear tint
   18386      *
   18387      * @attr ref android.R.styleable#View_backgroundTint
   18388      * @see #getBackgroundTintList()
   18389      * @see Drawable#setTintList(ColorStateList)
   18390      */
   18391     public void setBackgroundTintList(@Nullable ColorStateList tint) {
   18392         if (mBackgroundTint == null) {
   18393             mBackgroundTint = new TintInfo();
   18394         }
   18395         mBackgroundTint.mTintList = tint;
   18396         mBackgroundTint.mHasTintList = true;
   18397 
   18398         applyBackgroundTint();
   18399     }
   18400 
   18401     /**
   18402      * Return the tint applied to the background drawable, if specified.
   18403      *
   18404      * @return the tint applied to the background drawable
   18405      * @attr ref android.R.styleable#View_backgroundTint
   18406      * @see #setBackgroundTintList(ColorStateList)
   18407      */
   18408     @Nullable
   18409     public ColorStateList getBackgroundTintList() {
   18410         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
   18411     }
   18412 
   18413     /**
   18414      * Specifies the blending mode used to apply the tint specified by
   18415      * {@link #setBackgroundTintList(ColorStateList)}} to the background
   18416      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   18417      *
   18418      * @param tintMode the blending mode used to apply the tint, may be
   18419      *                 {@code null} to clear tint
   18420      * @attr ref android.R.styleable#View_backgroundTintMode
   18421      * @see #getBackgroundTintMode()
   18422      * @see Drawable#setTintMode(PorterDuff.Mode)
   18423      */
   18424     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   18425         if (mBackgroundTint == null) {
   18426             mBackgroundTint = new TintInfo();
   18427         }
   18428         mBackgroundTint.mTintMode = tintMode;
   18429         mBackgroundTint.mHasTintMode = true;
   18430 
   18431         applyBackgroundTint();
   18432     }
   18433 
   18434     /**
   18435      * Return the blending mode used to apply the tint to the background
   18436      * drawable, if specified.
   18437      *
   18438      * @return the blending mode used to apply the tint to the background
   18439      *         drawable
   18440      * @attr ref android.R.styleable#View_backgroundTintMode
   18441      * @see #setBackgroundTintMode(PorterDuff.Mode)
   18442      */
   18443     @Nullable
   18444     public PorterDuff.Mode getBackgroundTintMode() {
   18445         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
   18446     }
   18447 
   18448     private void applyBackgroundTint() {
   18449         if (mBackground != null && mBackgroundTint != null) {
   18450             final TintInfo tintInfo = mBackgroundTint;
   18451             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   18452                 mBackground = mBackground.mutate();
   18453 
   18454                 if (tintInfo.mHasTintList) {
   18455                     mBackground.setTintList(tintInfo.mTintList);
   18456                 }
   18457 
   18458                 if (tintInfo.mHasTintMode) {
   18459                     mBackground.setTintMode(tintInfo.mTintMode);
   18460                 }
   18461 
   18462                 // The drawable (or one of its children) may not have been
   18463                 // stateful before applying the tint, so let's try again.
   18464                 if (mBackground.isStateful()) {
   18465                     mBackground.setState(getDrawableState());
   18466                 }
   18467             }
   18468         }
   18469     }
   18470 
   18471     /**
   18472      * Returns the drawable used as the foreground of this View. The
   18473      * foreground drawable, if non-null, is always drawn on top of the view's content.
   18474      *
   18475      * @return a Drawable or null if no foreground was set
   18476      *
   18477      * @see #onDrawForeground(Canvas)
   18478      */
   18479     public Drawable getForeground() {
   18480         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   18481     }
   18482 
   18483     /**
   18484      * Supply a Drawable that is to be rendered on top of all of the content in the view.
   18485      *
   18486      * @param foreground the Drawable to be drawn on top of the children
   18487      *
   18488      * @attr ref android.R.styleable#View_foreground
   18489      */
   18490     public void setForeground(Drawable foreground) {
   18491         if (mForegroundInfo == null) {
   18492             if (foreground == null) {
   18493                 // Nothing to do.
   18494                 return;
   18495             }
   18496             mForegroundInfo = new ForegroundInfo();
   18497         }
   18498 
   18499         if (foreground == mForegroundInfo.mDrawable) {
   18500             // Nothing to do
   18501             return;
   18502         }
   18503 
   18504         if (mForegroundInfo.mDrawable != null) {
   18505             if (isAttachedToWindow()) {
   18506                 mForegroundInfo.mDrawable.setVisible(false, false);
   18507             }
   18508             mForegroundInfo.mDrawable.setCallback(null);
   18509             unscheduleDrawable(mForegroundInfo.mDrawable);
   18510         }
   18511 
   18512         mForegroundInfo.mDrawable = foreground;
   18513         mForegroundInfo.mBoundsChanged = true;
   18514         if (foreground != null) {
   18515             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   18516                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   18517             }
   18518             foreground.setLayoutDirection(getLayoutDirection());
   18519             if (foreground.isStateful()) {
   18520                 foreground.setState(getDrawableState());
   18521             }
   18522             applyForegroundTint();
   18523             if (isAttachedToWindow()) {
   18524                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   18525             }
   18526             // Set callback last, since the view may still be initializing.
   18527             foreground.setCallback(this);
   18528         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
   18529             mPrivateFlags |= PFLAG_SKIP_DRAW;
   18530         }
   18531         requestLayout();
   18532         invalidate();
   18533     }
   18534 
   18535     /**
   18536      * Magic bit used to support features of framework-internal window decor implementation details.
   18537      * This used to live exclusively in FrameLayout.
   18538      *
   18539      * @return true if the foreground should draw inside the padding region or false
   18540      *         if it should draw inset by the view's padding
   18541      * @hide internal use only; only used by FrameLayout and internal screen layouts.
   18542      */
   18543     public boolean isForegroundInsidePadding() {
   18544         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
   18545     }
   18546 
   18547     /**
   18548      * Describes how the foreground is positioned.
   18549      *
   18550      * @return foreground gravity.
   18551      *
   18552      * @see #setForegroundGravity(int)
   18553      *
   18554      * @attr ref android.R.styleable#View_foregroundGravity
   18555      */
   18556     public int getForegroundGravity() {
   18557         return mForegroundInfo != null ? mForegroundInfo.mGravity
   18558                 : Gravity.START | Gravity.TOP;
   18559     }
   18560 
   18561     /**
   18562      * Describes how the foreground is positioned. Defaults to START and TOP.
   18563      *
   18564      * @param gravity see {@link android.view.Gravity}
   18565      *
   18566      * @see #getForegroundGravity()
   18567      *
   18568      * @attr ref android.R.styleable#View_foregroundGravity
   18569      */
   18570     public void setForegroundGravity(int gravity) {
   18571         if (mForegroundInfo == null) {
   18572             mForegroundInfo = new ForegroundInfo();
   18573         }
   18574 
   18575         if (mForegroundInfo.mGravity != gravity) {
   18576             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
   18577                 gravity |= Gravity.START;
   18578             }
   18579 
   18580             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
   18581                 gravity |= Gravity.TOP;
   18582             }
   18583 
   18584             mForegroundInfo.mGravity = gravity;
   18585             requestLayout();
   18586         }
   18587     }
   18588 
   18589     /**
   18590      * Applies a tint to the foreground drawable. Does not modify the current tint
   18591      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   18592      * <p>
   18593      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
   18594      * mutate the drawable and apply the specified tint and tint mode using
   18595      * {@link Drawable#setTintList(ColorStateList)}.
   18596      *
   18597      * @param tint the tint to apply, may be {@code null} to clear tint
   18598      *
   18599      * @attr ref android.R.styleable#View_foregroundTint
   18600      * @see #getForegroundTintList()
   18601      * @see Drawable#setTintList(ColorStateList)
   18602      */
   18603     public void setForegroundTintList(@Nullable ColorStateList tint) {
   18604         if (mForegroundInfo == null) {
   18605             mForegroundInfo = new ForegroundInfo();
   18606         }
   18607         if (mForegroundInfo.mTintInfo == null) {
   18608             mForegroundInfo.mTintInfo = new TintInfo();
   18609         }
   18610         mForegroundInfo.mTintInfo.mTintList = tint;
   18611         mForegroundInfo.mTintInfo.mHasTintList = true;
   18612 
   18613         applyForegroundTint();
   18614     }
   18615 
   18616     /**
   18617      * Return the tint applied to the foreground drawable, if specified.
   18618      *
   18619      * @return the tint applied to the foreground drawable
   18620      * @attr ref android.R.styleable#View_foregroundTint
   18621      * @see #setForegroundTintList(ColorStateList)
   18622      */
   18623     @Nullable
   18624     public ColorStateList getForegroundTintList() {
   18625         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   18626                 ? mForegroundInfo.mTintInfo.mTintList : null;
   18627     }
   18628 
   18629     /**
   18630      * Specifies the blending mode used to apply the tint specified by
   18631      * {@link #setForegroundTintList(ColorStateList)}} to the background
   18632      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   18633      *
   18634      * @param tintMode the blending mode used to apply the tint, may be
   18635      *                 {@code null} to clear tint
   18636      * @attr ref android.R.styleable#View_foregroundTintMode
   18637      * @see #getForegroundTintMode()
   18638      * @see Drawable#setTintMode(PorterDuff.Mode)
   18639      */
   18640     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   18641         if (mForegroundInfo == null) {
   18642             mForegroundInfo = new ForegroundInfo();
   18643         }
   18644         if (mForegroundInfo.mTintInfo == null) {
   18645             mForegroundInfo.mTintInfo = new TintInfo();
   18646         }
   18647         mForegroundInfo.mTintInfo.mTintMode = tintMode;
   18648         mForegroundInfo.mTintInfo.mHasTintMode = true;
   18649 
   18650         applyForegroundTint();
   18651     }
   18652 
   18653     /**
   18654      * Return the blending mode used to apply the tint to the foreground
   18655      * drawable, if specified.
   18656      *
   18657      * @return the blending mode used to apply the tint to the foreground
   18658      *         drawable
   18659      * @attr ref android.R.styleable#View_foregroundTintMode
   18660      * @see #setForegroundTintMode(PorterDuff.Mode)
   18661      */
   18662     @Nullable
   18663     public PorterDuff.Mode getForegroundTintMode() {
   18664         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   18665                 ? mForegroundInfo.mTintInfo.mTintMode : null;
   18666     }
   18667 
   18668     private void applyForegroundTint() {
   18669         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   18670                 && mForegroundInfo.mTintInfo != null) {
   18671             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
   18672             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   18673                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
   18674 
   18675                 if (tintInfo.mHasTintList) {
   18676                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
   18677                 }
   18678 
   18679                 if (tintInfo.mHasTintMode) {
   18680                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
   18681                 }
   18682 
   18683                 // The drawable (or one of its children) may not have been
   18684                 // stateful before applying the tint, so let's try again.
   18685                 if (mForegroundInfo.mDrawable.isStateful()) {
   18686                     mForegroundInfo.mDrawable.setState(getDrawableState());
   18687                 }
   18688             }
   18689         }
   18690     }
   18691 
   18692     /**
   18693      * Draw any foreground content for this view.
   18694      *
   18695      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
   18696      * drawable or other view-specific decorations. The foreground is drawn on top of the
   18697      * primary view content.</p>
   18698      *
   18699      * @param canvas canvas to draw into
   18700      */
   18701     public void onDrawForeground(Canvas canvas) {
   18702         onDrawScrollIndicators(canvas);
   18703         onDrawScrollBars(canvas);
   18704 
   18705         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   18706         if (foreground != null) {
   18707             if (mForegroundInfo.mBoundsChanged) {
   18708                 mForegroundInfo.mBoundsChanged = false;
   18709                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
   18710                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
   18711 
   18712                 if (mForegroundInfo.mInsidePadding) {
   18713                     selfBounds.set(0, 0, getWidth(), getHeight());
   18714                 } else {
   18715                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
   18716                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
   18717                 }
   18718 
   18719                 final int ld = getLayoutDirection();
   18720                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
   18721                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
   18722                 foreground.setBounds(overlayBounds);
   18723             }
   18724 
   18725             foreground.draw(canvas);
   18726         }
   18727     }
   18728 
   18729     /**
   18730      * Sets the padding. The view may add on the space required to display
   18731      * the scrollbars, depending on the style and visibility of the scrollbars.
   18732      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
   18733      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
   18734      * from the values set in this call.
   18735      *
   18736      * @attr ref android.R.styleable#View_padding
   18737      * @attr ref android.R.styleable#View_paddingBottom
   18738      * @attr ref android.R.styleable#View_paddingLeft
   18739      * @attr ref android.R.styleable#View_paddingRight
   18740      * @attr ref android.R.styleable#View_paddingTop
   18741      * @param left the left padding in pixels
   18742      * @param top the top padding in pixels
   18743      * @param right the right padding in pixels
   18744      * @param bottom the bottom padding in pixels
   18745      */
   18746     public void setPadding(int left, int top, int right, int bottom) {
   18747         resetResolvedPaddingInternal();
   18748 
   18749         mUserPaddingStart = UNDEFINED_PADDING;
   18750         mUserPaddingEnd = UNDEFINED_PADDING;
   18751 
   18752         mUserPaddingLeftInitial = left;
   18753         mUserPaddingRightInitial = right;
   18754 
   18755         mLeftPaddingDefined = true;
   18756         mRightPaddingDefined = true;
   18757 
   18758         internalSetPadding(left, top, right, bottom);
   18759     }
   18760 
   18761     /**
   18762      * @hide
   18763      */
   18764     protected void internalSetPadding(int left, int top, int right, int bottom) {
   18765         mUserPaddingLeft = left;
   18766         mUserPaddingRight = right;
   18767         mUserPaddingBottom = bottom;
   18768 
   18769         final int viewFlags = mViewFlags;
   18770         boolean changed = false;
   18771 
   18772         // Common case is there are no scroll bars.
   18773         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
   18774             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
   18775                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
   18776                         ? 0 : getVerticalScrollbarWidth();
   18777                 switch (mVerticalScrollbarPosition) {
   18778                     case SCROLLBAR_POSITION_DEFAULT:
   18779                         if (isLayoutRtl()) {
   18780                             left += offset;
   18781                         } else {
   18782                             right += offset;
   18783                         }
   18784                         break;
   18785                     case SCROLLBAR_POSITION_RIGHT:
   18786                         right += offset;
   18787                         break;
   18788                     case SCROLLBAR_POSITION_LEFT:
   18789                         left += offset;
   18790                         break;
   18791                 }
   18792             }
   18793             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
   18794                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
   18795                         ? 0 : getHorizontalScrollbarHeight();
   18796             }
   18797         }
   18798 
   18799         if (mPaddingLeft != left) {
   18800             changed = true;
   18801             mPaddingLeft = left;
   18802         }
   18803         if (mPaddingTop != top) {
   18804             changed = true;
   18805             mPaddingTop = top;
   18806         }
   18807         if (mPaddingRight != right) {
   18808             changed = true;
   18809             mPaddingRight = right;
   18810         }
   18811         if (mPaddingBottom != bottom) {
   18812             changed = true;
   18813             mPaddingBottom = bottom;
   18814         }
   18815 
   18816         if (changed) {
   18817             requestLayout();
   18818             invalidateOutline();
   18819         }
   18820     }
   18821 
   18822     /**
   18823      * Sets the relative padding. The view may add on the space required to display
   18824      * the scrollbars, depending on the style and visibility of the scrollbars.
   18825      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
   18826      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
   18827      * from the values set in this call.
   18828      *
   18829      * @attr ref android.R.styleable#View_padding
   18830      * @attr ref android.R.styleable#View_paddingBottom
   18831      * @attr ref android.R.styleable#View_paddingStart
   18832      * @attr ref android.R.styleable#View_paddingEnd
   18833      * @attr ref android.R.styleable#View_paddingTop
   18834      * @param start the start padding in pixels
   18835      * @param top the top padding in pixels
   18836      * @param end the end padding in pixels
   18837      * @param bottom the bottom padding in pixels
   18838      */
   18839     public void setPaddingRelative(int start, int top, int end, int bottom) {
   18840         resetResolvedPaddingInternal();
   18841 
   18842         mUserPaddingStart = start;
   18843         mUserPaddingEnd = end;
   18844         mLeftPaddingDefined = true;
   18845         mRightPaddingDefined = true;
   18846 
   18847         switch(getLayoutDirection()) {
   18848             case LAYOUT_DIRECTION_RTL:
   18849                 mUserPaddingLeftInitial = end;
   18850                 mUserPaddingRightInitial = start;
   18851                 internalSetPadding(end, top, start, bottom);
   18852                 break;
   18853             case LAYOUT_DIRECTION_LTR:
   18854             default:
   18855                 mUserPaddingLeftInitial = start;
   18856                 mUserPaddingRightInitial = end;
   18857                 internalSetPadding(start, top, end, bottom);
   18858         }
   18859     }
   18860 
   18861     /**
   18862      * Returns the top padding of this view.
   18863      *
   18864      * @return the top padding in pixels
   18865      */
   18866     public int getPaddingTop() {
   18867         return mPaddingTop;
   18868     }
   18869 
   18870     /**
   18871      * Returns the bottom padding of this view. If there are inset and enabled
   18872      * scrollbars, this value may include the space required to display the
   18873      * scrollbars as well.
   18874      *
   18875      * @return the bottom padding in pixels
   18876      */
   18877     public int getPaddingBottom() {
   18878         return mPaddingBottom;
   18879     }
   18880 
   18881     /**
   18882      * Returns the left padding of this view. If there are inset and enabled
   18883      * scrollbars, this value may include the space required to display the
   18884      * scrollbars as well.
   18885      *
   18886      * @return the left padding in pixels
   18887      */
   18888     public int getPaddingLeft() {
   18889         if (!isPaddingResolved()) {
   18890             resolvePadding();
   18891         }
   18892         return mPaddingLeft;
   18893     }
   18894 
   18895     /**
   18896      * Returns the start padding of this view depending on its resolved layout direction.
   18897      * If there are inset and enabled scrollbars, this value may include the space
   18898      * required to display the scrollbars as well.
   18899      *
   18900      * @return the start padding in pixels
   18901      */
   18902     public int getPaddingStart() {
   18903         if (!isPaddingResolved()) {
   18904             resolvePadding();
   18905         }
   18906         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   18907                 mPaddingRight : mPaddingLeft;
   18908     }
   18909 
   18910     /**
   18911      * Returns the right padding of this view. If there are inset and enabled
   18912      * scrollbars, this value may include the space required to display the
   18913      * scrollbars as well.
   18914      *
   18915      * @return the right padding in pixels
   18916      */
   18917     public int getPaddingRight() {
   18918         if (!isPaddingResolved()) {
   18919             resolvePadding();
   18920         }
   18921         return mPaddingRight;
   18922     }
   18923 
   18924     /**
   18925      * Returns the end padding of this view depending on its resolved layout direction.
   18926      * If there are inset and enabled scrollbars, this value may include the space
   18927      * required to display the scrollbars as well.
   18928      *
   18929      * @return the end padding in pixels
   18930      */
   18931     public int getPaddingEnd() {
   18932         if (!isPaddingResolved()) {
   18933             resolvePadding();
   18934         }
   18935         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   18936                 mPaddingLeft : mPaddingRight;
   18937     }
   18938 
   18939     /**
   18940      * Return if the padding has been set through relative values
   18941      * {@link #setPaddingRelative(int, int, int, int)} or through
   18942      * @attr ref android.R.styleable#View_paddingStart or
   18943      * @attr ref android.R.styleable#View_paddingEnd
   18944      *
   18945      * @return true if the padding is relative or false if it is not.
   18946      */
   18947     public boolean isPaddingRelative() {
   18948         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
   18949     }
   18950 
   18951     Insets computeOpticalInsets() {
   18952         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
   18953     }
   18954 
   18955     /**
   18956      * @hide
   18957      */
   18958     public void resetPaddingToInitialValues() {
   18959         if (isRtlCompatibilityMode()) {
   18960             mPaddingLeft = mUserPaddingLeftInitial;
   18961             mPaddingRight = mUserPaddingRightInitial;
   18962             return;
   18963         }
   18964         if (isLayoutRtl()) {
   18965             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
   18966             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
   18967         } else {
   18968             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
   18969             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
   18970         }
   18971     }
   18972 
   18973     /**
   18974      * @hide
   18975      */
   18976     public Insets getOpticalInsets() {
   18977         if (mLayoutInsets == null) {
   18978             mLayoutInsets = computeOpticalInsets();
   18979         }
   18980         return mLayoutInsets;
   18981     }
   18982 
   18983     /**
   18984      * Set this view's optical insets.
   18985      *
   18986      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
   18987      * property. Views that compute their own optical insets should call it as part of measurement.
   18988      * This method does not request layout. If you are setting optical insets outside of
   18989      * measure/layout itself you will want to call requestLayout() yourself.
   18990      * </p>
   18991      * @hide
   18992      */
   18993     public void setOpticalInsets(Insets insets) {
   18994         mLayoutInsets = insets;
   18995     }
   18996 
   18997     /**
   18998      * Changes the selection state of this view. A view can be selected or not.
   18999      * Note that selection is not the same as focus. Views are typically
   19000      * selected in the context of an AdapterView like ListView or GridView;
   19001      * the selected view is the view that is highlighted.
   19002      *
   19003      * @param selected true if the view must be selected, false otherwise
   19004      */
   19005     public void setSelected(boolean selected) {
   19006         //noinspection DoubleNegation
   19007         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
   19008             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
   19009             if (!selected) resetPressedState();
   19010             invalidate(true);
   19011             refreshDrawableState();
   19012             dispatchSetSelected(selected);
   19013             if (selected) {
   19014                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
   19015             } else {
   19016                 notifyViewAccessibilityStateChangedIfNeeded(
   19017                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   19018             }
   19019         }
   19020     }
   19021 
   19022     /**
   19023      * Dispatch setSelected to all of this View's children.
   19024      *
   19025      * @see #setSelected(boolean)
   19026      *
   19027      * @param selected The new selected state
   19028      */
   19029     protected void dispatchSetSelected(boolean selected) {
   19030     }
   19031 
   19032     /**
   19033      * Indicates the selection state of this view.
   19034      *
   19035      * @return true if the view is selected, false otherwise
   19036      */
   19037     @ViewDebug.ExportedProperty
   19038     public boolean isSelected() {
   19039         return (mPrivateFlags & PFLAG_SELECTED) != 0;
   19040     }
   19041 
   19042     /**
   19043      * Changes the activated state of this view. A view can be activated or not.
   19044      * Note that activation is not the same as selection.  Selection is
   19045      * a transient property, representing the view (hierarchy) the user is
   19046      * currently interacting with.  Activation is a longer-term state that the
   19047      * user can move views in and out of.  For example, in a list view with
   19048      * single or multiple selection enabled, the views in the current selection
   19049      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
   19050      * here.)  The activated state is propagated down to children of the view it
   19051      * is set on.
   19052      *
   19053      * @param activated true if the view must be activated, false otherwise
   19054      */
   19055     public void setActivated(boolean activated) {
   19056         //noinspection DoubleNegation
   19057         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
   19058             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
   19059             invalidate(true);
   19060             refreshDrawableState();
   19061             dispatchSetActivated(activated);
   19062         }
   19063     }
   19064 
   19065     /**
   19066      * Dispatch setActivated to all of this View's children.
   19067      *
   19068      * @see #setActivated(boolean)
   19069      *
   19070      * @param activated The new activated state
   19071      */
   19072     protected void dispatchSetActivated(boolean activated) {
   19073     }
   19074 
   19075     /**
   19076      * Indicates the activation state of this view.
   19077      *
   19078      * @return true if the view is activated, false otherwise
   19079      */
   19080     @ViewDebug.ExportedProperty
   19081     public boolean isActivated() {
   19082         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
   19083     }
   19084 
   19085     /**
   19086      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
   19087      * observer can be used to get notifications when global events, like
   19088      * layout, happen.
   19089      *
   19090      * The returned ViewTreeObserver observer is not guaranteed to remain
   19091      * valid for the lifetime of this View. If the caller of this method keeps
   19092      * a long-lived reference to ViewTreeObserver, it should always check for
   19093      * the return value of {@link ViewTreeObserver#isAlive()}.
   19094      *
   19095      * @return The ViewTreeObserver for this view's hierarchy.
   19096      */
   19097     public ViewTreeObserver getViewTreeObserver() {
   19098         if (mAttachInfo != null) {
   19099             return mAttachInfo.mTreeObserver;
   19100         }
   19101         if (mFloatingTreeObserver == null) {
   19102             mFloatingTreeObserver = new ViewTreeObserver();
   19103         }
   19104         return mFloatingTreeObserver;
   19105     }
   19106 
   19107     /**
   19108      * <p>Finds the topmost view in the current view hierarchy.</p>
   19109      *
   19110      * @return the topmost view containing this view
   19111      */
   19112     public View getRootView() {
   19113         if (mAttachInfo != null) {
   19114             final View v = mAttachInfo.mRootView;
   19115             if (v != null) {
   19116                 return v;
   19117             }
   19118         }
   19119 
   19120         View parent = this;
   19121 
   19122         while (parent.mParent != null && parent.mParent instanceof View) {
   19123             parent = (View) parent.mParent;
   19124         }
   19125 
   19126         return parent;
   19127     }
   19128 
   19129     /**
   19130      * Transforms a motion event from view-local coordinates to on-screen
   19131      * coordinates.
   19132      *
   19133      * @param ev the view-local motion event
   19134      * @return false if the transformation could not be applied
   19135      * @hide
   19136      */
   19137     public boolean toGlobalMotionEvent(MotionEvent ev) {
   19138         final AttachInfo info = mAttachInfo;
   19139         if (info == null) {
   19140             return false;
   19141         }
   19142 
   19143         final Matrix m = info.mTmpMatrix;
   19144         m.set(Matrix.IDENTITY_MATRIX);
   19145         transformMatrixToGlobal(m);
   19146         ev.transform(m);
   19147         return true;
   19148     }
   19149 
   19150     /**
   19151      * Transforms a motion event from on-screen coordinates to view-local
   19152      * coordinates.
   19153      *
   19154      * @param ev the on-screen motion event
   19155      * @return false if the transformation could not be applied
   19156      * @hide
   19157      */
   19158     public boolean toLocalMotionEvent(MotionEvent ev) {
   19159         final AttachInfo info = mAttachInfo;
   19160         if (info == null) {
   19161             return false;
   19162         }
   19163 
   19164         final Matrix m = info.mTmpMatrix;
   19165         m.set(Matrix.IDENTITY_MATRIX);
   19166         transformMatrixToLocal(m);
   19167         ev.transform(m);
   19168         return true;
   19169     }
   19170 
   19171     /**
   19172      * Modifies the input matrix such that it maps view-local coordinates to
   19173      * on-screen coordinates.
   19174      *
   19175      * @param m input matrix to modify
   19176      * @hide
   19177      */
   19178     public void transformMatrixToGlobal(Matrix m) {
   19179         final ViewParent parent = mParent;
   19180         if (parent instanceof View) {
   19181             final View vp = (View) parent;
   19182             vp.transformMatrixToGlobal(m);
   19183             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
   19184         } else if (parent instanceof ViewRootImpl) {
   19185             final ViewRootImpl vr = (ViewRootImpl) parent;
   19186             vr.transformMatrixToGlobal(m);
   19187             m.preTranslate(0, -vr.mCurScrollY);
   19188         }
   19189 
   19190         m.preTranslate(mLeft, mTop);
   19191 
   19192         if (!hasIdentityMatrix()) {
   19193             m.preConcat(getMatrix());
   19194         }
   19195     }
   19196 
   19197     /**
   19198      * Modifies the input matrix such that it maps on-screen coordinates to
   19199      * view-local coordinates.
   19200      *
   19201      * @param m input matrix to modify
   19202      * @hide
   19203      */
   19204     public void transformMatrixToLocal(Matrix m) {
   19205         final ViewParent parent = mParent;
   19206         if (parent instanceof View) {
   19207             final View vp = (View) parent;
   19208             vp.transformMatrixToLocal(m);
   19209             m.postTranslate(vp.mScrollX, vp.mScrollY);
   19210         } else if (parent instanceof ViewRootImpl) {
   19211             final ViewRootImpl vr = (ViewRootImpl) parent;
   19212             vr.transformMatrixToLocal(m);
   19213             m.postTranslate(0, vr.mCurScrollY);
   19214         }
   19215 
   19216         m.postTranslate(-mLeft, -mTop);
   19217 
   19218         if (!hasIdentityMatrix()) {
   19219             m.postConcat(getInverseMatrix());
   19220         }
   19221     }
   19222 
   19223     /**
   19224      * @hide
   19225      */
   19226     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
   19227             @ViewDebug.IntToString(from = 0, to = "x"),
   19228             @ViewDebug.IntToString(from = 1, to = "y")
   19229     })
   19230     public int[] getLocationOnScreen() {
   19231         int[] location = new int[2];
   19232         getLocationOnScreen(location);
   19233         return location;
   19234     }
   19235 
   19236     /**
   19237      * <p>Computes the coordinates of this view on the screen. The argument
   19238      * must be an array of two integers. After the method returns, the array
   19239      * contains the x and y location in that order.</p>
   19240      *
   19241      * @param outLocation an array of two integers in which to hold the coordinates
   19242      */
   19243     public void getLocationOnScreen(@Size(2) int[] outLocation) {
   19244         getLocationInWindow(outLocation);
   19245 
   19246         final AttachInfo info = mAttachInfo;
   19247         if (info != null) {
   19248             outLocation[0] += info.mWindowLeft;
   19249             outLocation[1] += info.mWindowTop;
   19250         }
   19251     }
   19252 
   19253     /**
   19254      * <p>Computes the coordinates of this view in its window. The argument
   19255      * must be an array of two integers. After the method returns, the array
   19256      * contains the x and y location in that order.</p>
   19257      *
   19258      * @param outLocation an array of two integers in which to hold the coordinates
   19259      */
   19260     public void getLocationInWindow(@Size(2) int[] outLocation) {
   19261         if (outLocation == null || outLocation.length < 2) {
   19262             throw new IllegalArgumentException("outLocation must be an array of two integers");
   19263         }
   19264 
   19265         outLocation[0] = 0;
   19266         outLocation[1] = 0;
   19267 
   19268         transformFromViewToWindowSpace(outLocation);
   19269     }
   19270 
   19271     /** @hide */
   19272     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
   19273         if (inOutLocation == null || inOutLocation.length < 2) {
   19274             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
   19275         }
   19276 
   19277         if (mAttachInfo == null) {
   19278             // When the view is not attached to a window, this method does not make sense
   19279             inOutLocation[0] = inOutLocation[1] = 0;
   19280             return;
   19281         }
   19282 
   19283         float position[] = mAttachInfo.mTmpTransformLocation;
   19284         position[0] = inOutLocation[0];
   19285         position[1] = inOutLocation[1];
   19286 
   19287         if (!hasIdentityMatrix()) {
   19288             getMatrix().mapPoints(position);
   19289         }
   19290 
   19291         position[0] += mLeft;
   19292         position[1] += mTop;
   19293 
   19294         ViewParent viewParent = mParent;
   19295         while (viewParent instanceof View) {
   19296             final View view = (View) viewParent;
   19297 
   19298             position[0] -= view.mScrollX;
   19299             position[1] -= view.mScrollY;
   19300 
   19301             if (!view.hasIdentityMatrix()) {
   19302                 view.getMatrix().mapPoints(position);
   19303             }
   19304 
   19305             position[0] += view.mLeft;
   19306             position[1] += view.mTop;
   19307 
   19308             viewParent = view.mParent;
   19309          }
   19310 
   19311         if (viewParent instanceof ViewRootImpl) {
   19312             // *cough*
   19313             final ViewRootImpl vr = (ViewRootImpl) viewParent;
   19314             position[1] -= vr.mCurScrollY;
   19315         }
   19316 
   19317         inOutLocation[0] = Math.round(position[0]);
   19318         inOutLocation[1] = Math.round(position[1]);
   19319     }
   19320 
   19321     /**
   19322      * {@hide}
   19323      * @param id the id of the view to be found
   19324      * @return the view of the specified id, null if cannot be found
   19325      */
   19326     protected View findViewTraversal(@IdRes int id) {
   19327         if (id == mID) {
   19328             return this;
   19329         }
   19330         return null;
   19331     }
   19332 
   19333     /**
   19334      * {@hide}
   19335      * @param tag the tag of the view to be found
   19336      * @return the view of specified tag, null if cannot be found
   19337      */
   19338     protected View findViewWithTagTraversal(Object tag) {
   19339         if (tag != null && tag.equals(mTag)) {
   19340             return this;
   19341         }
   19342         return null;
   19343     }
   19344 
   19345     /**
   19346      * {@hide}
   19347      * @param predicate The predicate to evaluate.
   19348      * @param childToSkip If not null, ignores this child during the recursive traversal.
   19349      * @return The first view that matches the predicate or null.
   19350      */
   19351     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
   19352         if (predicate.apply(this)) {
   19353             return this;
   19354         }
   19355         return null;
   19356     }
   19357 
   19358     /**
   19359      * Look for a child view with the given id.  If this view has the given
   19360      * id, return this view.
   19361      *
   19362      * @param id The id to search for.
   19363      * @return The view that has the given id in the hierarchy or null
   19364      */
   19365     @Nullable
   19366     public final View findViewById(@IdRes int id) {
   19367         if (id < 0) {
   19368             return null;
   19369         }
   19370         return findViewTraversal(id);
   19371     }
   19372 
   19373     /**
   19374      * Finds a view by its unuque and stable accessibility id.
   19375      *
   19376      * @param accessibilityId The searched accessibility id.
   19377      * @return The found view.
   19378      */
   19379     final View findViewByAccessibilityId(int accessibilityId) {
   19380         if (accessibilityId < 0) {
   19381             return null;
   19382         }
   19383         View view = findViewByAccessibilityIdTraversal(accessibilityId);
   19384         if (view != null) {
   19385             return view.includeForAccessibility() ? view : null;
   19386         }
   19387         return null;
   19388     }
   19389 
   19390     /**
   19391      * Performs the traversal to find a view by its unuque and stable accessibility id.
   19392      *
   19393      * <strong>Note:</strong>This method does not stop at the root namespace
   19394      * boundary since the user can touch the screen at an arbitrary location
   19395      * potentially crossing the root namespace bounday which will send an
   19396      * accessibility event to accessibility services and they should be able
   19397      * to obtain the event source. Also accessibility ids are guaranteed to be
   19398      * unique in the window.
   19399      *
   19400      * @param accessibilityId The accessibility id.
   19401      * @return The found view.
   19402      *
   19403      * @hide
   19404      */
   19405     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
   19406         if (getAccessibilityViewId() == accessibilityId) {
   19407             return this;
   19408         }
   19409         return null;
   19410     }
   19411 
   19412     /**
   19413      * Look for a child view with the given tag.  If this view has the given
   19414      * tag, return this view.
   19415      *
   19416      * @param tag The tag to search for, using "tag.equals(getTag())".
   19417      * @return The View that has the given tag in the hierarchy or null
   19418      */
   19419     public final View findViewWithTag(Object tag) {
   19420         if (tag == null) {
   19421             return null;
   19422         }
   19423         return findViewWithTagTraversal(tag);
   19424     }
   19425 
   19426     /**
   19427      * {@hide}
   19428      * Look for a child view that matches the specified predicate.
   19429      * If this view matches the predicate, return this view.
   19430      *
   19431      * @param predicate The predicate to evaluate.
   19432      * @return The first view that matches the predicate or null.
   19433      */
   19434     public final View findViewByPredicate(Predicate<View> predicate) {
   19435         return findViewByPredicateTraversal(predicate, null);
   19436     }
   19437 
   19438     /**
   19439      * {@hide}
   19440      * Look for a child view that matches the specified predicate,
   19441      * starting with the specified view and its descendents and then
   19442      * recusively searching the ancestors and siblings of that view
   19443      * until this view is reached.
   19444      *
   19445      * This method is useful in cases where the predicate does not match
   19446      * a single unique view (perhaps multiple views use the same id)
   19447      * and we are trying to find the view that is "closest" in scope to the
   19448      * starting view.
   19449      *
   19450      * @param start The view to start from.
   19451      * @param predicate The predicate to evaluate.
   19452      * @return The first view that matches the predicate or null.
   19453      */
   19454     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
   19455         View childToSkip = null;
   19456         for (;;) {
   19457             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
   19458             if (view != null || start == this) {
   19459                 return view;
   19460             }
   19461 
   19462             ViewParent parent = start.getParent();
   19463             if (parent == null || !(parent instanceof View)) {
   19464                 return null;
   19465             }
   19466 
   19467             childToSkip = start;
   19468             start = (View) parent;
   19469         }
   19470     }
   19471 
   19472     /**
   19473      * Sets the identifier for this view. The identifier does not have to be
   19474      * unique in this view's hierarchy. The identifier should be a positive
   19475      * number.
   19476      *
   19477      * @see #NO_ID
   19478      * @see #getId()
   19479      * @see #findViewById(int)
   19480      *
   19481      * @param id a number used to identify the view
   19482      *
   19483      * @attr ref android.R.styleable#View_id
   19484      */
   19485     public void setId(@IdRes int id) {
   19486         mID = id;
   19487         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
   19488             mID = generateViewId();
   19489         }
   19490     }
   19491 
   19492     /**
   19493      * {@hide}
   19494      *
   19495      * @param isRoot true if the view belongs to the root namespace, false
   19496      *        otherwise
   19497      */
   19498     public void setIsRootNamespace(boolean isRoot) {
   19499         if (isRoot) {
   19500             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
   19501         } else {
   19502             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
   19503         }
   19504     }
   19505 
   19506     /**
   19507      * {@hide}
   19508      *
   19509      * @return true if the view belongs to the root namespace, false otherwise
   19510      */
   19511     public boolean isRootNamespace() {
   19512         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
   19513     }
   19514 
   19515     /**
   19516      * Returns this view's identifier.
   19517      *
   19518      * @return a positive integer used to identify the view or {@link #NO_ID}
   19519      *         if the view has no ID
   19520      *
   19521      * @see #setId(int)
   19522      * @see #findViewById(int)
   19523      * @attr ref android.R.styleable#View_id
   19524      */
   19525     @IdRes
   19526     @ViewDebug.CapturedViewProperty
   19527     public int getId() {
   19528         return mID;
   19529     }
   19530 
   19531     /**
   19532      * Returns this view's tag.
   19533      *
   19534      * @return the Object stored in this view as a tag, or {@code null} if not
   19535      *         set
   19536      *
   19537      * @see #setTag(Object)
   19538      * @see #getTag(int)
   19539      */
   19540     @ViewDebug.ExportedProperty
   19541     public Object getTag() {
   19542         return mTag;
   19543     }
   19544 
   19545     /**
   19546      * Sets the tag associated with this view. A tag can be used to mark
   19547      * a view in its hierarchy and does not have to be unique within the
   19548      * hierarchy. Tags can also be used to store data within a view without
   19549      * resorting to another data structure.
   19550      *
   19551      * @param tag an Object to tag the view with
   19552      *
   19553      * @see #getTag()
   19554      * @see #setTag(int, Object)
   19555      */
   19556     public void setTag(final Object tag) {
   19557         mTag = tag;
   19558     }
   19559 
   19560     /**
   19561      * Returns the tag associated with this view and the specified key.
   19562      *
   19563      * @param key The key identifying the tag
   19564      *
   19565      * @return the Object stored in this view as a tag, or {@code null} if not
   19566      *         set
   19567      *
   19568      * @see #setTag(int, Object)
   19569      * @see #getTag()
   19570      */
   19571     public Object getTag(int key) {
   19572         if (mKeyedTags != null) return mKeyedTags.get(key);
   19573         return null;
   19574     }
   19575 
   19576     /**
   19577      * Sets a tag associated with this view and a key. A tag can be used
   19578      * to mark a view in its hierarchy and does not have to be unique within
   19579      * the hierarchy. Tags can also be used to store data within a view
   19580      * without resorting to another data structure.
   19581      *
   19582      * The specified key should be an id declared in the resources of the
   19583      * application to ensure it is unique (see the <a
   19584      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
   19585      * Keys identified as belonging to
   19586      * the Android framework or not associated with any package will cause
   19587      * an {@link IllegalArgumentException} to be thrown.
   19588      *
   19589      * @param key The key identifying the tag
   19590      * @param tag An Object to tag the view with
   19591      *
   19592      * @throws IllegalArgumentException If they specified key is not valid
   19593      *
   19594      * @see #setTag(Object)
   19595      * @see #getTag(int)
   19596      */
   19597     public void setTag(int key, final Object tag) {
   19598         // If the package id is 0x00 or 0x01, it's either an undefined package
   19599         // or a framework id
   19600         if ((key >>> 24) < 2) {
   19601             throw new IllegalArgumentException("The key must be an application-specific "
   19602                     + "resource id.");
   19603         }
   19604 
   19605         setKeyedTag(key, tag);
   19606     }
   19607 
   19608     /**
   19609      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
   19610      * framework id.
   19611      *
   19612      * @hide
   19613      */
   19614     public void setTagInternal(int key, Object tag) {
   19615         if ((key >>> 24) != 0x1) {
   19616             throw new IllegalArgumentException("The key must be a framework-specific "
   19617                     + "resource id.");
   19618         }
   19619 
   19620         setKeyedTag(key, tag);
   19621     }
   19622 
   19623     private void setKeyedTag(int key, Object tag) {
   19624         if (mKeyedTags == null) {
   19625             mKeyedTags = new SparseArray<Object>(2);
   19626         }
   19627 
   19628         mKeyedTags.put(key, tag);
   19629     }
   19630 
   19631     /**
   19632      * Prints information about this view in the log output, with the tag
   19633      * {@link #VIEW_LOG_TAG}.
   19634      *
   19635      * @hide
   19636      */
   19637     public void debug() {
   19638         debug(0);
   19639     }
   19640 
   19641     /**
   19642      * Prints information about this view in the log output, with the tag
   19643      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
   19644      * indentation defined by the <code>depth</code>.
   19645      *
   19646      * @param depth the indentation level
   19647      *
   19648      * @hide
   19649      */
   19650     protected void debug(int depth) {
   19651         String output = debugIndent(depth - 1);
   19652 
   19653         output += "+ " + this;
   19654         int id = getId();
   19655         if (id != -1) {
   19656             output += " (id=" + id + ")";
   19657         }
   19658         Object tag = getTag();
   19659         if (tag != null) {
   19660             output += " (tag=" + tag + ")";
   19661         }
   19662         Log.d(VIEW_LOG_TAG, output);
   19663 
   19664         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   19665             output = debugIndent(depth) + " FOCUSED";
   19666             Log.d(VIEW_LOG_TAG, output);
   19667         }
   19668 
   19669         output = debugIndent(depth);
   19670         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
   19671                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
   19672                 + "} ";
   19673         Log.d(VIEW_LOG_TAG, output);
   19674 
   19675         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
   19676                 || mPaddingBottom != 0) {
   19677             output = debugIndent(depth);
   19678             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
   19679                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
   19680             Log.d(VIEW_LOG_TAG, output);
   19681         }
   19682 
   19683         output = debugIndent(depth);
   19684         output += "mMeasureWidth=" + mMeasuredWidth +
   19685                 " mMeasureHeight=" + mMeasuredHeight;
   19686         Log.d(VIEW_LOG_TAG, output);
   19687 
   19688         output = debugIndent(depth);
   19689         if (mLayoutParams == null) {
   19690             output += "BAD! no layout params";
   19691         } else {
   19692             output = mLayoutParams.debug(output);
   19693         }
   19694         Log.d(VIEW_LOG_TAG, output);
   19695 
   19696         output = debugIndent(depth);
   19697         output += "flags={";
   19698         output += View.printFlags(mViewFlags);
   19699         output += "}";
   19700         Log.d(VIEW_LOG_TAG, output);
   19701 
   19702         output = debugIndent(depth);
   19703         output += "privateFlags={";
   19704         output += View.printPrivateFlags(mPrivateFlags);
   19705         output += "}";
   19706         Log.d(VIEW_LOG_TAG, output);
   19707     }
   19708 
   19709     /**
   19710      * Creates a string of whitespaces used for indentation.
   19711      *
   19712      * @param depth the indentation level
   19713      * @return a String containing (depth * 2 + 3) * 2 white spaces
   19714      *
   19715      * @hide
   19716      */
   19717     protected static String debugIndent(int depth) {
   19718         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
   19719         for (int i = 0; i < (depth * 2) + 3; i++) {
   19720             spaces.append(' ').append(' ');
   19721         }
   19722         return spaces.toString();
   19723     }
   19724 
   19725     /**
   19726      * <p>Return the offset of the widget's text baseline from the widget's top
   19727      * boundary. If this widget does not support baseline alignment, this
   19728      * method returns -1. </p>
   19729      *
   19730      * @return the offset of the baseline within the widget's bounds or -1
   19731      *         if baseline alignment is not supported
   19732      */
   19733     @ViewDebug.ExportedProperty(category = "layout")
   19734     public int getBaseline() {
   19735         return -1;
   19736     }
   19737 
   19738     /**
   19739      * Returns whether the view hierarchy is currently undergoing a layout pass. This
   19740      * information is useful to avoid situations such as calling {@link #requestLayout()} during
   19741      * a layout pass.
   19742      *
   19743      * @return whether the view hierarchy is currently undergoing a layout pass
   19744      */
   19745     public boolean isInLayout() {
   19746         ViewRootImpl viewRoot = getViewRootImpl();
   19747         return (viewRoot != null && viewRoot.isInLayout());
   19748     }
   19749 
   19750     /**
   19751      * Call this when something has changed which has invalidated the
   19752      * layout of this view. This will schedule a layout pass of the view
   19753      * tree. This should not be called while the view hierarchy is currently in a layout
   19754      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
   19755      * end of the current layout pass (and then layout will run again) or after the current
   19756      * frame is drawn and the next layout occurs.
   19757      *
   19758      * <p>Subclasses which override this method should call the superclass method to
   19759      * handle possible request-during-layout errors correctly.</p>
   19760      */
   19761     @CallSuper
   19762     public void requestLayout() {
   19763         if (mMeasureCache != null) mMeasureCache.clear();
   19764 
   19765         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
   19766             // Only trigger request-during-layout logic if this is the view requesting it,
   19767             // not the views in its parent hierarchy
   19768             ViewRootImpl viewRoot = getViewRootImpl();
   19769             if (viewRoot != null && viewRoot.isInLayout()) {
   19770                 if (!viewRoot.requestLayoutDuringLayout(this)) {
   19771                     return;
   19772                 }
   19773             }
   19774             mAttachInfo.mViewRequestingLayout = this;
   19775         }
   19776 
   19777         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   19778         mPrivateFlags |= PFLAG_INVALIDATED;
   19779 
   19780         if (mParent != null && !mParent.isLayoutRequested()) {
   19781             mParent.requestLayout();
   19782         }
   19783         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
   19784             mAttachInfo.mViewRequestingLayout = null;
   19785         }
   19786     }
   19787 
   19788     /**
   19789      * Forces this view to be laid out during the next layout pass.
   19790      * This method does not call requestLayout() or forceLayout()
   19791      * on the parent.
   19792      */
   19793     public void forceLayout() {
   19794         if (mMeasureCache != null) mMeasureCache.clear();
   19795 
   19796         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   19797         mPrivateFlags |= PFLAG_INVALIDATED;
   19798     }
   19799 
   19800     /**
   19801      * <p>
   19802      * This is called to find out how big a view should be. The parent
   19803      * supplies constraint information in the width and height parameters.
   19804      * </p>
   19805      *
   19806      * <p>
   19807      * The actual measurement work of a view is performed in
   19808      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
   19809      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
   19810      * </p>
   19811      *
   19812      *
   19813      * @param widthMeasureSpec Horizontal space requirements as imposed by the
   19814      *        parent
   19815      * @param heightMeasureSpec Vertical space requirements as imposed by the
   19816      *        parent
   19817      *
   19818      * @see #onMeasure(int, int)
   19819      */
   19820     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
   19821         boolean optical = isLayoutModeOptical(this);
   19822         if (optical != isLayoutModeOptical(mParent)) {
   19823             Insets insets = getOpticalInsets();
   19824             int oWidth  = insets.left + insets.right;
   19825             int oHeight = insets.top  + insets.bottom;
   19826             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
   19827             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
   19828         }
   19829 
   19830         // Suppress sign extension for the low bytes
   19831         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
   19832         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
   19833 
   19834         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   19835 
   19836         // Optimize layout by avoiding an extra EXACTLY pass when the view is
   19837         // already measured as the correct size. In API 23 and below, this
   19838         // extra pass is required to make LinearLayout re-distribute weight.
   19839         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
   19840                 || heightMeasureSpec != mOldHeightMeasureSpec;
   19841         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
   19842                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
   19843         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
   19844                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
   19845         final boolean needsLayout = specChanged
   19846                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
   19847 
   19848         if (forceLayout || needsLayout) {
   19849             // first clears the measured dimension flag
   19850             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
   19851 
   19852             resolveRtlPropertiesIfNeeded();
   19853 
   19854             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
   19855             if (cacheIndex < 0 || sIgnoreMeasureCache) {
   19856                 // measure ourselves, this should set the measured dimension flag back
   19857                 onMeasure(widthMeasureSpec, heightMeasureSpec);
   19858                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   19859             } else {
   19860                 long value = mMeasureCache.valueAt(cacheIndex);
   19861                 // Casting a long to int drops the high 32 bits, no mask needed
   19862                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
   19863                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   19864             }
   19865 
   19866             // flag not set, setMeasuredDimension() was not invoked, we raise
   19867             // an exception to warn the developer
   19868             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
   19869                 throw new IllegalStateException("View with id " + getId() + ": "
   19870                         + getClass().getName() + "#onMeasure() did not set the"
   19871                         + " measured dimension by calling"
   19872                         + " setMeasuredDimension()");
   19873             }
   19874 
   19875             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
   19876         }
   19877 
   19878         mOldWidthMeasureSpec = widthMeasureSpec;
   19879         mOldHeightMeasureSpec = heightMeasureSpec;
   19880 
   19881         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
   19882                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
   19883     }
   19884 
   19885     /**
   19886      * <p>
   19887      * Measure the view and its content to determine the measured width and the
   19888      * measured height. This method is invoked by {@link #measure(int, int)} and
   19889      * should be overridden by subclasses to provide accurate and efficient
   19890      * measurement of their contents.
   19891      * </p>
   19892      *
   19893      * <p>
   19894      * <strong>CONTRACT:</strong> When overriding this method, you
   19895      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
   19896      * measured width and height of this view. Failure to do so will trigger an
   19897      * <code>IllegalStateException</code>, thrown by
   19898      * {@link #measure(int, int)}. Calling the superclass'
   19899      * {@link #onMeasure(int, int)} is a valid use.
   19900      * </p>
   19901      *
   19902      * <p>
   19903      * The base class implementation of measure defaults to the background size,
   19904      * unless a larger size is allowed by the MeasureSpec. Subclasses should
   19905      * override {@link #onMeasure(int, int)} to provide better measurements of
   19906      * their content.
   19907      * </p>
   19908      *
   19909      * <p>
   19910      * If this method is overridden, it is the subclass's responsibility to make
   19911      * sure the measured height and width are at least the view's minimum height
   19912      * and width ({@link #getSuggestedMinimumHeight()} and
   19913      * {@link #getSuggestedMinimumWidth()}).
   19914      * </p>
   19915      *
   19916      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
   19917      *                         The requirements are encoded with
   19918      *                         {@link android.view.View.MeasureSpec}.
   19919      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
   19920      *                         The requirements are encoded with
   19921      *                         {@link android.view.View.MeasureSpec}.
   19922      *
   19923      * @see #getMeasuredWidth()
   19924      * @see #getMeasuredHeight()
   19925      * @see #setMeasuredDimension(int, int)
   19926      * @see #getSuggestedMinimumHeight()
   19927      * @see #getSuggestedMinimumWidth()
   19928      * @see android.view.View.MeasureSpec#getMode(int)
   19929      * @see android.view.View.MeasureSpec#getSize(int)
   19930      */
   19931     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   19932         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
   19933                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
   19934     }
   19935 
   19936     /**
   19937      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
   19938      * measured width and measured height. Failing to do so will trigger an
   19939      * exception at measurement time.</p>
   19940      *
   19941      * @param measuredWidth The measured width of this view.  May be a complex
   19942      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   19943      * {@link #MEASURED_STATE_TOO_SMALL}.
   19944      * @param measuredHeight The measured height of this view.  May be a complex
   19945      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   19946      * {@link #MEASURED_STATE_TOO_SMALL}.
   19947      */
   19948     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
   19949         boolean optical = isLayoutModeOptical(this);
   19950         if (optical != isLayoutModeOptical(mParent)) {
   19951             Insets insets = getOpticalInsets();
   19952             int opticalWidth  = insets.left + insets.right;
   19953             int opticalHeight = insets.top  + insets.bottom;
   19954 
   19955             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
   19956             measuredHeight += optical ? opticalHeight : -opticalHeight;
   19957         }
   19958         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
   19959     }
   19960 
   19961     /**
   19962      * Sets the measured dimension without extra processing for things like optical bounds.
   19963      * Useful for reapplying consistent values that have already been cooked with adjustments
   19964      * for optical bounds, etc. such as those from the measurement cache.
   19965      *
   19966      * @param measuredWidth The measured width of this view.  May be a complex
   19967      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   19968      * {@link #MEASURED_STATE_TOO_SMALL}.
   19969      * @param measuredHeight The measured height of this view.  May be a complex
   19970      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   19971      * {@link #MEASURED_STATE_TOO_SMALL}.
   19972      */
   19973     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
   19974         mMeasuredWidth = measuredWidth;
   19975         mMeasuredHeight = measuredHeight;
   19976 
   19977         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
   19978     }
   19979 
   19980     /**
   19981      * Merge two states as returned by {@link #getMeasuredState()}.
   19982      * @param curState The current state as returned from a view or the result
   19983      * of combining multiple views.
   19984      * @param newState The new view state to combine.
   19985      * @return Returns a new integer reflecting the combination of the two
   19986      * states.
   19987      */
   19988     public static int combineMeasuredStates(int curState, int newState) {
   19989         return curState | newState;
   19990     }
   19991 
   19992     /**
   19993      * Version of {@link #resolveSizeAndState(int, int, int)}
   19994      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
   19995      */
   19996     public static int resolveSize(int size, int measureSpec) {
   19997         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
   19998     }
   19999 
   20000     /**
   20001      * Utility to reconcile a desired size and state, with constraints imposed
   20002      * by a MeasureSpec. Will take the desired size, unless a different size
   20003      * is imposed by the constraints. The returned value is a compound integer,
   20004      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
   20005      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
   20006      * resulting size is smaller than the size the view wants to be.
   20007      *
   20008      * @param size How big the view wants to be.
   20009      * @param measureSpec Constraints imposed by the parent.
   20010      * @param childMeasuredState Size information bit mask for the view's
   20011      *                           children.
   20012      * @return Size information bit mask as defined by
   20013      *         {@link #MEASURED_SIZE_MASK} and
   20014      *         {@link #MEASURED_STATE_TOO_SMALL}.
   20015      */
   20016     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
   20017         final int specMode = MeasureSpec.getMode(measureSpec);
   20018         final int specSize = MeasureSpec.getSize(measureSpec);
   20019         final int result;
   20020         switch (specMode) {
   20021             case MeasureSpec.AT_MOST:
   20022                 if (specSize < size) {
   20023                     result = specSize | MEASURED_STATE_TOO_SMALL;
   20024                 } else {
   20025                     result = size;
   20026                 }
   20027                 break;
   20028             case MeasureSpec.EXACTLY:
   20029                 result = specSize;
   20030                 break;
   20031             case MeasureSpec.UNSPECIFIED:
   20032             default:
   20033                 result = size;
   20034         }
   20035         return result | (childMeasuredState & MEASURED_STATE_MASK);
   20036     }
   20037 
   20038     /**
   20039      * Utility to return a default size. Uses the supplied size if the
   20040      * MeasureSpec imposed no constraints. Will get larger if allowed
   20041      * by the MeasureSpec.
   20042      *
   20043      * @param size Default size for this view
   20044      * @param measureSpec Constraints imposed by the parent
   20045      * @return The size this view should be.
   20046      */
   20047     public static int getDefaultSize(int size, int measureSpec) {
   20048         int result = size;
   20049         int specMode = MeasureSpec.getMode(measureSpec);
   20050         int specSize = MeasureSpec.getSize(measureSpec);
   20051 
   20052         switch (specMode) {
   20053         case MeasureSpec.UNSPECIFIED:
   20054             result = size;
   20055             break;
   20056         case MeasureSpec.AT_MOST:
   20057         case MeasureSpec.EXACTLY:
   20058             result = specSize;
   20059             break;
   20060         }
   20061         return result;
   20062     }
   20063 
   20064     /**
   20065      * Returns the suggested minimum height that the view should use. This
   20066      * returns the maximum of the view's minimum height
   20067      * and the background's minimum height
   20068      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
   20069      * <p>
   20070      * When being used in {@link #onMeasure(int, int)}, the caller should still
   20071      * ensure the returned height is within the requirements of the parent.
   20072      *
   20073      * @return The suggested minimum height of the view.
   20074      */
   20075     protected int getSuggestedMinimumHeight() {
   20076         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
   20077 
   20078     }
   20079 
   20080     /**
   20081      * Returns the suggested minimum width that the view should use. This
   20082      * returns the maximum of the view's minimum width
   20083      * and the background's minimum width
   20084      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
   20085      * <p>
   20086      * When being used in {@link #onMeasure(int, int)}, the caller should still
   20087      * ensure the returned width is within the requirements of the parent.
   20088      *
   20089      * @return The suggested minimum width of the view.
   20090      */
   20091     protected int getSuggestedMinimumWidth() {
   20092         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
   20093     }
   20094 
   20095     /**
   20096      * Returns the minimum height of the view.
   20097      *
   20098      * @return the minimum height the view will try to be.
   20099      *
   20100      * @see #setMinimumHeight(int)
   20101      *
   20102      * @attr ref android.R.styleable#View_minHeight
   20103      */
   20104     public int getMinimumHeight() {
   20105         return mMinHeight;
   20106     }
   20107 
   20108     /**
   20109      * Sets the minimum height of the view. It is not guaranteed the view will
   20110      * be able to achieve this minimum height (for example, if its parent layout
   20111      * constrains it with less available height).
   20112      *
   20113      * @param minHeight The minimum height the view will try to be.
   20114      *
   20115      * @see #getMinimumHeight()
   20116      *
   20117      * @attr ref android.R.styleable#View_minHeight
   20118      */
   20119     @RemotableViewMethod
   20120     public void setMinimumHeight(int minHeight) {
   20121         mMinHeight = minHeight;
   20122         requestLayout();
   20123     }
   20124 
   20125     /**
   20126      * Returns the minimum width of the view.
   20127      *
   20128      * @return the minimum width the view will try to be.
   20129      *
   20130      * @see #setMinimumWidth(int)
   20131      *
   20132      * @attr ref android.R.styleable#View_minWidth
   20133      */
   20134     public int getMinimumWidth() {
   20135         return mMinWidth;
   20136     }
   20137 
   20138     /**
   20139      * Sets the minimum width of the view. It is not guaranteed the view will
   20140      * be able to achieve this minimum width (for example, if its parent layout
   20141      * constrains it with less available width).
   20142      *
   20143      * @param minWidth The minimum width the view will try to be.
   20144      *
   20145      * @see #getMinimumWidth()
   20146      *
   20147      * @attr ref android.R.styleable#View_minWidth
   20148      */
   20149     public void setMinimumWidth(int minWidth) {
   20150         mMinWidth = minWidth;
   20151         requestLayout();
   20152 
   20153     }
   20154 
   20155     /**
   20156      * Get the animation currently associated with this view.
   20157      *
   20158      * @return The animation that is currently playing or
   20159      *         scheduled to play for this view.
   20160      */
   20161     public Animation getAnimation() {
   20162         return mCurrentAnimation;
   20163     }
   20164 
   20165     /**
   20166      * Start the specified animation now.
   20167      *
   20168      * @param animation the animation to start now
   20169      */
   20170     public void startAnimation(Animation animation) {
   20171         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
   20172         setAnimation(animation);
   20173         invalidateParentCaches();
   20174         invalidate(true);
   20175     }
   20176 
   20177     /**
   20178      * Cancels any animations for this view.
   20179      */
   20180     public void clearAnimation() {
   20181         if (mCurrentAnimation != null) {
   20182             mCurrentAnimation.detach();
   20183         }
   20184         mCurrentAnimation = null;
   20185         invalidateParentIfNeeded();
   20186     }
   20187 
   20188     /**
   20189      * Sets the next animation to play for this view.
   20190      * If you want the animation to play immediately, use
   20191      * {@link #startAnimation(android.view.animation.Animation)} instead.
   20192      * This method provides allows fine-grained
   20193      * control over the start time and invalidation, but you
   20194      * must make sure that 1) the animation has a start time set, and
   20195      * 2) the view's parent (which controls animations on its children)
   20196      * will be invalidated when the animation is supposed to
   20197      * start.
   20198      *
   20199      * @param animation The next animation, or null.
   20200      */
   20201     public void setAnimation(Animation animation) {
   20202         mCurrentAnimation = animation;
   20203 
   20204         if (animation != null) {
   20205             // If the screen is off assume the animation start time is now instead of
   20206             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
   20207             // would cause the animation to start when the screen turns back on
   20208             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
   20209                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
   20210                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
   20211             }
   20212             animation.reset();
   20213         }
   20214     }
   20215 
   20216     /**
   20217      * Invoked by a parent ViewGroup to notify the start of the animation
   20218      * currently associated with this view. If you override this method,
   20219      * always call super.onAnimationStart();
   20220      *
   20221      * @see #setAnimation(android.view.animation.Animation)
   20222      * @see #getAnimation()
   20223      */
   20224     @CallSuper
   20225     protected void onAnimationStart() {
   20226         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
   20227     }
   20228 
   20229     /**
   20230      * Invoked by a parent ViewGroup to notify the end of the animation
   20231      * currently associated with this view. If you override this method,
   20232      * always call super.onAnimationEnd();
   20233      *
   20234      * @see #setAnimation(android.view.animation.Animation)
   20235      * @see #getAnimation()
   20236      */
   20237     @CallSuper
   20238     protected void onAnimationEnd() {
   20239         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
   20240     }
   20241 
   20242     /**
   20243      * Invoked if there is a Transform that involves alpha. Subclass that can
   20244      * draw themselves with the specified alpha should return true, and then
   20245      * respect that alpha when their onDraw() is called. If this returns false
   20246      * then the view may be redirected to draw into an offscreen buffer to
   20247      * fulfill the request, which will look fine, but may be slower than if the
   20248      * subclass handles it internally. The default implementation returns false.
   20249      *
   20250      * @param alpha The alpha (0..255) to apply to the view's drawing
   20251      * @return true if the view can draw with the specified alpha.
   20252      */
   20253     protected boolean onSetAlpha(int alpha) {
   20254         return false;
   20255     }
   20256 
   20257     /**
   20258      * This is used by the RootView to perform an optimization when
   20259      * the view hierarchy contains one or several SurfaceView.
   20260      * SurfaceView is always considered transparent, but its children are not,
   20261      * therefore all View objects remove themselves from the global transparent
   20262      * region (passed as a parameter to this function).
   20263      *
   20264      * @param region The transparent region for this ViewAncestor (window).
   20265      *
   20266      * @return Returns true if the effective visibility of the view at this
   20267      * point is opaque, regardless of the transparent region; returns false
   20268      * if it is possible for underlying windows to be seen behind the view.
   20269      *
   20270      * {@hide}
   20271      */
   20272     public boolean gatherTransparentRegion(Region region) {
   20273         final AttachInfo attachInfo = mAttachInfo;
   20274         if (region != null && attachInfo != null) {
   20275             final int pflags = mPrivateFlags;
   20276             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
   20277                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
   20278                 // remove it from the transparent region.
   20279                 final int[] location = attachInfo.mTransparentLocation;
   20280                 getLocationInWindow(location);
   20281                 // When a view has Z value, then it will be better to leave some area below the view
   20282                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
   20283                 // the bottom part needs more offset than the left, top and right parts due to the
   20284                 // spot light effects.
   20285                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
   20286                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
   20287                         location[0] + mRight - mLeft + shadowOffset,
   20288                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
   20289             } else {
   20290                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
   20291                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
   20292                     // the background drawable's non-transparent parts from this transparent region.
   20293                     applyDrawableToTransparentRegion(mBackground, region);
   20294                 }
   20295                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   20296                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
   20297                     // Similarly, we remove the foreground drawable's non-transparent parts.
   20298                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
   20299                 }
   20300             }
   20301         }
   20302         return true;
   20303     }
   20304 
   20305     /**
   20306      * Play a sound effect for this view.
   20307      *
   20308      * <p>The framework will play sound effects for some built in actions, such as
   20309      * clicking, but you may wish to play these effects in your widget,
   20310      * for instance, for internal navigation.
   20311      *
   20312      * <p>The sound effect will only be played if sound effects are enabled by the user, and
   20313      * {@link #isSoundEffectsEnabled()} is true.
   20314      *
   20315      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
   20316      */
   20317     public void playSoundEffect(int soundConstant) {
   20318         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
   20319             return;
   20320         }
   20321         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
   20322     }
   20323 
   20324     /**
   20325      * BZZZTT!!1!
   20326      *
   20327      * <p>Provide haptic feedback to the user for this view.
   20328      *
   20329      * <p>The framework will provide haptic feedback for some built in actions,
   20330      * such as long presses, but you may wish to provide feedback for your
   20331      * own widget.
   20332      *
   20333      * <p>The feedback will only be performed if
   20334      * {@link #isHapticFeedbackEnabled()} is true.
   20335      *
   20336      * @param feedbackConstant One of the constants defined in
   20337      * {@link HapticFeedbackConstants}
   20338      */
   20339     public boolean performHapticFeedback(int feedbackConstant) {
   20340         return performHapticFeedback(feedbackConstant, 0);
   20341     }
   20342 
   20343     /**
   20344      * BZZZTT!!1!
   20345      *
   20346      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
   20347      *
   20348      * @param feedbackConstant One of the constants defined in
   20349      * {@link HapticFeedbackConstants}
   20350      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
   20351      */
   20352     public boolean performHapticFeedback(int feedbackConstant, int flags) {
   20353         if (mAttachInfo == null) {
   20354             return false;
   20355         }
   20356         //noinspection SimplifiableIfStatement
   20357         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
   20358                 && !isHapticFeedbackEnabled()) {
   20359             return false;
   20360         }
   20361         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
   20362                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
   20363     }
   20364 
   20365     /**
   20366      * Request that the visibility of the status bar or other screen/window
   20367      * decorations be changed.
   20368      *
   20369      * <p>This method is used to put the over device UI into temporary modes
   20370      * where the user's attention is focused more on the application content,
   20371      * by dimming or hiding surrounding system affordances.  This is typically
   20372      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   20373      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
   20374      * to be placed behind the action bar (and with these flags other system
   20375      * affordances) so that smooth transitions between hiding and showing them
   20376      * can be done.
   20377      *
   20378      * <p>Two representative examples of the use of system UI visibility is
   20379      * implementing a content browsing application (like a magazine reader)
   20380      * and a video playing application.
   20381      *
   20382      * <p>The first code shows a typical implementation of a View in a content
   20383      * browsing application.  In this implementation, the application goes
   20384      * into a content-oriented mode by hiding the status bar and action bar,
   20385      * and putting the navigation elements into lights out mode.  The user can
   20386      * then interact with content while in this mode.  Such an application should
   20387      * provide an easy way for the user to toggle out of the mode (such as to
   20388      * check information in the status bar or access notifications).  In the
   20389      * implementation here, this is done simply by tapping on the content.
   20390      *
   20391      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
   20392      *      content}
   20393      *
   20394      * <p>This second code sample shows a typical implementation of a View
   20395      * in a video playing application.  In this situation, while the video is
   20396      * playing the application would like to go into a complete full-screen mode,
   20397      * to use as much of the display as possible for the video.  When in this state
   20398      * the user can not interact with the application; the system intercepts
   20399      * touching on the screen to pop the UI out of full screen mode.  See
   20400      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
   20401      *
   20402      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
   20403      *      content}
   20404      *
   20405      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   20406      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   20407      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   20408      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   20409      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   20410      */
   20411     public void setSystemUiVisibility(int visibility) {
   20412         if (visibility != mSystemUiVisibility) {
   20413             mSystemUiVisibility = visibility;
   20414             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   20415                 mParent.recomputeViewAttributes(this);
   20416             }
   20417         }
   20418     }
   20419 
   20420     /**
   20421      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
   20422      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   20423      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   20424      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   20425      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   20426      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   20427      */
   20428     public int getSystemUiVisibility() {
   20429         return mSystemUiVisibility;
   20430     }
   20431 
   20432     /**
   20433      * Returns the current system UI visibility that is currently set for
   20434      * the entire window.  This is the combination of the
   20435      * {@link #setSystemUiVisibility(int)} values supplied by all of the
   20436      * views in the window.
   20437      */
   20438     public int getWindowSystemUiVisibility() {
   20439         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
   20440     }
   20441 
   20442     /**
   20443      * Override to find out when the window's requested system UI visibility
   20444      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
   20445      * This is different from the callbacks received through
   20446      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
   20447      * in that this is only telling you about the local request of the window,
   20448      * not the actual values applied by the system.
   20449      */
   20450     public void onWindowSystemUiVisibilityChanged(int visible) {
   20451     }
   20452 
   20453     /**
   20454      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
   20455      * the view hierarchy.
   20456      */
   20457     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
   20458         onWindowSystemUiVisibilityChanged(visible);
   20459     }
   20460 
   20461     /**
   20462      * Set a listener to receive callbacks when the visibility of the system bar changes.
   20463      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
   20464      */
   20465     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
   20466         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
   20467         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   20468             mParent.recomputeViewAttributes(this);
   20469         }
   20470     }
   20471 
   20472     /**
   20473      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
   20474      * the view hierarchy.
   20475      */
   20476     public void dispatchSystemUiVisibilityChanged(int visibility) {
   20477         ListenerInfo li = mListenerInfo;
   20478         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   20479             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
   20480                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
   20481         }
   20482     }
   20483 
   20484     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
   20485         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
   20486         if (val != mSystemUiVisibility) {
   20487             setSystemUiVisibility(val);
   20488             return true;
   20489         }
   20490         return false;
   20491     }
   20492 
   20493     /** @hide */
   20494     public void setDisabledSystemUiVisibility(int flags) {
   20495         if (mAttachInfo != null) {
   20496             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
   20497                 mAttachInfo.mDisabledSystemUiVisibility = flags;
   20498                 if (mParent != null) {
   20499                     mParent.recomputeViewAttributes(this);
   20500                 }
   20501             }
   20502         }
   20503     }
   20504 
   20505     /**
   20506      * Creates an image that the system displays during the drag and drop
   20507      * operation. This is called a &quot;drag shadow&quot;. The default implementation
   20508      * for a DragShadowBuilder based on a View returns an image that has exactly the same
   20509      * appearance as the given View. The default also positions the center of the drag shadow
   20510      * directly under the touch point. If no View is provided (the constructor with no parameters
   20511      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
   20512      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
   20513      * default is an invisible drag shadow.
   20514      * <p>
   20515      * You are not required to use the View you provide to the constructor as the basis of the
   20516      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
   20517      * anything you want as the drag shadow.
   20518      * </p>
   20519      * <p>
   20520      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
   20521      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
   20522      *  size and position of the drag shadow. It uses this data to construct a
   20523      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
   20524      *  so that your application can draw the shadow image in the Canvas.
   20525      * </p>
   20526      *
   20527      * <div class="special reference">
   20528      * <h3>Developer Guides</h3>
   20529      * <p>For a guide to implementing drag and drop features, read the
   20530      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   20531      * </div>
   20532      */
   20533     public static class DragShadowBuilder {
   20534         private final WeakReference<View> mView;
   20535 
   20536         /**
   20537          * Constructs a shadow image builder based on a View. By default, the resulting drag
   20538          * shadow will have the same appearance and dimensions as the View, with the touch point
   20539          * over the center of the View.
   20540          * @param view A View. Any View in scope can be used.
   20541          */
   20542         public DragShadowBuilder(View view) {
   20543             mView = new WeakReference<View>(view);
   20544         }
   20545 
   20546         /**
   20547          * Construct a shadow builder object with no associated View.  This
   20548          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
   20549          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
   20550          * to supply the drag shadow's dimensions and appearance without
   20551          * reference to any View object. If they are not overridden, then the result is an
   20552          * invisible drag shadow.
   20553          */
   20554         public DragShadowBuilder() {
   20555             mView = new WeakReference<View>(null);
   20556         }
   20557 
   20558         /**
   20559          * Returns the View object that had been passed to the
   20560          * {@link #View.DragShadowBuilder(View)}
   20561          * constructor.  If that View parameter was {@code null} or if the
   20562          * {@link #View.DragShadowBuilder()}
   20563          * constructor was used to instantiate the builder object, this method will return
   20564          * null.
   20565          *
   20566          * @return The View object associate with this builder object.
   20567          */
   20568         @SuppressWarnings({"JavadocReference"})
   20569         final public View getView() {
   20570             return mView.get();
   20571         }
   20572 
   20573         /**
   20574          * Provides the metrics for the shadow image. These include the dimensions of
   20575          * the shadow image, and the point within that shadow that should
   20576          * be centered under the touch location while dragging.
   20577          * <p>
   20578          * The default implementation sets the dimensions of the shadow to be the
   20579          * same as the dimensions of the View itself and centers the shadow under
   20580          * the touch point.
   20581          * </p>
   20582          *
   20583          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
   20584          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
   20585          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
   20586          * image.
   20587          *
   20588          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
   20589          * shadow image that should be underneath the touch point during the drag and drop
   20590          * operation. Your application must set {@link android.graphics.Point#x} to the
   20591          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
   20592          */
   20593         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
   20594             final View view = mView.get();
   20595             if (view != null) {
   20596                 outShadowSize.set(view.getWidth(), view.getHeight());
   20597                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
   20598             } else {
   20599                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
   20600             }
   20601         }
   20602 
   20603         /**
   20604          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
   20605          * based on the dimensions it received from the
   20606          * {@link #onProvideShadowMetrics(Point, Point)} callback.
   20607          *
   20608          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
   20609          */
   20610         public void onDrawShadow(Canvas canvas) {
   20611             final View view = mView.get();
   20612             if (view != null) {
   20613                 view.draw(canvas);
   20614             } else {
   20615                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
   20616             }
   20617         }
   20618     }
   20619 
   20620     /**
   20621      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
   20622      * startDragAndDrop()} for newer platform versions.
   20623      */
   20624     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
   20625                                    Object myLocalState, int flags) {
   20626         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
   20627     }
   20628 
   20629     /**
   20630      * Starts a drag and drop operation. When your application calls this method, it passes a
   20631      * {@link android.view.View.DragShadowBuilder} object to the system. The
   20632      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
   20633      * to get metrics for the drag shadow, and then calls the object's
   20634      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
   20635      * <p>
   20636      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
   20637      *  drag events to all the View objects in your application that are currently visible. It does
   20638      *  this either by calling the View object's drag listener (an implementation of
   20639      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
   20640      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
   20641      *  Both are passed a {@link android.view.DragEvent} object that has a
   20642      *  {@link android.view.DragEvent#getAction()} value of
   20643      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
   20644      * </p>
   20645      * <p>
   20646      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
   20647      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
   20648      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
   20649      * to the View the user selected for dragging.
   20650      * </p>
   20651      * @param data A {@link android.content.ClipData} object pointing to the data to be
   20652      * transferred by the drag and drop operation.
   20653      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   20654      * drag shadow.
   20655      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
   20656      * drop operation. When dispatching drag events to views in the same activity this object
   20657      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
   20658      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
   20659      * will return null).
   20660      * <p>
   20661      * myLocalState is a lightweight mechanism for the sending information from the dragged View
   20662      * to the target Views. For example, it can contain flags that differentiate between a
   20663      * a copy operation and a move operation.
   20664      * </p>
   20665      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
   20666      * flags, or any combination of the following:
   20667      *     <ul>
   20668      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
   20669      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
   20670      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
   20671      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
   20672      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
   20673      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
   20674      *     </ul>
   20675      * @return {@code true} if the method completes successfully, or
   20676      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
   20677      * do a drag, and so no drag operation is in progress.
   20678      */
   20679     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
   20680             Object myLocalState, int flags) {
   20681         if (ViewDebug.DEBUG_DRAG) {
   20682             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
   20683         }
   20684         if (mAttachInfo == null) {
   20685             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
   20686             return false;
   20687         }
   20688         boolean okay = false;
   20689 
   20690         Point shadowSize = new Point();
   20691         Point shadowTouchPoint = new Point();
   20692         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
   20693 
   20694         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
   20695                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
   20696             throw new IllegalStateException("Drag shadow dimensions must not be negative");
   20697         }
   20698 
   20699         if (ViewDebug.DEBUG_DRAG) {
   20700             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
   20701                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
   20702         }
   20703         if (mAttachInfo.mDragSurface != null) {
   20704             mAttachInfo.mDragSurface.release();
   20705         }
   20706         mAttachInfo.mDragSurface = new Surface();
   20707         try {
   20708             mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
   20709                     flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
   20710             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
   20711                     + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
   20712             if (mAttachInfo.mDragToken != null) {
   20713                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
   20714                 try {
   20715                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   20716                     shadowBuilder.onDrawShadow(canvas);
   20717                 } finally {
   20718                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
   20719                 }
   20720 
   20721                 final ViewRootImpl root = getViewRootImpl();
   20722 
   20723                 // Cache the local state object for delivery with DragEvents
   20724                 root.setLocalDragState(myLocalState);
   20725 
   20726                 // repurpose 'shadowSize' for the last touch point
   20727                 root.getLastTouchPoint(shadowSize);
   20728 
   20729                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
   20730                         root.getLastTouchSource(), shadowSize.x, shadowSize.y,
   20731                         shadowTouchPoint.x, shadowTouchPoint.y, data);
   20732                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
   20733             }
   20734         } catch (Exception e) {
   20735             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
   20736             mAttachInfo.mDragSurface.destroy();
   20737             mAttachInfo.mDragSurface = null;
   20738         }
   20739 
   20740         return okay;
   20741     }
   20742 
   20743     /**
   20744      * Cancels an ongoing drag and drop operation.
   20745      * <p>
   20746      * A {@link android.view.DragEvent} object with
   20747      * {@link android.view.DragEvent#getAction()} value of
   20748      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
   20749      * {@link android.view.DragEvent#getResult()} value of {@code false}
   20750      * will be sent to every
   20751      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
   20752      * even if they are not currently visible.
   20753      * </p>
   20754      * <p>
   20755      * This method can be called on any View in the same window as the View on which
   20756      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
   20757      * was called.
   20758      * </p>
   20759      */
   20760     public final void cancelDragAndDrop() {
   20761         if (ViewDebug.DEBUG_DRAG) {
   20762             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
   20763         }
   20764         if (mAttachInfo == null) {
   20765             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
   20766             return;
   20767         }
   20768         if (mAttachInfo.mDragToken != null) {
   20769             try {
   20770                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
   20771             } catch (Exception e) {
   20772                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
   20773             }
   20774             mAttachInfo.mDragToken = null;
   20775         } else {
   20776             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
   20777         }
   20778     }
   20779 
   20780     /**
   20781      * Updates the drag shadow for the ongoing drag and drop operation.
   20782      *
   20783      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   20784      * new drag shadow.
   20785      */
   20786     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
   20787         if (ViewDebug.DEBUG_DRAG) {
   20788             Log.d(VIEW_LOG_TAG, "updateDragShadow");
   20789         }
   20790         if (mAttachInfo == null) {
   20791             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
   20792             return;
   20793         }
   20794         if (mAttachInfo.mDragToken != null) {
   20795             try {
   20796                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
   20797                 try {
   20798                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   20799                     shadowBuilder.onDrawShadow(canvas);
   20800                 } finally {
   20801                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
   20802                 }
   20803             } catch (Exception e) {
   20804                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
   20805             }
   20806         } else {
   20807             Log.e(VIEW_LOG_TAG, "No active drag");
   20808         }
   20809     }
   20810 
   20811     /**
   20812      * Starts a move from {startX, startY}, the amount of the movement will be the offset
   20813      * between {startX, startY} and the new cursor positon.
   20814      * @param startX horizontal coordinate where the move started.
   20815      * @param startY vertical coordinate where the move started.
   20816      * @return whether moving was started successfully.
   20817      * @hide
   20818      */
   20819     public final boolean startMovingTask(float startX, float startY) {
   20820         if (ViewDebug.DEBUG_POSITIONING) {
   20821             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
   20822         }
   20823         try {
   20824             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
   20825         } catch (RemoteException e) {
   20826             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
   20827         }
   20828         return false;
   20829     }
   20830 
   20831     /**
   20832      * Handles drag events sent by the system following a call to
   20833      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
   20834      * startDragAndDrop()}.
   20835      *<p>
   20836      * When the system calls this method, it passes a
   20837      * {@link android.view.DragEvent} object. A call to
   20838      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
   20839      * in DragEvent. The method uses these to determine what is happening in the drag and drop
   20840      * operation.
   20841      * @param event The {@link android.view.DragEvent} sent by the system.
   20842      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
   20843      * in DragEvent, indicating the type of drag event represented by this object.
   20844      * @return {@code true} if the method was successful, otherwise {@code false}.
   20845      * <p>
   20846      *  The method should return {@code true} in response to an action type of
   20847      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
   20848      *  operation.
   20849      * </p>
   20850      * <p>
   20851      *  The method should also return {@code true} in response to an action type of
   20852      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
   20853      *  {@code false} if it didn't.
   20854      * </p>
   20855      */
   20856     public boolean onDragEvent(DragEvent event) {
   20857         return false;
   20858     }
   20859 
   20860     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
   20861     boolean dispatchDragEnterExitInPreN(DragEvent event) {
   20862         return callDragEventHandler(event);
   20863     }
   20864 
   20865     /**
   20866      * Detects if this View is enabled and has a drag event listener.
   20867      * If both are true, then it calls the drag event listener with the
   20868      * {@link android.view.DragEvent} it received. If the drag event listener returns
   20869      * {@code true}, then dispatchDragEvent() returns {@code true}.
   20870      * <p>
   20871      * For all other cases, the method calls the
   20872      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
   20873      * method and returns its result.
   20874      * </p>
   20875      * <p>
   20876      * This ensures that a drag event is always consumed, even if the View does not have a drag
   20877      * event listener. However, if the View has a listener and the listener returns true, then
   20878      * onDragEvent() is not called.
   20879      * </p>
   20880      */
   20881     public boolean dispatchDragEvent(DragEvent event) {
   20882         event.mEventHandlerWasCalled = true;
   20883         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
   20884             event.mAction == DragEvent.ACTION_DROP) {
   20885             // About to deliver an event with coordinates to this view. Notify that now this view
   20886             // has drag focus. This will send exit/enter events as needed.
   20887             getViewRootImpl().setDragFocus(this, event);
   20888         }
   20889         return callDragEventHandler(event);
   20890     }
   20891 
   20892     final boolean callDragEventHandler(DragEvent event) {
   20893         final boolean result;
   20894 
   20895         ListenerInfo li = mListenerInfo;
   20896         //noinspection SimplifiableIfStatement
   20897         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   20898                 && li.mOnDragListener.onDrag(this, event)) {
   20899             result = true;
   20900         } else {
   20901             result = onDragEvent(event);
   20902         }
   20903 
   20904         switch (event.mAction) {
   20905             case DragEvent.ACTION_DRAG_ENTERED: {
   20906                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
   20907                 refreshDrawableState();
   20908             } break;
   20909             case DragEvent.ACTION_DRAG_EXITED: {
   20910                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
   20911                 refreshDrawableState();
   20912             } break;
   20913             case DragEvent.ACTION_DRAG_ENDED: {
   20914                 mPrivateFlags2 &= ~View.DRAG_MASK;
   20915                 refreshDrawableState();
   20916             } break;
   20917         }
   20918 
   20919         return result;
   20920     }
   20921 
   20922     boolean canAcceptDrag() {
   20923         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
   20924     }
   20925 
   20926     /**
   20927      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
   20928      * it is ever exposed at all.
   20929      * @hide
   20930      */
   20931     public void onCloseSystemDialogs(String reason) {
   20932     }
   20933 
   20934     /**
   20935      * Given a Drawable whose bounds have been set to draw into this view,
   20936      * update a Region being computed for
   20937      * {@link #gatherTransparentRegion(android.graphics.Region)} so
   20938      * that any non-transparent parts of the Drawable are removed from the
   20939      * given transparent region.
   20940      *
   20941      * @param dr The Drawable whose transparency is to be applied to the region.
   20942      * @param region A Region holding the current transparency information,
   20943      * where any parts of the region that are set are considered to be
   20944      * transparent.  On return, this region will be modified to have the
   20945      * transparency information reduced by the corresponding parts of the
   20946      * Drawable that are not transparent.
   20947      * {@hide}
   20948      */
   20949     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
   20950         if (DBG) {
   20951             Log.i("View", "Getting transparent region for: " + this);
   20952         }
   20953         final Region r = dr.getTransparentRegion();
   20954         final Rect db = dr.getBounds();
   20955         final AttachInfo attachInfo = mAttachInfo;
   20956         if (r != null && attachInfo != null) {
   20957             final int w = getRight()-getLeft();
   20958             final int h = getBottom()-getTop();
   20959             if (db.left > 0) {
   20960                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
   20961                 r.op(0, 0, db.left, h, Region.Op.UNION);
   20962             }
   20963             if (db.right < w) {
   20964                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
   20965                 r.op(db.right, 0, w, h, Region.Op.UNION);
   20966             }
   20967             if (db.top > 0) {
   20968                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
   20969                 r.op(0, 0, w, db.top, Region.Op.UNION);
   20970             }
   20971             if (db.bottom < h) {
   20972                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
   20973                 r.op(0, db.bottom, w, h, Region.Op.UNION);
   20974             }
   20975             final int[] location = attachInfo.mTransparentLocation;
   20976             getLocationInWindow(location);
   20977             r.translate(location[0], location[1]);
   20978             region.op(r, Region.Op.INTERSECT);
   20979         } else {
   20980             region.op(db, Region.Op.DIFFERENCE);
   20981         }
   20982     }
   20983 
   20984     private void checkForLongClick(int delayOffset, float x, float y) {
   20985         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
   20986             mHasPerformedLongPress = false;
   20987 
   20988             if (mPendingCheckForLongPress == null) {
   20989                 mPendingCheckForLongPress = new CheckForLongPress();
   20990             }
   20991             mPendingCheckForLongPress.setAnchor(x, y);
   20992             mPendingCheckForLongPress.rememberWindowAttachCount();
   20993             postDelayed(mPendingCheckForLongPress,
   20994                     ViewConfiguration.getLongPressTimeout() - delayOffset);
   20995         }
   20996     }
   20997 
   20998     /**
   20999      * Inflate a view from an XML resource.  This convenience method wraps the {@link
   21000      * LayoutInflater} class, which provides a full range of options for view inflation.
   21001      *
   21002      * @param context The Context object for your activity or application.
   21003      * @param resource The resource ID to inflate
   21004      * @param root A view group that will be the parent.  Used to properly inflate the
   21005      * layout_* parameters.
   21006      * @see LayoutInflater
   21007      */
   21008     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
   21009         LayoutInflater factory = LayoutInflater.from(context);
   21010         return factory.inflate(resource, root);
   21011     }
   21012 
   21013     /**
   21014      * Scroll the view with standard behavior for scrolling beyond the normal
   21015      * content boundaries. Views that call this method should override
   21016      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
   21017      * results of an over-scroll operation.
   21018      *
   21019      * Views can use this method to handle any touch or fling-based scrolling.
   21020      *
   21021      * @param deltaX Change in X in pixels
   21022      * @param deltaY Change in Y in pixels
   21023      * @param scrollX Current X scroll value in pixels before applying deltaX
   21024      * @param scrollY Current Y scroll value in pixels before applying deltaY
   21025      * @param scrollRangeX Maximum content scroll range along the X axis
   21026      * @param scrollRangeY Maximum content scroll range along the Y axis
   21027      * @param maxOverScrollX Number of pixels to overscroll by in either direction
   21028      *          along the X axis.
   21029      * @param maxOverScrollY Number of pixels to overscroll by in either direction
   21030      *          along the Y axis.
   21031      * @param isTouchEvent true if this scroll operation is the result of a touch event.
   21032      * @return true if scrolling was clamped to an over-scroll boundary along either
   21033      *          axis, false otherwise.
   21034      */
   21035     @SuppressWarnings({"UnusedParameters"})
   21036     protected boolean overScrollBy(int deltaX, int deltaY,
   21037             int scrollX, int scrollY,
   21038             int scrollRangeX, int scrollRangeY,
   21039             int maxOverScrollX, int maxOverScrollY,
   21040             boolean isTouchEvent) {
   21041         final int overScrollMode = mOverScrollMode;
   21042         final boolean canScrollHorizontal =
   21043                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
   21044         final boolean canScrollVertical =
   21045                 computeVerticalScrollRange() > computeVerticalScrollExtent();
   21046         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
   21047                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
   21048         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
   21049                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
   21050 
   21051         int newScrollX = scrollX + deltaX;
   21052         if (!overScrollHorizontal) {
   21053             maxOverScrollX = 0;
   21054         }
   21055 
   21056         int newScrollY = scrollY + deltaY;
   21057         if (!overScrollVertical) {
   21058             maxOverScrollY = 0;
   21059         }
   21060 
   21061         // Clamp values if at the limits and record
   21062         final int left = -maxOverScrollX;
   21063         final int right = maxOverScrollX + scrollRangeX;
   21064         final int top = -maxOverScrollY;
   21065         final int bottom = maxOverScrollY + scrollRangeY;
   21066 
   21067         boolean clampedX = false;
   21068         if (newScrollX > right) {
   21069             newScrollX = right;
   21070             clampedX = true;
   21071         } else if (newScrollX < left) {
   21072             newScrollX = left;
   21073             clampedX = true;
   21074         }
   21075 
   21076         boolean clampedY = false;
   21077         if (newScrollY > bottom) {
   21078             newScrollY = bottom;
   21079             clampedY = true;
   21080         } else if (newScrollY < top) {
   21081             newScrollY = top;
   21082             clampedY = true;
   21083         }
   21084 
   21085         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
   21086 
   21087         return clampedX || clampedY;
   21088     }
   21089 
   21090     /**
   21091      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
   21092      * respond to the results of an over-scroll operation.
   21093      *
   21094      * @param scrollX New X scroll value in pixels
   21095      * @param scrollY New Y scroll value in pixels
   21096      * @param clampedX True if scrollX was clamped to an over-scroll boundary
   21097      * @param clampedY True if scrollY was clamped to an over-scroll boundary
   21098      */
   21099     protected void onOverScrolled(int scrollX, int scrollY,
   21100             boolean clampedX, boolean clampedY) {
   21101         // Intentionally empty.
   21102     }
   21103 
   21104     /**
   21105      * Returns the over-scroll mode for this view. The result will be
   21106      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   21107      * (allow over-scrolling only if the view content is larger than the container),
   21108      * or {@link #OVER_SCROLL_NEVER}.
   21109      *
   21110      * @return This view's over-scroll mode.
   21111      */
   21112     public int getOverScrollMode() {
   21113         return mOverScrollMode;
   21114     }
   21115 
   21116     /**
   21117      * Set the over-scroll mode for this view. Valid over-scroll modes are
   21118      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   21119      * (allow over-scrolling only if the view content is larger than the container),
   21120      * or {@link #OVER_SCROLL_NEVER}.
   21121      *
   21122      * Setting the over-scroll mode of a view will have an effect only if the
   21123      * view is capable of scrolling.
   21124      *
   21125      * @param overScrollMode The new over-scroll mode for this view.
   21126      */
   21127     public void setOverScrollMode(int overScrollMode) {
   21128         if (overScrollMode != OVER_SCROLL_ALWAYS &&
   21129                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
   21130                 overScrollMode != OVER_SCROLL_NEVER) {
   21131             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
   21132         }
   21133         mOverScrollMode = overScrollMode;
   21134     }
   21135 
   21136     /**
   21137      * Enable or disable nested scrolling for this view.
   21138      *
   21139      * <p>If this property is set to true the view will be permitted to initiate nested
   21140      * scrolling operations with a compatible parent view in the current hierarchy. If this
   21141      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
   21142      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
   21143      * the nested scroll.</p>
   21144      *
   21145      * @param enabled true to enable nested scrolling, false to disable
   21146      *
   21147      * @see #isNestedScrollingEnabled()
   21148      */
   21149     public void setNestedScrollingEnabled(boolean enabled) {
   21150         if (enabled) {
   21151             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
   21152         } else {
   21153             stopNestedScroll();
   21154             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
   21155         }
   21156     }
   21157 
   21158     /**
   21159      * Returns true if nested scrolling is enabled for this view.
   21160      *
   21161      * <p>If nested scrolling is enabled and this View class implementation supports it,
   21162      * this view will act as a nested scrolling child view when applicable, forwarding data
   21163      * about the scroll operation in progress to a compatible and cooperating nested scrolling
   21164      * parent.</p>
   21165      *
   21166      * @return true if nested scrolling is enabled
   21167      *
   21168      * @see #setNestedScrollingEnabled(boolean)
   21169      */
   21170     public boolean isNestedScrollingEnabled() {
   21171         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
   21172                 PFLAG3_NESTED_SCROLLING_ENABLED;
   21173     }
   21174 
   21175     /**
   21176      * Begin a nestable scroll operation along the given axes.
   21177      *
   21178      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
   21179      *
   21180      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
   21181      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
   21182      * In the case of touch scrolling the nested scroll will be terminated automatically in
   21183      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
   21184      * In the event of programmatic scrolling the caller must explicitly call
   21185      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
   21186      *
   21187      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
   21188      * If it returns false the caller may ignore the rest of this contract until the next scroll.
   21189      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
   21190      *
   21191      * <p>At each incremental step of the scroll the caller should invoke
   21192      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
   21193      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
   21194      * parent at least partially consumed the scroll and the caller should adjust the amount it
   21195      * scrolls by.</p>
   21196      *
   21197      * <p>After applying the remainder of the scroll delta the caller should invoke
   21198      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
   21199      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
   21200      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
   21201      * </p>
   21202      *
   21203      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
   21204      *             {@link #SCROLL_AXIS_VERTICAL}.
   21205      * @return true if a cooperative parent was found and nested scrolling has been enabled for
   21206      *         the current gesture.
   21207      *
   21208      * @see #stopNestedScroll()
   21209      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   21210      * @see #dispatchNestedScroll(int, int, int, int, int[])
   21211      */
   21212     public boolean startNestedScroll(int axes) {
   21213         if (hasNestedScrollingParent()) {
   21214             // Already in progress
   21215             return true;
   21216         }
   21217         if (isNestedScrollingEnabled()) {
   21218             ViewParent p = getParent();
   21219             View child = this;
   21220             while (p != null) {
   21221                 try {
   21222                     if (p.onStartNestedScroll(child, this, axes)) {
   21223                         mNestedScrollingParent = p;
   21224                         p.onNestedScrollAccepted(child, this, axes);
   21225                         return true;
   21226                     }
   21227                 } catch (AbstractMethodError e) {
   21228                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
   21229                             "method onStartNestedScroll", e);
   21230                     // Allow the search upward to continue
   21231                 }
   21232                 if (p instanceof View) {
   21233                     child = (View) p;
   21234                 }
   21235                 p = p.getParent();
   21236             }
   21237         }
   21238         return false;
   21239     }
   21240 
   21241     /**
   21242      * Stop a nested scroll in progress.
   21243      *
   21244      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
   21245      *
   21246      * @see #startNestedScroll(int)
   21247      */
   21248     public void stopNestedScroll() {
   21249         if (mNestedScrollingParent != null) {
   21250             mNestedScrollingParent.onStopNestedScroll(this);
   21251             mNestedScrollingParent = null;
   21252         }
   21253     }
   21254 
   21255     /**
   21256      * Returns true if this view has a nested scrolling parent.
   21257      *
   21258      * <p>The presence of a nested scrolling parent indicates that this view has initiated
   21259      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
   21260      *
   21261      * @return whether this view has a nested scrolling parent
   21262      */
   21263     public boolean hasNestedScrollingParent() {
   21264         return mNestedScrollingParent != null;
   21265     }
   21266 
   21267     /**
   21268      * Dispatch one step of a nested scroll in progress.
   21269      *
   21270      * <p>Implementations of views that support nested scrolling should call this to report
   21271      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
   21272      * is not currently in progress or nested scrolling is not
   21273      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
   21274      *
   21275      * <p>Compatible View implementations should also call
   21276      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
   21277      * consuming a component of the scroll event themselves.</p>
   21278      *
   21279      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
   21280      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
   21281      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
   21282      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
   21283      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   21284      *                       in local view coordinates of this view from before this operation
   21285      *                       to after it completes. View implementations may use this to adjust
   21286      *                       expected input coordinate tracking.
   21287      * @return true if the event was dispatched, false if it could not be dispatched.
   21288      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   21289      */
   21290     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
   21291             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
   21292         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   21293             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
   21294                 int startX = 0;
   21295                 int startY = 0;
   21296                 if (offsetInWindow != null) {
   21297                     getLocationInWindow(offsetInWindow);
   21298                     startX = offsetInWindow[0];
   21299                     startY = offsetInWindow[1];
   21300                 }
   21301 
   21302                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
   21303                         dxUnconsumed, dyUnconsumed);
   21304 
   21305                 if (offsetInWindow != null) {
   21306                     getLocationInWindow(offsetInWindow);
   21307                     offsetInWindow[0] -= startX;
   21308                     offsetInWindow[1] -= startY;
   21309                 }
   21310                 return true;
   21311             } else if (offsetInWindow != null) {
   21312                 // No motion, no dispatch. Keep offsetInWindow up to date.
   21313                 offsetInWindow[0] = 0;
   21314                 offsetInWindow[1] = 0;
   21315             }
   21316         }
   21317         return false;
   21318     }
   21319 
   21320     /**
   21321      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
   21322      *
   21323      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
   21324      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
   21325      * scrolling operation to consume some or all of the scroll operation before the child view
   21326      * consumes it.</p>
   21327      *
   21328      * @param dx Horizontal scroll distance in pixels
   21329      * @param dy Vertical scroll distance in pixels
   21330      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
   21331      *                 and consumed[1] the consumed dy.
   21332      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   21333      *                       in local view coordinates of this view from before this operation
   21334      *                       to after it completes. View implementations may use this to adjust
   21335      *                       expected input coordinate tracking.
   21336      * @return true if the parent consumed some or all of the scroll delta
   21337      * @see #dispatchNestedScroll(int, int, int, int, int[])
   21338      */
   21339     public boolean dispatchNestedPreScroll(int dx, int dy,
   21340             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
   21341         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   21342             if (dx != 0 || dy != 0) {
   21343                 int startX = 0;
   21344                 int startY = 0;
   21345                 if (offsetInWindow != null) {
   21346                     getLocationInWindow(offsetInWindow);
   21347                     startX = offsetInWindow[0];
   21348                     startY = offsetInWindow[1];
   21349                 }
   21350 
   21351                 if (consumed == null) {
   21352                     if (mTempNestedScrollConsumed == null) {
   21353                         mTempNestedScrollConsumed = new int[2];
   21354                     }
   21355                     consumed = mTempNestedScrollConsumed;
   21356                 }
   21357                 consumed[0] = 0;
   21358                 consumed[1] = 0;
   21359                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
   21360 
   21361                 if (offsetInWindow != null) {
   21362                     getLocationInWindow(offsetInWindow);
   21363                     offsetInWindow[0] -= startX;
   21364                     offsetInWindow[1] -= startY;
   21365                 }
   21366                 return consumed[0] != 0 || consumed[1] != 0;
   21367             } else if (offsetInWindow != null) {
   21368                 offsetInWindow[0] = 0;
   21369                 offsetInWindow[1] = 0;
   21370             }
   21371         }
   21372         return false;
   21373     }
   21374 
   21375     /**
   21376      * Dispatch a fling to a nested scrolling parent.
   21377      *
   21378      * <p>This method should be used to indicate that a nested scrolling child has detected
   21379      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
   21380      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
   21381      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
   21382      * along a scrollable axis.</p>
   21383      *
   21384      * <p>If a nested scrolling child view would normally fling but it is at the edge of
   21385      * its own content, it can use this method to delegate the fling to its nested scrolling
   21386      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
   21387      *
   21388      * @param velocityX Horizontal fling velocity in pixels per second
   21389      * @param velocityY Vertical fling velocity in pixels per second
   21390      * @param consumed true if the child consumed the fling, false otherwise
   21391      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
   21392      */
   21393     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
   21394         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   21395             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
   21396         }
   21397         return false;
   21398     }
   21399 
   21400     /**
   21401      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
   21402      *
   21403      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
   21404      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
   21405      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
   21406      * before the child view consumes it. If this method returns <code>true</code>, a nested
   21407      * parent view consumed the fling and this view should not scroll as a result.</p>
   21408      *
   21409      * <p>For a better user experience, only one view in a nested scrolling chain should consume
   21410      * the fling at a time. If a parent view consumed the fling this method will return false.
   21411      * Custom view implementations should account for this in two ways:</p>
   21412      *
   21413      * <ul>
   21414      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
   21415      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
   21416      *     position regardless.</li>
   21417      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
   21418      *     even to settle back to a valid idle position.</li>
   21419      * </ul>
   21420      *
   21421      * <p>Views should also not offer fling velocities to nested parent views along an axis
   21422      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
   21423      * should not offer a horizontal fling velocity to its parents since scrolling along that
   21424      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
   21425      *
   21426      * @param velocityX Horizontal fling velocity in pixels per second
   21427      * @param velocityY Vertical fling velocity in pixels per second
   21428      * @return true if a nested scrolling parent consumed the fling
   21429      */
   21430     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
   21431         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   21432             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
   21433         }
   21434         return false;
   21435     }
   21436 
   21437     /**
   21438      * Gets a scale factor that determines the distance the view should scroll
   21439      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
   21440      * @return The vertical scroll scale factor.
   21441      * @hide
   21442      */
   21443     protected float getVerticalScrollFactor() {
   21444         if (mVerticalScrollFactor == 0) {
   21445             TypedValue outValue = new TypedValue();
   21446             if (!mContext.getTheme().resolveAttribute(
   21447                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
   21448                 throw new IllegalStateException(
   21449                         "Expected theme to define listPreferredItemHeight.");
   21450             }
   21451             mVerticalScrollFactor = outValue.getDimension(
   21452                     mContext.getResources().getDisplayMetrics());
   21453         }
   21454         return mVerticalScrollFactor;
   21455     }
   21456 
   21457     /**
   21458      * Gets a scale factor that determines the distance the view should scroll
   21459      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
   21460      * @return The horizontal scroll scale factor.
   21461      * @hide
   21462      */
   21463     protected float getHorizontalScrollFactor() {
   21464         // TODO: Should use something else.
   21465         return getVerticalScrollFactor();
   21466     }
   21467 
   21468     /**
   21469      * Return the value specifying the text direction or policy that was set with
   21470      * {@link #setTextDirection(int)}.
   21471      *
   21472      * @return the defined text direction. It can be one of:
   21473      *
   21474      * {@link #TEXT_DIRECTION_INHERIT},
   21475      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   21476      * {@link #TEXT_DIRECTION_ANY_RTL},
   21477      * {@link #TEXT_DIRECTION_LTR},
   21478      * {@link #TEXT_DIRECTION_RTL},
   21479      * {@link #TEXT_DIRECTION_LOCALE},
   21480      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   21481      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   21482      *
   21483      * @attr ref android.R.styleable#View_textDirection
   21484      *
   21485      * @hide
   21486      */
   21487     @ViewDebug.ExportedProperty(category = "text", mapping = {
   21488             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   21489             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   21490             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   21491             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   21492             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   21493             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   21494             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   21495             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   21496     })
   21497     public int getRawTextDirection() {
   21498         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   21499     }
   21500 
   21501     /**
   21502      * Set the text direction.
   21503      *
   21504      * @param textDirection the direction to set. Should be one of:
   21505      *
   21506      * {@link #TEXT_DIRECTION_INHERIT},
   21507      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   21508      * {@link #TEXT_DIRECTION_ANY_RTL},
   21509      * {@link #TEXT_DIRECTION_LTR},
   21510      * {@link #TEXT_DIRECTION_RTL},
   21511      * {@link #TEXT_DIRECTION_LOCALE}
   21512      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   21513      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
   21514      *
   21515      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
   21516      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
   21517      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
   21518      *
   21519      * @attr ref android.R.styleable#View_textDirection
   21520      */
   21521     public void setTextDirection(int textDirection) {
   21522         if (getRawTextDirection() != textDirection) {
   21523             // Reset the current text direction and the resolved one
   21524             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   21525             resetResolvedTextDirection();
   21526             // Set the new text direction
   21527             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
   21528             // Do resolution
   21529             resolveTextDirection();
   21530             // Notify change
   21531             onRtlPropertiesChanged(getLayoutDirection());
   21532             // Refresh
   21533             requestLayout();
   21534             invalidate(true);
   21535         }
   21536     }
   21537 
   21538     /**
   21539      * Return the resolved text direction.
   21540      *
   21541      * @return the resolved text direction. Returns one of:
   21542      *
   21543      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   21544      * {@link #TEXT_DIRECTION_ANY_RTL},
   21545      * {@link #TEXT_DIRECTION_LTR},
   21546      * {@link #TEXT_DIRECTION_RTL},
   21547      * {@link #TEXT_DIRECTION_LOCALE},
   21548      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   21549      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   21550      *
   21551      * @attr ref android.R.styleable#View_textDirection
   21552      */
   21553     @ViewDebug.ExportedProperty(category = "text", mapping = {
   21554             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   21555             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   21556             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   21557             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   21558             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   21559             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   21560             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   21561             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   21562     })
   21563     public int getTextDirection() {
   21564         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   21565     }
   21566 
   21567     /**
   21568      * Resolve the text direction.
   21569      *
   21570      * @return true if resolution has been done, false otherwise.
   21571      *
   21572      * @hide
   21573      */
   21574     public boolean resolveTextDirection() {
   21575         // Reset any previous text direction resolution
   21576         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   21577 
   21578         if (hasRtlSupport()) {
   21579             // Set resolved text direction flag depending on text direction flag
   21580             final int textDirection = getRawTextDirection();
   21581             switch(textDirection) {
   21582                 case TEXT_DIRECTION_INHERIT:
   21583                     if (!canResolveTextDirection()) {
   21584                         // We cannot do the resolution if there is no parent, so use the default one
   21585                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21586                         // Resolution will need to happen again later
   21587                         return false;
   21588                     }
   21589 
   21590                     // Parent has not yet resolved, so we still return the default
   21591                     try {
   21592                         if (!mParent.isTextDirectionResolved()) {
   21593                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21594                             // Resolution will need to happen again later
   21595                             return false;
   21596                         }
   21597                     } catch (AbstractMethodError e) {
   21598                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21599                                 " does not fully implement ViewParent", e);
   21600                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
   21601                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21602                         return true;
   21603                     }
   21604 
   21605                     // Set current resolved direction to the same value as the parent's one
   21606                     int parentResolvedDirection;
   21607                     try {
   21608                         parentResolvedDirection = mParent.getTextDirection();
   21609                     } catch (AbstractMethodError e) {
   21610                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21611                                 " does not fully implement ViewParent", e);
   21612                         parentResolvedDirection = TEXT_DIRECTION_LTR;
   21613                     }
   21614                     switch (parentResolvedDirection) {
   21615                         case TEXT_DIRECTION_FIRST_STRONG:
   21616                         case TEXT_DIRECTION_ANY_RTL:
   21617                         case TEXT_DIRECTION_LTR:
   21618                         case TEXT_DIRECTION_RTL:
   21619                         case TEXT_DIRECTION_LOCALE:
   21620                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
   21621                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
   21622                             mPrivateFlags2 |=
   21623                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   21624                             break;
   21625                         default:
   21626                             // Default resolved direction is "first strong" heuristic
   21627                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21628                     }
   21629                     break;
   21630                 case TEXT_DIRECTION_FIRST_STRONG:
   21631                 case TEXT_DIRECTION_ANY_RTL:
   21632                 case TEXT_DIRECTION_LTR:
   21633                 case TEXT_DIRECTION_RTL:
   21634                 case TEXT_DIRECTION_LOCALE:
   21635                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
   21636                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
   21637                     // Resolved direction is the same as text direction
   21638                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   21639                     break;
   21640                 default:
   21641                     // Default resolved direction is "first strong" heuristic
   21642                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21643             }
   21644         } else {
   21645             // Default resolved direction is "first strong" heuristic
   21646             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21647         }
   21648 
   21649         // Set to resolved
   21650         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
   21651         return true;
   21652     }
   21653 
   21654     /**
   21655      * Check if text direction resolution can be done.
   21656      *
   21657      * @return true if text direction resolution can be done otherwise return false.
   21658      */
   21659     public boolean canResolveTextDirection() {
   21660         switch (getRawTextDirection()) {
   21661             case TEXT_DIRECTION_INHERIT:
   21662                 if (mParent != null) {
   21663                     try {
   21664                         return mParent.canResolveTextDirection();
   21665                     } catch (AbstractMethodError e) {
   21666                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21667                                 " does not fully implement ViewParent", e);
   21668                     }
   21669                 }
   21670                 return false;
   21671 
   21672             default:
   21673                 return true;
   21674         }
   21675     }
   21676 
   21677     /**
   21678      * Reset resolved text direction. Text direction will be resolved during a call to
   21679      * {@link #onMeasure(int, int)}.
   21680      *
   21681      * @hide
   21682      */
   21683     public void resetResolvedTextDirection() {
   21684         // Reset any previous text direction resolution
   21685         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   21686         // Set to default value
   21687         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   21688     }
   21689 
   21690     /**
   21691      * @return true if text direction is inherited.
   21692      *
   21693      * @hide
   21694      */
   21695     public boolean isTextDirectionInherited() {
   21696         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
   21697     }
   21698 
   21699     /**
   21700      * @return true if text direction is resolved.
   21701      */
   21702     public boolean isTextDirectionResolved() {
   21703         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
   21704     }
   21705 
   21706     /**
   21707      * Return the value specifying the text alignment or policy that was set with
   21708      * {@link #setTextAlignment(int)}.
   21709      *
   21710      * @return the defined text alignment. It can be one of:
   21711      *
   21712      * {@link #TEXT_ALIGNMENT_INHERIT},
   21713      * {@link #TEXT_ALIGNMENT_GRAVITY},
   21714      * {@link #TEXT_ALIGNMENT_CENTER},
   21715      * {@link #TEXT_ALIGNMENT_TEXT_START},
   21716      * {@link #TEXT_ALIGNMENT_TEXT_END},
   21717      * {@link #TEXT_ALIGNMENT_VIEW_START},
   21718      * {@link #TEXT_ALIGNMENT_VIEW_END}
   21719      *
   21720      * @attr ref android.R.styleable#View_textAlignment
   21721      *
   21722      * @hide
   21723      */
   21724     @ViewDebug.ExportedProperty(category = "text", mapping = {
   21725             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   21726             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   21727             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   21728             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   21729             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   21730             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   21731             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   21732     })
   21733     @TextAlignment
   21734     public int getRawTextAlignment() {
   21735         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   21736     }
   21737 
   21738     /**
   21739      * Set the text alignment.
   21740      *
   21741      * @param textAlignment The text alignment to set. Should be one of
   21742      *
   21743      * {@link #TEXT_ALIGNMENT_INHERIT},
   21744      * {@link #TEXT_ALIGNMENT_GRAVITY},
   21745      * {@link #TEXT_ALIGNMENT_CENTER},
   21746      * {@link #TEXT_ALIGNMENT_TEXT_START},
   21747      * {@link #TEXT_ALIGNMENT_TEXT_END},
   21748      * {@link #TEXT_ALIGNMENT_VIEW_START},
   21749      * {@link #TEXT_ALIGNMENT_VIEW_END}
   21750      *
   21751      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
   21752      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   21753      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
   21754      *
   21755      * @attr ref android.R.styleable#View_textAlignment
   21756      */
   21757     public void setTextAlignment(@TextAlignment int textAlignment) {
   21758         if (textAlignment != getRawTextAlignment()) {
   21759             // Reset the current and resolved text alignment
   21760             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   21761             resetResolvedTextAlignment();
   21762             // Set the new text alignment
   21763             mPrivateFlags2 |=
   21764                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
   21765             // Do resolution
   21766             resolveTextAlignment();
   21767             // Notify change
   21768             onRtlPropertiesChanged(getLayoutDirection());
   21769             // Refresh
   21770             requestLayout();
   21771             invalidate(true);
   21772         }
   21773     }
   21774 
   21775     /**
   21776      * Return the resolved text alignment.
   21777      *
   21778      * @return the resolved text alignment. Returns one of:
   21779      *
   21780      * {@link #TEXT_ALIGNMENT_GRAVITY},
   21781      * {@link #TEXT_ALIGNMENT_CENTER},
   21782      * {@link #TEXT_ALIGNMENT_TEXT_START},
   21783      * {@link #TEXT_ALIGNMENT_TEXT_END},
   21784      * {@link #TEXT_ALIGNMENT_VIEW_START},
   21785      * {@link #TEXT_ALIGNMENT_VIEW_END}
   21786      *
   21787      * @attr ref android.R.styleable#View_textAlignment
   21788      */
   21789     @ViewDebug.ExportedProperty(category = "text", mapping = {
   21790             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   21791             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   21792             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   21793             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   21794             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   21795             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   21796             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   21797     })
   21798     @TextAlignment
   21799     public int getTextAlignment() {
   21800         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
   21801                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   21802     }
   21803 
   21804     /**
   21805      * Resolve the text alignment.
   21806      *
   21807      * @return true if resolution has been done, false otherwise.
   21808      *
   21809      * @hide
   21810      */
   21811     public boolean resolveTextAlignment() {
   21812         // Reset any previous text alignment resolution
   21813         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   21814 
   21815         if (hasRtlSupport()) {
   21816             // Set resolved text alignment flag depending on text alignment flag
   21817             final int textAlignment = getRawTextAlignment();
   21818             switch (textAlignment) {
   21819                 case TEXT_ALIGNMENT_INHERIT:
   21820                     // Check if we can resolve the text alignment
   21821                     if (!canResolveTextAlignment()) {
   21822                         // We cannot do the resolution if there is no parent so use the default
   21823                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21824                         // Resolution will need to happen again later
   21825                         return false;
   21826                     }
   21827 
   21828                     // Parent has not yet resolved, so we still return the default
   21829                     try {
   21830                         if (!mParent.isTextAlignmentResolved()) {
   21831                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21832                             // Resolution will need to happen again later
   21833                             return false;
   21834                         }
   21835                     } catch (AbstractMethodError e) {
   21836                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21837                                 " does not fully implement ViewParent", e);
   21838                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   21839                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21840                         return true;
   21841                     }
   21842 
   21843                     int parentResolvedTextAlignment;
   21844                     try {
   21845                         parentResolvedTextAlignment = mParent.getTextAlignment();
   21846                     } catch (AbstractMethodError e) {
   21847                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21848                                 " does not fully implement ViewParent", e);
   21849                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
   21850                     }
   21851                     switch (parentResolvedTextAlignment) {
   21852                         case TEXT_ALIGNMENT_GRAVITY:
   21853                         case TEXT_ALIGNMENT_TEXT_START:
   21854                         case TEXT_ALIGNMENT_TEXT_END:
   21855                         case TEXT_ALIGNMENT_CENTER:
   21856                         case TEXT_ALIGNMENT_VIEW_START:
   21857                         case TEXT_ALIGNMENT_VIEW_END:
   21858                             // Resolved text alignment is the same as the parent resolved
   21859                             // text alignment
   21860                             mPrivateFlags2 |=
   21861                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   21862                             break;
   21863                         default:
   21864                             // Use default resolved text alignment
   21865                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21866                     }
   21867                     break;
   21868                 case TEXT_ALIGNMENT_GRAVITY:
   21869                 case TEXT_ALIGNMENT_TEXT_START:
   21870                 case TEXT_ALIGNMENT_TEXT_END:
   21871                 case TEXT_ALIGNMENT_CENTER:
   21872                 case TEXT_ALIGNMENT_VIEW_START:
   21873                 case TEXT_ALIGNMENT_VIEW_END:
   21874                     // Resolved text alignment is the same as text alignment
   21875                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   21876                     break;
   21877                 default:
   21878                     // Use default resolved text alignment
   21879                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21880             }
   21881         } else {
   21882             // Use default resolved text alignment
   21883             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21884         }
   21885 
   21886         // Set the resolved
   21887         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   21888         return true;
   21889     }
   21890 
   21891     /**
   21892      * Check if text alignment resolution can be done.
   21893      *
   21894      * @return true if text alignment resolution can be done otherwise return false.
   21895      */
   21896     public boolean canResolveTextAlignment() {
   21897         switch (getRawTextAlignment()) {
   21898             case TEXT_DIRECTION_INHERIT:
   21899                 if (mParent != null) {
   21900                     try {
   21901                         return mParent.canResolveTextAlignment();
   21902                     } catch (AbstractMethodError e) {
   21903                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   21904                                 " does not fully implement ViewParent", e);
   21905                     }
   21906                 }
   21907                 return false;
   21908 
   21909             default:
   21910                 return true;
   21911         }
   21912     }
   21913 
   21914     /**
   21915      * Reset resolved text alignment. Text alignment will be resolved during a call to
   21916      * {@link #onMeasure(int, int)}.
   21917      *
   21918      * @hide
   21919      */
   21920     public void resetResolvedTextAlignment() {
   21921         // Reset any previous text alignment resolution
   21922         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   21923         // Set to default
   21924         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   21925     }
   21926 
   21927     /**
   21928      * @return true if text alignment is inherited.
   21929      *
   21930      * @hide
   21931      */
   21932     public boolean isTextAlignmentInherited() {
   21933         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
   21934     }
   21935 
   21936     /**
   21937      * @return true if text alignment is resolved.
   21938      */
   21939     public boolean isTextAlignmentResolved() {
   21940         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   21941     }
   21942 
   21943     /**
   21944      * Generate a value suitable for use in {@link #setId(int)}.
   21945      * This value will not collide with ID values generated at build time by aapt for R.id.
   21946      *
   21947      * @return a generated ID value
   21948      */
   21949     public static int generateViewId() {
   21950         for (;;) {
   21951             final int result = sNextGeneratedId.get();
   21952             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
   21953             int newValue = result + 1;
   21954             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
   21955             if (sNextGeneratedId.compareAndSet(result, newValue)) {
   21956                 return result;
   21957             }
   21958         }
   21959     }
   21960 
   21961     /**
   21962      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
   21963      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
   21964      *                           a normal View or a ViewGroup with
   21965      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
   21966      * @hide
   21967      */
   21968     public void captureTransitioningViews(List<View> transitioningViews) {
   21969         if (getVisibility() == View.VISIBLE) {
   21970             transitioningViews.add(this);
   21971         }
   21972     }
   21973 
   21974     /**
   21975      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
   21976      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
   21977      * @hide
   21978      */
   21979     public void findNamedViews(Map<String, View> namedElements) {
   21980         if (getVisibility() == VISIBLE || mGhostView != null) {
   21981             String transitionName = getTransitionName();
   21982             if (transitionName != null) {
   21983                 namedElements.put(transitionName, this);
   21984             }
   21985         }
   21986     }
   21987 
   21988     /**
   21989      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
   21990      * The default implementation does not care the location or event types, but some subclasses
   21991      * may use it (such as WebViews).
   21992      * @param event The MotionEvent from a mouse
   21993      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
   21994      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
   21995      * @see PointerIcon
   21996      */
   21997     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
   21998         final float x = event.getX(pointerIndex);
   21999         final float y = event.getY(pointerIndex);
   22000         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
   22001             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
   22002         }
   22003         return mPointerIcon;
   22004     }
   22005 
   22006     /**
   22007      * Set the pointer icon for the current view.
   22008      * Passing {@code null} will restore the pointer icon to its default value.
   22009      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
   22010      */
   22011     public void setPointerIcon(PointerIcon pointerIcon) {
   22012         mPointerIcon = pointerIcon;
   22013         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
   22014             return;
   22015         }
   22016         try {
   22017             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
   22018         } catch (RemoteException e) {
   22019         }
   22020     }
   22021 
   22022     /**
   22023      * Gets the pointer icon for the current view.
   22024      */
   22025     public PointerIcon getPointerIcon() {
   22026         return mPointerIcon;
   22027     }
   22028 
   22029     //
   22030     // Properties
   22031     //
   22032     /**
   22033      * A Property wrapper around the <code>alpha</code> functionality handled by the
   22034      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
   22035      */
   22036     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
   22037         @Override
   22038         public void setValue(View object, float value) {
   22039             object.setAlpha(value);
   22040         }
   22041 
   22042         @Override
   22043         public Float get(View object) {
   22044             return object.getAlpha();
   22045         }
   22046     };
   22047 
   22048     /**
   22049      * A Property wrapper around the <code>translationX</code> functionality handled by the
   22050      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
   22051      */
   22052     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
   22053         @Override
   22054         public void setValue(View object, float value) {
   22055             object.setTranslationX(value);
   22056         }
   22057 
   22058                 @Override
   22059         public Float get(View object) {
   22060             return object.getTranslationX();
   22061         }
   22062     };
   22063 
   22064     /**
   22065      * A Property wrapper around the <code>translationY</code> functionality handled by the
   22066      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
   22067      */
   22068     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
   22069         @Override
   22070         public void setValue(View object, float value) {
   22071             object.setTranslationY(value);
   22072         }
   22073 
   22074         @Override
   22075         public Float get(View object) {
   22076             return object.getTranslationY();
   22077         }
   22078     };
   22079 
   22080     /**
   22081      * A Property wrapper around the <code>translationZ</code> functionality handled by the
   22082      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
   22083      */
   22084     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
   22085         @Override
   22086         public void setValue(View object, float value) {
   22087             object.setTranslationZ(value);
   22088         }
   22089 
   22090         @Override
   22091         public Float get(View object) {
   22092             return object.getTranslationZ();
   22093         }
   22094     };
   22095 
   22096     /**
   22097      * A Property wrapper around the <code>x</code> functionality handled by the
   22098      * {@link View#setX(float)} and {@link View#getX()} methods.
   22099      */
   22100     public static final Property<View, Float> X = new FloatProperty<View>("x") {
   22101         @Override
   22102         public void setValue(View object, float value) {
   22103             object.setX(value);
   22104         }
   22105 
   22106         @Override
   22107         public Float get(View object) {
   22108             return object.getX();
   22109         }
   22110     };
   22111 
   22112     /**
   22113      * A Property wrapper around the <code>y</code> functionality handled by the
   22114      * {@link View#setY(float)} and {@link View#getY()} methods.
   22115      */
   22116     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
   22117         @Override
   22118         public void setValue(View object, float value) {
   22119             object.setY(value);
   22120         }
   22121 
   22122         @Override
   22123         public Float get(View object) {
   22124             return object.getY();
   22125         }
   22126     };
   22127 
   22128     /**
   22129      * A Property wrapper around the <code>z</code> functionality handled by the
   22130      * {@link View#setZ(float)} and {@link View#getZ()} methods.
   22131      */
   22132     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
   22133         @Override
   22134         public void setValue(View object, float value) {
   22135             object.setZ(value);
   22136         }
   22137 
   22138         @Override
   22139         public Float get(View object) {
   22140             return object.getZ();
   22141         }
   22142     };
   22143 
   22144     /**
   22145      * A Property wrapper around the <code>rotation</code> functionality handled by the
   22146      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
   22147      */
   22148     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
   22149         @Override
   22150         public void setValue(View object, float value) {
   22151             object.setRotation(value);
   22152         }
   22153 
   22154         @Override
   22155         public Float get(View object) {
   22156             return object.getRotation();
   22157         }
   22158     };
   22159 
   22160     /**
   22161      * A Property wrapper around the <code>rotationX</code> functionality handled by the
   22162      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
   22163      */
   22164     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
   22165         @Override
   22166         public void setValue(View object, float value) {
   22167             object.setRotationX(value);
   22168         }
   22169 
   22170         @Override
   22171         public Float get(View object) {
   22172             return object.getRotationX();
   22173         }
   22174     };
   22175 
   22176     /**
   22177      * A Property wrapper around the <code>rotationY</code> functionality handled by the
   22178      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
   22179      */
   22180     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
   22181         @Override
   22182         public void setValue(View object, float value) {
   22183             object.setRotationY(value);
   22184         }
   22185 
   22186         @Override
   22187         public Float get(View object) {
   22188             return object.getRotationY();
   22189         }
   22190     };
   22191 
   22192     /**
   22193      * A Property wrapper around the <code>scaleX</code> functionality handled by the
   22194      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
   22195      */
   22196     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
   22197         @Override
   22198         public void setValue(View object, float value) {
   22199             object.setScaleX(value);
   22200         }
   22201 
   22202         @Override
   22203         public Float get(View object) {
   22204             return object.getScaleX();
   22205         }
   22206     };
   22207 
   22208     /**
   22209      * A Property wrapper around the <code>scaleY</code> functionality handled by the
   22210      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
   22211      */
   22212     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
   22213         @Override
   22214         public void setValue(View object, float value) {
   22215             object.setScaleY(value);
   22216         }
   22217 
   22218         @Override
   22219         public Float get(View object) {
   22220             return object.getScaleY();
   22221         }
   22222     };
   22223 
   22224     /**
   22225      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
   22226      * Each MeasureSpec represents a requirement for either the width or the height.
   22227      * A MeasureSpec is comprised of a size and a mode. There are three possible
   22228      * modes:
   22229      * <dl>
   22230      * <dt>UNSPECIFIED</dt>
   22231      * <dd>
   22232      * The parent has not imposed any constraint on the child. It can be whatever size
   22233      * it wants.
   22234      * </dd>
   22235      *
   22236      * <dt>EXACTLY</dt>
   22237      * <dd>
   22238      * The parent has determined an exact size for the child. The child is going to be
   22239      * given those bounds regardless of how big it wants to be.
   22240      * </dd>
   22241      *
   22242      * <dt>AT_MOST</dt>
   22243      * <dd>
   22244      * The child can be as large as it wants up to the specified size.
   22245      * </dd>
   22246      * </dl>
   22247      *
   22248      * MeasureSpecs are implemented as ints to reduce object allocation. This class
   22249      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
   22250      */
   22251     public static class MeasureSpec {
   22252         private static final int MODE_SHIFT = 30;
   22253         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
   22254 
   22255         /** @hide */
   22256         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
   22257         @Retention(RetentionPolicy.SOURCE)
   22258         public @interface MeasureSpecMode {}
   22259 
   22260         /**
   22261          * Measure specification mode: The parent has not imposed any constraint
   22262          * on the child. It can be whatever size it wants.
   22263          */
   22264         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
   22265 
   22266         /**
   22267          * Measure specification mode: The parent has determined an exact size
   22268          * for the child. The child is going to be given those bounds regardless
   22269          * of how big it wants to be.
   22270          */
   22271         public static final int EXACTLY     = 1 << MODE_SHIFT;
   22272 
   22273         /**
   22274          * Measure specification mode: The child can be as large as it wants up
   22275          * to the specified size.
   22276          */
   22277         public static final int AT_MOST     = 2 << MODE_SHIFT;
   22278 
   22279         /**
   22280          * Creates a measure specification based on the supplied size and mode.
   22281          *
   22282          * The mode must always be one of the following:
   22283          * <ul>
   22284          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
   22285          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
   22286          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
   22287          * </ul>
   22288          *
   22289          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
   22290          * implementation was such that the order of arguments did not matter
   22291          * and overflow in either value could impact the resulting MeasureSpec.
   22292          * {@link android.widget.RelativeLayout} was affected by this bug.
   22293          * Apps targeting API levels greater than 17 will get the fixed, more strict
   22294          * behavior.</p>
   22295          *
   22296          * @param size the size of the measure specification
   22297          * @param mode the mode of the measure specification
   22298          * @return the measure specification based on size and mode
   22299          */
   22300         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
   22301                                           @MeasureSpecMode int mode) {
   22302             if (sUseBrokenMakeMeasureSpec) {
   22303                 return size + mode;
   22304             } else {
   22305                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
   22306             }
   22307         }
   22308 
   22309         /**
   22310          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
   22311          * will automatically get a size of 0. Older apps expect this.
   22312          *
   22313          * @hide internal use only for compatibility with system widgets and older apps
   22314          */
   22315         public static int makeSafeMeasureSpec(int size, int mode) {
   22316             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
   22317                 return 0;
   22318             }
   22319             return makeMeasureSpec(size, mode);
   22320         }
   22321 
   22322         /**
   22323          * Extracts the mode from the supplied measure specification.
   22324          *
   22325          * @param measureSpec the measure specification to extract the mode from
   22326          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
   22327          *         {@link android.view.View.MeasureSpec#AT_MOST} or
   22328          *         {@link android.view.View.MeasureSpec#EXACTLY}
   22329          */
   22330         @MeasureSpecMode
   22331         public static int getMode(int measureSpec) {
   22332             //noinspection ResourceType
   22333             return (measureSpec & MODE_MASK);
   22334         }
   22335 
   22336         /**
   22337          * Extracts the size from the supplied measure specification.
   22338          *
   22339          * @param measureSpec the measure specification to extract the size from
   22340          * @return the size in pixels defined in the supplied measure specification
   22341          */
   22342         public static int getSize(int measureSpec) {
   22343             return (measureSpec & ~MODE_MASK);
   22344         }
   22345 
   22346         static int adjust(int measureSpec, int delta) {
   22347             final int mode = getMode(measureSpec);
   22348             int size = getSize(measureSpec);
   22349             if (mode == UNSPECIFIED) {
   22350                 // No need to adjust size for UNSPECIFIED mode.
   22351                 return makeMeasureSpec(size, UNSPECIFIED);
   22352             }
   22353             size += delta;
   22354             if (size < 0) {
   22355                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
   22356                         ") spec: " + toString(measureSpec) + " delta: " + delta);
   22357                 size = 0;
   22358             }
   22359             return makeMeasureSpec(size, mode);
   22360         }
   22361 
   22362         /**
   22363          * Returns a String representation of the specified measure
   22364          * specification.
   22365          *
   22366          * @param measureSpec the measure specification to convert to a String
   22367          * @return a String with the following format: "MeasureSpec: MODE SIZE"
   22368          */
   22369         public static String toString(int measureSpec) {
   22370             int mode = getMode(measureSpec);
   22371             int size = getSize(measureSpec);
   22372 
   22373             StringBuilder sb = new StringBuilder("MeasureSpec: ");
   22374 
   22375             if (mode == UNSPECIFIED)
   22376                 sb.append("UNSPECIFIED ");
   22377             else if (mode == EXACTLY)
   22378                 sb.append("EXACTLY ");
   22379             else if (mode == AT_MOST)
   22380                 sb.append("AT_MOST ");
   22381             else
   22382                 sb.append(mode).append(" ");
   22383 
   22384             sb.append(size);
   22385             return sb.toString();
   22386         }
   22387     }
   22388 
   22389     private final class CheckForLongPress implements Runnable {
   22390         private int mOriginalWindowAttachCount;
   22391         private float mX;
   22392         private float mY;
   22393 
   22394         @Override
   22395         public void run() {
   22396             if (isPressed() && (mParent != null)
   22397                     && mOriginalWindowAttachCount == mWindowAttachCount) {
   22398                 if (performLongClick(mX, mY)) {
   22399                     mHasPerformedLongPress = true;
   22400                 }
   22401             }
   22402         }
   22403 
   22404         public void setAnchor(float x, float y) {
   22405             mX = x;
   22406             mY = y;
   22407         }
   22408 
   22409         public void rememberWindowAttachCount() {
   22410             mOriginalWindowAttachCount = mWindowAttachCount;
   22411         }
   22412     }
   22413 
   22414     private final class CheckForTap implements Runnable {
   22415         public float x;
   22416         public float y;
   22417 
   22418         @Override
   22419         public void run() {
   22420             mPrivateFlags &= ~PFLAG_PREPRESSED;
   22421             setPressed(true, x, y);
   22422             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
   22423         }
   22424     }
   22425 
   22426     private final class PerformClick implements Runnable {
   22427         @Override
   22428         public void run() {
   22429             performClick();
   22430         }
   22431     }
   22432 
   22433     /**
   22434      * This method returns a ViewPropertyAnimator object, which can be used to animate
   22435      * specific properties on this View.
   22436      *
   22437      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
   22438      */
   22439     public ViewPropertyAnimator animate() {
   22440         if (mAnimator == null) {
   22441             mAnimator = new ViewPropertyAnimator(this);
   22442         }
   22443         return mAnimator;
   22444     }
   22445 
   22446     /**
   22447      * Sets the name of the View to be used to identify Views in Transitions.
   22448      * Names should be unique in the View hierarchy.
   22449      *
   22450      * @param transitionName The name of the View to uniquely identify it for Transitions.
   22451      */
   22452     public final void setTransitionName(String transitionName) {
   22453         mTransitionName = transitionName;
   22454     }
   22455 
   22456     /**
   22457      * Returns the name of the View to be used to identify Views in Transitions.
   22458      * Names should be unique in the View hierarchy.
   22459      *
   22460      * <p>This returns null if the View has not been given a name.</p>
   22461      *
   22462      * @return The name used of the View to be used to identify Views in Transitions or null
   22463      * if no name has been given.
   22464      */
   22465     @ViewDebug.ExportedProperty
   22466     public String getTransitionName() {
   22467         return mTransitionName;
   22468     }
   22469 
   22470     /**
   22471      * @hide
   22472      */
   22473     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
   22474         // Do nothing.
   22475     }
   22476 
   22477     /**
   22478      * Interface definition for a callback to be invoked when a hardware key event is
   22479      * dispatched to this view. The callback will be invoked before the key event is
   22480      * given to the view. This is only useful for hardware keyboards; a software input
   22481      * method has no obligation to trigger this listener.
   22482      */
   22483     public interface OnKeyListener {
   22484         /**
   22485          * Called when a hardware key is dispatched to a view. This allows listeners to
   22486          * get a chance to respond before the target view.
   22487          * <p>Key presses in software keyboards will generally NOT trigger this method,
   22488          * although some may elect to do so in some situations. Do not assume a
   22489          * software input method has to be key-based; even if it is, it may use key presses
   22490          * in a different way than you expect, so there is no way to reliably catch soft
   22491          * input key presses.
   22492          *
   22493          * @param v The view the key has been dispatched to.
   22494          * @param keyCode The code for the physical key that was pressed
   22495          * @param event The KeyEvent object containing full information about
   22496          *        the event.
   22497          * @return True if the listener has consumed the event, false otherwise.
   22498          */
   22499         boolean onKey(View v, int keyCode, KeyEvent event);
   22500     }
   22501 
   22502     /**
   22503      * Interface definition for a callback to be invoked when a touch event is
   22504      * dispatched to this view. The callback will be invoked before the touch
   22505      * event is given to the view.
   22506      */
   22507     public interface OnTouchListener {
   22508         /**
   22509          * Called when a touch event is dispatched to a view. This allows listeners to
   22510          * get a chance to respond before the target view.
   22511          *
   22512          * @param v The view the touch event has been dispatched to.
   22513          * @param event The MotionEvent object containing full information about
   22514          *        the event.
   22515          * @return True if the listener has consumed the event, false otherwise.
   22516          */
   22517         boolean onTouch(View v, MotionEvent event);
   22518     }
   22519 
   22520     /**
   22521      * Interface definition for a callback to be invoked when a hover event is
   22522      * dispatched to this view. The callback will be invoked before the hover
   22523      * event is given to the view.
   22524      */
   22525     public interface OnHoverListener {
   22526         /**
   22527          * Called when a hover event is dispatched to a view. This allows listeners to
   22528          * get a chance to respond before the target view.
   22529          *
   22530          * @param v The view the hover event has been dispatched to.
   22531          * @param event The MotionEvent object containing full information about
   22532          *        the event.
   22533          * @return True if the listener has consumed the event, false otherwise.
   22534          */
   22535         boolean onHover(View v, MotionEvent event);
   22536     }
   22537 
   22538     /**
   22539      * Interface definition for a callback to be invoked when a generic motion event is
   22540      * dispatched to this view. The callback will be invoked before the generic motion
   22541      * event is given to the view.
   22542      */
   22543     public interface OnGenericMotionListener {
   22544         /**
   22545          * Called when a generic motion event is dispatched to a view. This allows listeners to
   22546          * get a chance to respond before the target view.
   22547          *
   22548          * @param v The view the generic motion event has been dispatched to.
   22549          * @param event The MotionEvent object containing full information about
   22550          *        the event.
   22551          * @return True if the listener has consumed the event, false otherwise.
   22552          */
   22553         boolean onGenericMotion(View v, MotionEvent event);
   22554     }
   22555 
   22556     /**
   22557      * Interface definition for a callback to be invoked when a view has been clicked and held.
   22558      */
   22559     public interface OnLongClickListener {
   22560         /**
   22561          * Called when a view has been clicked and held.
   22562          *
   22563          * @param v The view that was clicked and held.
   22564          *
   22565          * @return true if the callback consumed the long click, false otherwise.
   22566          */
   22567         boolean onLongClick(View v);
   22568     }
   22569 
   22570     /**
   22571      * Interface definition for a callback to be invoked when a drag is being dispatched
   22572      * to this view.  The callback will be invoked before the hosting view's own
   22573      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
   22574      * onDrag(event) behavior, it should return 'false' from this callback.
   22575      *
   22576      * <div class="special reference">
   22577      * <h3>Developer Guides</h3>
   22578      * <p>For a guide to implementing drag and drop features, read the
   22579      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   22580      * </div>
   22581      */
   22582     public interface OnDragListener {
   22583         /**
   22584          * Called when a drag event is dispatched to a view. This allows listeners
   22585          * to get a chance to override base View behavior.
   22586          *
   22587          * @param v The View that received the drag event.
   22588          * @param event The {@link android.view.DragEvent} object for the drag event.
   22589          * @return {@code true} if the drag event was handled successfully, or {@code false}
   22590          * if the drag event was not handled. Note that {@code false} will trigger the View
   22591          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
   22592          */
   22593         boolean onDrag(View v, DragEvent event);
   22594     }
   22595 
   22596     /**
   22597      * Interface definition for a callback to be invoked when the focus state of
   22598      * a view changed.
   22599      */
   22600     public interface OnFocusChangeListener {
   22601         /**
   22602          * Called when the focus state of a view has changed.
   22603          *
   22604          * @param v The view whose state has changed.
   22605          * @param hasFocus The new focus state of v.
   22606          */
   22607         void onFocusChange(View v, boolean hasFocus);
   22608     }
   22609 
   22610     /**
   22611      * Interface definition for a callback to be invoked when a view is clicked.
   22612      */
   22613     public interface OnClickListener {
   22614         /**
   22615          * Called when a view has been clicked.
   22616          *
   22617          * @param v The view that was clicked.
   22618          */
   22619         void onClick(View v);
   22620     }
   22621 
   22622     /**
   22623      * Interface definition for a callback to be invoked when a view is context clicked.
   22624      */
   22625     public interface OnContextClickListener {
   22626         /**
   22627          * Called when a view is context clicked.
   22628          *
   22629          * @param v The view that has been context clicked.
   22630          * @return true if the callback consumed the context click, false otherwise.
   22631          */
   22632         boolean onContextClick(View v);
   22633     }
   22634 
   22635     /**
   22636      * Interface definition for a callback to be invoked when the context menu
   22637      * for this view is being built.
   22638      */
   22639     public interface OnCreateContextMenuListener {
   22640         /**
   22641          * Called when the context menu for this view is being built. It is not
   22642          * safe to hold onto the menu after this method returns.
   22643          *
   22644          * @param menu The context menu that is being built
   22645          * @param v The view for which the context menu is being built
   22646          * @param menuInfo Extra information about the item for which the
   22647          *            context menu should be shown. This information will vary
   22648          *            depending on the class of v.
   22649          */
   22650         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
   22651     }
   22652 
   22653     /**
   22654      * Interface definition for a callback to be invoked when the status bar changes
   22655      * visibility.  This reports <strong>global</strong> changes to the system UI
   22656      * state, not what the application is requesting.
   22657      *
   22658      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
   22659      */
   22660     public interface OnSystemUiVisibilityChangeListener {
   22661         /**
   22662          * Called when the status bar changes visibility because of a call to
   22663          * {@link View#setSystemUiVisibility(int)}.
   22664          *
   22665          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   22666          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
   22667          * This tells you the <strong>global</strong> state of these UI visibility
   22668          * flags, not what your app is currently applying.
   22669          */
   22670         public void onSystemUiVisibilityChange(int visibility);
   22671     }
   22672 
   22673     /**
   22674      * Interface definition for a callback to be invoked when this view is attached
   22675      * or detached from its window.
   22676      */
   22677     public interface OnAttachStateChangeListener {
   22678         /**
   22679          * Called when the view is attached to a window.
   22680          * @param v The view that was attached
   22681          */
   22682         public void onViewAttachedToWindow(View v);
   22683         /**
   22684          * Called when the view is detached from a window.
   22685          * @param v The view that was detached
   22686          */
   22687         public void onViewDetachedFromWindow(View v);
   22688     }
   22689 
   22690     /**
   22691      * Listener for applying window insets on a view in a custom way.
   22692      *
   22693      * <p>Apps may choose to implement this interface if they want to apply custom policy
   22694      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
   22695      * is set, its
   22696      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   22697      * method will be called instead of the View's own
   22698      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
   22699      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
   22700      * the View's normal behavior as part of its own.</p>
   22701      */
   22702     public interface OnApplyWindowInsetsListener {
   22703         /**
   22704          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
   22705          * on a View, this listener method will be called instead of the view's own
   22706          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   22707          *
   22708          * @param v The view applying window insets
   22709          * @param insets The insets to apply
   22710          * @return The insets supplied, minus any insets that were consumed
   22711          */
   22712         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
   22713     }
   22714 
   22715     private final class UnsetPressedState implements Runnable {
   22716         @Override
   22717         public void run() {
   22718             setPressed(false);
   22719         }
   22720     }
   22721 
   22722     /**
   22723      * Base class for derived classes that want to save and restore their own
   22724      * state in {@link android.view.View#onSaveInstanceState()}.
   22725      */
   22726     public static class BaseSavedState extends AbsSavedState {
   22727         String mStartActivityRequestWhoSaved;
   22728 
   22729         /**
   22730          * Constructor used when reading from a parcel. Reads the state of the superclass.
   22731          *
   22732          * @param source parcel to read from
   22733          */
   22734         public BaseSavedState(Parcel source) {
   22735             this(source, null);
   22736         }
   22737 
   22738         /**
   22739          * Constructor used when reading from a parcel using a given class loader.
   22740          * Reads the state of the superclass.
   22741          *
   22742          * @param source parcel to read from
   22743          * @param loader ClassLoader to use for reading
   22744          */
   22745         public BaseSavedState(Parcel source, ClassLoader loader) {
   22746             super(source, loader);
   22747             mStartActivityRequestWhoSaved = source.readString();
   22748         }
   22749 
   22750         /**
   22751          * Constructor called by derived classes when creating their SavedState objects
   22752          *
   22753          * @param superState The state of the superclass of this view
   22754          */
   22755         public BaseSavedState(Parcelable superState) {
   22756             super(superState);
   22757         }
   22758 
   22759         @Override
   22760         public void writeToParcel(Parcel out, int flags) {
   22761             super.writeToParcel(out, flags);
   22762             out.writeString(mStartActivityRequestWhoSaved);
   22763         }
   22764 
   22765         public static final Parcelable.Creator<BaseSavedState> CREATOR
   22766                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
   22767             @Override
   22768             public BaseSavedState createFromParcel(Parcel in) {
   22769                 return new BaseSavedState(in);
   22770             }
   22771 
   22772             @Override
   22773             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
   22774                 return new BaseSavedState(in, loader);
   22775             }
   22776 
   22777             @Override
   22778             public BaseSavedState[] newArray(int size) {
   22779                 return new BaseSavedState[size];
   22780             }
   22781         };
   22782     }
   22783 
   22784     /**
   22785      * A set of information given to a view when it is attached to its parent
   22786      * window.
   22787      */
   22788     final static class AttachInfo {
   22789         interface Callbacks {
   22790             void playSoundEffect(int effectId);
   22791             boolean performHapticFeedback(int effectId, boolean always);
   22792         }
   22793 
   22794         /**
   22795          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
   22796          * to a Handler. This class contains the target (View) to invalidate and
   22797          * the coordinates of the dirty rectangle.
   22798          *
   22799          * For performance purposes, this class also implements a pool of up to
   22800          * POOL_LIMIT objects that get reused. This reduces memory allocations
   22801          * whenever possible.
   22802          */
   22803         static class InvalidateInfo {
   22804             private static final int POOL_LIMIT = 10;
   22805 
   22806             private static final SynchronizedPool<InvalidateInfo> sPool =
   22807                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
   22808 
   22809             View target;
   22810 
   22811             int left;
   22812             int top;
   22813             int right;
   22814             int bottom;
   22815 
   22816             public static InvalidateInfo obtain() {
   22817                 InvalidateInfo instance = sPool.acquire();
   22818                 return (instance != null) ? instance : new InvalidateInfo();
   22819             }
   22820 
   22821             public void recycle() {
   22822                 target = null;
   22823                 sPool.release(this);
   22824             }
   22825         }
   22826 
   22827         final IWindowSession mSession;
   22828 
   22829         final IWindow mWindow;
   22830 
   22831         final IBinder mWindowToken;
   22832 
   22833         final Display mDisplay;
   22834 
   22835         final Callbacks mRootCallbacks;
   22836 
   22837         IWindowId mIWindowId;
   22838         WindowId mWindowId;
   22839 
   22840         /**
   22841          * The top view of the hierarchy.
   22842          */
   22843         View mRootView;
   22844 
   22845         IBinder mPanelParentWindowToken;
   22846 
   22847         boolean mHardwareAccelerated;
   22848         boolean mHardwareAccelerationRequested;
   22849         ThreadedRenderer mHardwareRenderer;
   22850         List<RenderNode> mPendingAnimatingRenderNodes;
   22851 
   22852         /**
   22853          * The state of the display to which the window is attached, as reported
   22854          * by {@link Display#getState()}.  Note that the display state constants
   22855          * declared by {@link Display} do not exactly line up with the screen state
   22856          * constants declared by {@link View} (there are more display states than
   22857          * screen states).
   22858          */
   22859         int mDisplayState = Display.STATE_UNKNOWN;
   22860 
   22861         /**
   22862          * Scale factor used by the compatibility mode
   22863          */
   22864         float mApplicationScale;
   22865 
   22866         /**
   22867          * Indicates whether the application is in compatibility mode
   22868          */
   22869         boolean mScalingRequired;
   22870 
   22871         /**
   22872          * Left position of this view's window
   22873          */
   22874         int mWindowLeft;
   22875 
   22876         /**
   22877          * Top position of this view's window
   22878          */
   22879         int mWindowTop;
   22880 
   22881         /**
   22882          * Indicates whether views need to use 32-bit drawing caches
   22883          */
   22884         boolean mUse32BitDrawingCache;
   22885 
   22886         /**
   22887          * For windows that are full-screen but using insets to layout inside
   22888          * of the screen areas, these are the current insets to appear inside
   22889          * the overscan area of the display.
   22890          */
   22891         final Rect mOverscanInsets = new Rect();
   22892 
   22893         /**
   22894          * For windows that are full-screen but using insets to layout inside
   22895          * of the screen decorations, these are the current insets for the
   22896          * content of the window.
   22897          */
   22898         final Rect mContentInsets = new Rect();
   22899 
   22900         /**
   22901          * For windows that are full-screen but using insets to layout inside
   22902          * of the screen decorations, these are the current insets for the
   22903          * actual visible parts of the window.
   22904          */
   22905         final Rect mVisibleInsets = new Rect();
   22906 
   22907         /**
   22908          * For windows that are full-screen but using insets to layout inside
   22909          * of the screen decorations, these are the current insets for the
   22910          * stable system windows.
   22911          */
   22912         final Rect mStableInsets = new Rect();
   22913 
   22914         /**
   22915          * For windows that include areas that are not covered by real surface these are the outsets
   22916          * for real surface.
   22917          */
   22918         final Rect mOutsets = new Rect();
   22919 
   22920         /**
   22921          * In multi-window we force show the navigation bar. Because we don't want that the surface
   22922          * size changes in this mode, we instead have a flag whether the navigation bar size should
   22923          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
   22924          */
   22925         boolean mAlwaysConsumeNavBar;
   22926 
   22927         /**
   22928          * The internal insets given by this window.  This value is
   22929          * supplied by the client (through
   22930          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
   22931          * be given to the window manager when changed to be used in laying
   22932          * out windows behind it.
   22933          */
   22934         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
   22935                 = new ViewTreeObserver.InternalInsetsInfo();
   22936 
   22937         /**
   22938          * Set to true when mGivenInternalInsets is non-empty.
   22939          */
   22940         boolean mHasNonEmptyGivenInternalInsets;
   22941 
   22942         /**
   22943          * All views in the window's hierarchy that serve as scroll containers,
   22944          * used to determine if the window can be resized or must be panned
   22945          * to adjust for a soft input area.
   22946          */
   22947         final ArrayList<View> mScrollContainers = new ArrayList<View>();
   22948 
   22949         final KeyEvent.DispatcherState mKeyDispatchState
   22950                 = new KeyEvent.DispatcherState();
   22951 
   22952         /**
   22953          * Indicates whether the view's window currently has the focus.
   22954          */
   22955         boolean mHasWindowFocus;
   22956 
   22957         /**
   22958          * The current visibility of the window.
   22959          */
   22960         int mWindowVisibility;
   22961 
   22962         /**
   22963          * Indicates the time at which drawing started to occur.
   22964          */
   22965         long mDrawingTime;
   22966 
   22967         /**
   22968          * Indicates whether or not ignoring the DIRTY_MASK flags.
   22969          */
   22970         boolean mIgnoreDirtyState;
   22971 
   22972         /**
   22973          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
   22974          * to avoid clearing that flag prematurely.
   22975          */
   22976         boolean mSetIgnoreDirtyState = false;
   22977 
   22978         /**
   22979          * Indicates whether the view's window is currently in touch mode.
   22980          */
   22981         boolean mInTouchMode;
   22982 
   22983         /**
   22984          * Indicates whether the view has requested unbuffered input dispatching for the current
   22985          * event stream.
   22986          */
   22987         boolean mUnbufferedDispatchRequested;
   22988 
   22989         /**
   22990          * Indicates that ViewAncestor should trigger a global layout change
   22991          * the next time it performs a traversal
   22992          */
   22993         boolean mRecomputeGlobalAttributes;
   22994 
   22995         /**
   22996          * Always report new attributes at next traversal.
   22997          */
   22998         boolean mForceReportNewAttributes;
   22999 
   23000         /**
   23001          * Set during a traveral if any views want to keep the screen on.
   23002          */
   23003         boolean mKeepScreenOn;
   23004 
   23005         /**
   23006          * Set during a traveral if the light center needs to be updated.
   23007          */
   23008         boolean mNeedsUpdateLightCenter;
   23009 
   23010         /**
   23011          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
   23012          */
   23013         int mSystemUiVisibility;
   23014 
   23015         /**
   23016          * Hack to force certain system UI visibility flags to be cleared.
   23017          */
   23018         int mDisabledSystemUiVisibility;
   23019 
   23020         /**
   23021          * Last global system UI visibility reported by the window manager.
   23022          */
   23023         int mGlobalSystemUiVisibility = -1;
   23024 
   23025         /**
   23026          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
   23027          * attached.
   23028          */
   23029         boolean mHasSystemUiListeners;
   23030 
   23031         /**
   23032          * Set if the window has requested to extend into the overscan region
   23033          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
   23034          */
   23035         boolean mOverscanRequested;
   23036 
   23037         /**
   23038          * Set if the visibility of any views has changed.
   23039          */
   23040         boolean mViewVisibilityChanged;
   23041 
   23042         /**
   23043          * Set to true if a view has been scrolled.
   23044          */
   23045         boolean mViewScrollChanged;
   23046 
   23047         /**
   23048          * Set to true if high contrast mode enabled
   23049          */
   23050         boolean mHighContrastText;
   23051 
   23052         /**
   23053          * Set to true if a pointer event is currently being handled.
   23054          */
   23055         boolean mHandlingPointerEvent;
   23056 
   23057         /**
   23058          * Global to the view hierarchy used as a temporary for dealing with
   23059          * x/y points in the transparent region computations.
   23060          */
   23061         final int[] mTransparentLocation = new int[2];
   23062 
   23063         /**
   23064          * Global to the view hierarchy used as a temporary for dealing with
   23065          * x/y points in the ViewGroup.invalidateChild implementation.
   23066          */
   23067         final int[] mInvalidateChildLocation = new int[2];
   23068 
   23069         /**
   23070          * Global to the view hierarchy used as a temporary for dealing with
   23071          * computing absolute on-screen location.
   23072          */
   23073         final int[] mTmpLocation = new int[2];
   23074 
   23075         /**
   23076          * Global to the view hierarchy used as a temporary for dealing with
   23077          * x/y location when view is transformed.
   23078          */
   23079         final float[] mTmpTransformLocation = new float[2];
   23080 
   23081         /**
   23082          * The view tree observer used to dispatch global events like
   23083          * layout, pre-draw, touch mode change, etc.
   23084          */
   23085         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
   23086 
   23087         /**
   23088          * A Canvas used by the view hierarchy to perform bitmap caching.
   23089          */
   23090         Canvas mCanvas;
   23091 
   23092         /**
   23093          * The view root impl.
   23094          */
   23095         final ViewRootImpl mViewRootImpl;
   23096 
   23097         /**
   23098          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
   23099          * handler can be used to pump events in the UI events queue.
   23100          */
   23101         final Handler mHandler;
   23102 
   23103         /**
   23104          * Temporary for use in computing invalidate rectangles while
   23105          * calling up the hierarchy.
   23106          */
   23107         final Rect mTmpInvalRect = new Rect();
   23108 
   23109         /**
   23110          * Temporary for use in computing hit areas with transformed views
   23111          */
   23112         final RectF mTmpTransformRect = new RectF();
   23113 
   23114         /**
   23115          * Temporary for use in computing hit areas with transformed views
   23116          */
   23117         final RectF mTmpTransformRect1 = new RectF();
   23118 
   23119         /**
   23120          * Temporary list of rectanges.
   23121          */
   23122         final List<RectF> mTmpRectList = new ArrayList<>();
   23123 
   23124         /**
   23125          * Temporary for use in transforming invalidation rect
   23126          */
   23127         final Matrix mTmpMatrix = new Matrix();
   23128 
   23129         /**
   23130          * Temporary for use in transforming invalidation rect
   23131          */
   23132         final Transformation mTmpTransformation = new Transformation();
   23133 
   23134         /**
   23135          * Temporary for use in querying outlines from OutlineProviders
   23136          */
   23137         final Outline mTmpOutline = new Outline();
   23138 
   23139         /**
   23140          * Temporary list for use in collecting focusable descendents of a view.
   23141          */
   23142         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
   23143 
   23144         /**
   23145          * The id of the window for accessibility purposes.
   23146          */
   23147         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
   23148 
   23149         /**
   23150          * Flags related to accessibility processing.
   23151          *
   23152          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   23153          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
   23154          */
   23155         int mAccessibilityFetchFlags;
   23156 
   23157         /**
   23158          * The drawable for highlighting accessibility focus.
   23159          */
   23160         Drawable mAccessibilityFocusDrawable;
   23161 
   23162         /**
   23163          * Show where the margins, bounds and layout bounds are for each view.
   23164          */
   23165         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
   23166 
   23167         /**
   23168          * Point used to compute visible regions.
   23169          */
   23170         final Point mPoint = new Point();
   23171 
   23172         /**
   23173          * Used to track which View originated a requestLayout() call, used when
   23174          * requestLayout() is called during layout.
   23175          */
   23176         View mViewRequestingLayout;
   23177 
   23178         /**
   23179          * Used to track views that need (at least) a partial relayout at their current size
   23180          * during the next traversal.
   23181          */
   23182         List<View> mPartialLayoutViews = new ArrayList<>();
   23183 
   23184         /**
   23185          * Swapped with mPartialLayoutViews during layout to avoid concurrent
   23186          * modification. Lazily assigned during ViewRootImpl layout.
   23187          */
   23188         List<View> mEmptyPartialLayoutViews;
   23189 
   23190         /**
   23191          * Used to track the identity of the current drag operation.
   23192          */
   23193         IBinder mDragToken;
   23194 
   23195         /**
   23196          * The drag shadow surface for the current drag operation.
   23197          */
   23198         public Surface mDragSurface;
   23199 
   23200         /**
   23201          * Creates a new set of attachment information with the specified
   23202          * events handler and thread.
   23203          *
   23204          * @param handler the events handler the view must use
   23205          */
   23206         AttachInfo(IWindowSession session, IWindow window, Display display,
   23207                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
   23208             mSession = session;
   23209             mWindow = window;
   23210             mWindowToken = window.asBinder();
   23211             mDisplay = display;
   23212             mViewRootImpl = viewRootImpl;
   23213             mHandler = handler;
   23214             mRootCallbacks = effectPlayer;
   23215         }
   23216     }
   23217 
   23218     /**
   23219      * <p>ScrollabilityCache holds various fields used by a View when scrolling
   23220      * is supported. This avoids keeping too many unused fields in most
   23221      * instances of View.</p>
   23222      */
   23223     private static class ScrollabilityCache implements Runnable {
   23224 
   23225         /**
   23226          * Scrollbars are not visible
   23227          */
   23228         public static final int OFF = 0;
   23229 
   23230         /**
   23231          * Scrollbars are visible
   23232          */
   23233         public static final int ON = 1;
   23234 
   23235         /**
   23236          * Scrollbars are fading away
   23237          */
   23238         public static final int FADING = 2;
   23239 
   23240         public boolean fadeScrollBars;
   23241 
   23242         public int fadingEdgeLength;
   23243         public int scrollBarDefaultDelayBeforeFade;
   23244         public int scrollBarFadeDuration;
   23245 
   23246         public int scrollBarSize;
   23247         public ScrollBarDrawable scrollBar;
   23248         public float[] interpolatorValues;
   23249         public View host;
   23250 
   23251         public final Paint paint;
   23252         public final Matrix matrix;
   23253         public Shader shader;
   23254 
   23255         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
   23256 
   23257         private static final float[] OPAQUE = { 255 };
   23258         private static final float[] TRANSPARENT = { 0.0f };
   23259 
   23260         /**
   23261          * When fading should start. This time moves into the future every time
   23262          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
   23263          */
   23264         public long fadeStartTime;
   23265 
   23266 
   23267         /**
   23268          * The current state of the scrollbars: ON, OFF, or FADING
   23269          */
   23270         public int state = OFF;
   23271 
   23272         private int mLastColor;
   23273 
   23274         public final Rect mScrollBarBounds = new Rect();
   23275 
   23276         public static final int NOT_DRAGGING = 0;
   23277         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
   23278         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
   23279         public int mScrollBarDraggingState = NOT_DRAGGING;
   23280 
   23281         public float mScrollBarDraggingPos = 0;
   23282 
   23283         public ScrollabilityCache(ViewConfiguration configuration, View host) {
   23284             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
   23285             scrollBarSize = configuration.getScaledScrollBarSize();
   23286             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
   23287             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
   23288 
   23289             paint = new Paint();
   23290             matrix = new Matrix();
   23291             // use use a height of 1, and then wack the matrix each time we
   23292             // actually use it.
   23293             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   23294             paint.setShader(shader);
   23295             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   23296 
   23297             this.host = host;
   23298         }
   23299 
   23300         public void setFadeColor(int color) {
   23301             if (color != mLastColor) {
   23302                 mLastColor = color;
   23303 
   23304                 if (color != 0) {
   23305                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
   23306                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
   23307                     paint.setShader(shader);
   23308                     // Restore the default transfer mode (src_over)
   23309                     paint.setXfermode(null);
   23310                 } else {
   23311                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   23312                     paint.setShader(shader);
   23313                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   23314                 }
   23315             }
   23316         }
   23317 
   23318         public void run() {
   23319             long now = AnimationUtils.currentAnimationTimeMillis();
   23320             if (now >= fadeStartTime) {
   23321 
   23322                 // the animation fades the scrollbars out by changing
   23323                 // the opacity (alpha) from fully opaque to fully
   23324                 // transparent
   23325                 int nextFrame = (int) now;
   23326                 int framesCount = 0;
   23327 
   23328                 Interpolator interpolator = scrollBarInterpolator;
   23329 
   23330                 // Start opaque
   23331                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
   23332 
   23333                 // End transparent
   23334                 nextFrame += scrollBarFadeDuration;
   23335                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
   23336 
   23337                 state = FADING;
   23338 
   23339                 // Kick off the fade animation
   23340                 host.invalidate(true);
   23341             }
   23342         }
   23343     }
   23344 
   23345     /**
   23346      * Resuable callback for sending
   23347      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   23348      */
   23349     private class SendViewScrolledAccessibilityEvent implements Runnable {
   23350         public volatile boolean mIsPending;
   23351 
   23352         public void run() {
   23353             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
   23354             mIsPending = false;
   23355         }
   23356     }
   23357 
   23358     /**
   23359      * <p>
   23360      * This class represents a delegate that can be registered in a {@link View}
   23361      * to enhance accessibility support via composition rather via inheritance.
   23362      * It is specifically targeted to widget developers that extend basic View
   23363      * classes i.e. classes in package android.view, that would like their
   23364      * applications to be backwards compatible.
   23365      * </p>
   23366      * <div class="special reference">
   23367      * <h3>Developer Guides</h3>
   23368      * <p>For more information about making applications accessible, read the
   23369      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
   23370      * developer guide.</p>
   23371      * </div>
   23372      * <p>
   23373      * A scenario in which a developer would like to use an accessibility delegate
   23374      * is overriding a method introduced in a later API version then the minimal API
   23375      * version supported by the application. For example, the method
   23376      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
   23377      * in API version 4 when the accessibility APIs were first introduced. If a
   23378      * developer would like his application to run on API version 4 devices (assuming
   23379      * all other APIs used by the application are version 4 or lower) and take advantage
   23380      * of this method, instead of overriding the method which would break the application's
   23381      * backwards compatibility, he can override the corresponding method in this
   23382      * delegate and register the delegate in the target View if the API version of
   23383      * the system is high enough i.e. the API version is same or higher to the API
   23384      * version that introduced
   23385      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
   23386      * </p>
   23387      * <p>
   23388      * Here is an example implementation:
   23389      * </p>
   23390      * <code><pre><p>
   23391      * if (Build.VERSION.SDK_INT >= 14) {
   23392      *     // If the API version is equal of higher than the version in
   23393      *     // which onInitializeAccessibilityNodeInfo was introduced we
   23394      *     // register a delegate with a customized implementation.
   23395      *     View view = findViewById(R.id.view_id);
   23396      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
   23397      *         public void onInitializeAccessibilityNodeInfo(View host,
   23398      *                 AccessibilityNodeInfo info) {
   23399      *             // Let the default implementation populate the info.
   23400      *             super.onInitializeAccessibilityNodeInfo(host, info);
   23401      *             // Set some other information.
   23402      *             info.setEnabled(host.isEnabled());
   23403      *         }
   23404      *     });
   23405      * }
   23406      * </code></pre></p>
   23407      * <p>
   23408      * This delegate contains methods that correspond to the accessibility methods
   23409      * in View. If a delegate has been specified the implementation in View hands
   23410      * off handling to the corresponding method in this delegate. The default
   23411      * implementation the delegate methods behaves exactly as the corresponding
   23412      * method in View for the case of no accessibility delegate been set. Hence,
   23413      * to customize the behavior of a View method, clients can override only the
   23414      * corresponding delegate method without altering the behavior of the rest
   23415      * accessibility related methods of the host view.
   23416      * </p>
   23417      * <p>
   23418      * <strong>Note:</strong> On platform versions prior to
   23419      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
   23420      * views in the {@code android.widget.*} package are called <i>before</i>
   23421      * host methods. This prevents certain properties such as class name from
   23422      * being modified by overriding
   23423      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
   23424      * as any changes will be overwritten by the host class.
   23425      * <p>
   23426      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
   23427      * methods are called <i>after</i> host methods, which all properties to be
   23428      * modified without being overwritten by the host class.
   23429      */
   23430     public static class AccessibilityDelegate {
   23431 
   23432         /**
   23433          * Sends an accessibility event of the given type. If accessibility is not
   23434          * enabled this method has no effect.
   23435          * <p>
   23436          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
   23437          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
   23438          * been set.
   23439          * </p>
   23440          *
   23441          * @param host The View hosting the delegate.
   23442          * @param eventType The type of the event to send.
   23443          *
   23444          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
   23445          */
   23446         public void sendAccessibilityEvent(View host, int eventType) {
   23447             host.sendAccessibilityEventInternal(eventType);
   23448         }
   23449 
   23450         /**
   23451          * Performs the specified accessibility action on the view. For
   23452          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   23453          * <p>
   23454          * The default implementation behaves as
   23455          * {@link View#performAccessibilityAction(int, Bundle)
   23456          *  View#performAccessibilityAction(int, Bundle)} for the case of
   23457          *  no accessibility delegate been set.
   23458          * </p>
   23459          *
   23460          * @param action The action to perform.
   23461          * @return Whether the action was performed.
   23462          *
   23463          * @see View#performAccessibilityAction(int, Bundle)
   23464          *      View#performAccessibilityAction(int, Bundle)
   23465          */
   23466         public boolean performAccessibilityAction(View host, int action, Bundle args) {
   23467             return host.performAccessibilityActionInternal(action, args);
   23468         }
   23469 
   23470         /**
   23471          * Sends an accessibility event. This method behaves exactly as
   23472          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
   23473          * empty {@link AccessibilityEvent} and does not perform a check whether
   23474          * accessibility is enabled.
   23475          * <p>
   23476          * The default implementation behaves as
   23477          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   23478          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
   23479          * the case of no accessibility delegate been set.
   23480          * </p>
   23481          *
   23482          * @param host The View hosting the delegate.
   23483          * @param event The event to send.
   23484          *
   23485          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   23486          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   23487          */
   23488         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
   23489             host.sendAccessibilityEventUncheckedInternal(event);
   23490         }
   23491 
   23492         /**
   23493          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
   23494          * to its children for adding their text content to the event.
   23495          * <p>
   23496          * The default implementation behaves as
   23497          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   23498          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
   23499          * the case of no accessibility delegate been set.
   23500          * </p>
   23501          *
   23502          * @param host The View hosting the delegate.
   23503          * @param event The event.
   23504          * @return True if the event population was completed.
   23505          *
   23506          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   23507          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   23508          */
   23509         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   23510             return host.dispatchPopulateAccessibilityEventInternal(event);
   23511         }
   23512 
   23513         /**
   23514          * Gives a chance to the host View to populate the accessibility event with its
   23515          * text content.
   23516          * <p>
   23517          * The default implementation behaves as
   23518          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
   23519          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
   23520          * the case of no accessibility delegate been set.
   23521          * </p>
   23522          *
   23523          * @param host The View hosting the delegate.
   23524          * @param event The accessibility event which to populate.
   23525          *
   23526          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
   23527          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
   23528          */
   23529         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   23530             host.onPopulateAccessibilityEventInternal(event);
   23531         }
   23532 
   23533         /**
   23534          * Initializes an {@link AccessibilityEvent} with information about the
   23535          * the host View which is the event source.
   23536          * <p>
   23537          * The default implementation behaves as
   23538          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
   23539          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
   23540          * the case of no accessibility delegate been set.
   23541          * </p>
   23542          *
   23543          * @param host The View hosting the delegate.
   23544          * @param event The event to initialize.
   23545          *
   23546          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
   23547          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
   23548          */
   23549         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
   23550             host.onInitializeAccessibilityEventInternal(event);
   23551         }
   23552 
   23553         /**
   23554          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
   23555          * <p>
   23556          * The default implementation behaves as
   23557          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   23558          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
   23559          * the case of no accessibility delegate been set.
   23560          * </p>
   23561          *
   23562          * @param host The View hosting the delegate.
   23563          * @param info The instance to initialize.
   23564          *
   23565          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   23566          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   23567          */
   23568         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
   23569             host.onInitializeAccessibilityNodeInfoInternal(info);
   23570         }
   23571 
   23572         /**
   23573          * Called when a child of the host View has requested sending an
   23574          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
   23575          * to augment the event.
   23576          * <p>
   23577          * The default implementation behaves as
   23578          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   23579          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
   23580          * the case of no accessibility delegate been set.
   23581          * </p>
   23582          *
   23583          * @param host The View hosting the delegate.
   23584          * @param child The child which requests sending the event.
   23585          * @param event The event to be sent.
   23586          * @return True if the event should be sent
   23587          *
   23588          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   23589          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   23590          */
   23591         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
   23592                 AccessibilityEvent event) {
   23593             return host.onRequestSendAccessibilityEventInternal(child, event);
   23594         }
   23595 
   23596         /**
   23597          * Gets the provider for managing a virtual view hierarchy rooted at this View
   23598          * and reported to {@link android.accessibilityservice.AccessibilityService}s
   23599          * that explore the window content.
   23600          * <p>
   23601          * The default implementation behaves as
   23602          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
   23603          * the case of no accessibility delegate been set.
   23604          * </p>
   23605          *
   23606          * @return The provider.
   23607          *
   23608          * @see AccessibilityNodeProvider
   23609          */
   23610         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
   23611             return null;
   23612         }
   23613 
   23614         /**
   23615          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
   23616          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   23617          * This method is responsible for obtaining an accessibility node info from a
   23618          * pool of reusable instances and calling
   23619          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
   23620          * view to initialize the former.
   23621          * <p>
   23622          * <strong>Note:</strong> The client is responsible for recycling the obtained
   23623          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
   23624          * creation.
   23625          * </p>
   23626          * <p>
   23627          * The default implementation behaves as
   23628          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
   23629          * the case of no accessibility delegate been set.
   23630          * </p>
   23631          * @return A populated {@link AccessibilityNodeInfo}.
   23632          *
   23633          * @see AccessibilityNodeInfo
   23634          *
   23635          * @hide
   23636          */
   23637         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
   23638             return host.createAccessibilityNodeInfoInternal();
   23639         }
   23640     }
   23641 
   23642     private class MatchIdPredicate implements Predicate<View> {
   23643         public int mId;
   23644 
   23645         @Override
   23646         public boolean apply(View view) {
   23647             return (view.mID == mId);
   23648         }
   23649     }
   23650 
   23651     private class MatchLabelForPredicate implements Predicate<View> {
   23652         private int mLabeledId;
   23653 
   23654         @Override
   23655         public boolean apply(View view) {
   23656             return (view.mLabelForId == mLabeledId);
   23657         }
   23658     }
   23659 
   23660     private class SendViewStateChangedAccessibilityEvent implements Runnable {
   23661         private int mChangeTypes = 0;
   23662         private boolean mPosted;
   23663         private boolean mPostedWithDelay;
   23664         private long mLastEventTimeMillis;
   23665 
   23666         @Override
   23667         public void run() {
   23668             mPosted = false;
   23669             mPostedWithDelay = false;
   23670             mLastEventTimeMillis = SystemClock.uptimeMillis();
   23671             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   23672                 final AccessibilityEvent event = AccessibilityEvent.obtain();
   23673                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
   23674                 event.setContentChangeTypes(mChangeTypes);
   23675                 sendAccessibilityEventUnchecked(event);
   23676             }
   23677             mChangeTypes = 0;
   23678         }
   23679 
   23680         public void runOrPost(int changeType) {
   23681             mChangeTypes |= changeType;
   23682 
   23683             // If this is a live region or the child of a live region, collect
   23684             // all events from this frame and send them on the next frame.
   23685             if (inLiveRegion()) {
   23686                 // If we're already posted with a delay, remove that.
   23687                 if (mPostedWithDelay) {
   23688                     removeCallbacks(this);
   23689                     mPostedWithDelay = false;
   23690                 }
   23691                 // Only post if we're not already posted.
   23692                 if (!mPosted) {
   23693                     post(this);
   23694                     mPosted = true;
   23695                 }
   23696                 return;
   23697             }
   23698 
   23699             if (mPosted) {
   23700                 return;
   23701             }
   23702 
   23703             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
   23704             final long minEventIntevalMillis =
   23705                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
   23706             if (timeSinceLastMillis >= minEventIntevalMillis) {
   23707                 removeCallbacks(this);
   23708                 run();
   23709             } else {
   23710                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
   23711                 mPostedWithDelay = true;
   23712             }
   23713         }
   23714     }
   23715 
   23716     private boolean inLiveRegion() {
   23717         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
   23718             return true;
   23719         }
   23720 
   23721         ViewParent parent = getParent();
   23722         while (parent instanceof View) {
   23723             if (((View) parent).getAccessibilityLiveRegion()
   23724                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
   23725                 return true;
   23726             }
   23727             parent = parent.getParent();
   23728         }
   23729 
   23730         return false;
   23731     }
   23732 
   23733     /**
   23734      * Dump all private flags in readable format, useful for documentation and
   23735      * sanity checking.
   23736      */
   23737     private static void dumpFlags() {
   23738         final HashMap<String, String> found = Maps.newHashMap();
   23739         try {
   23740             for (Field field : View.class.getDeclaredFields()) {
   23741                 final int modifiers = field.getModifiers();
   23742                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
   23743                     if (field.getType().equals(int.class)) {
   23744                         final int value = field.getInt(null);
   23745                         dumpFlag(found, field.getName(), value);
   23746                     } else if (field.getType().equals(int[].class)) {
   23747                         final int[] values = (int[]) field.get(null);
   23748                         for (int i = 0; i < values.length; i++) {
   23749                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
   23750                         }
   23751                     }
   23752                 }
   23753             }
   23754         } catch (IllegalAccessException e) {
   23755             throw new RuntimeException(e);
   23756         }
   23757 
   23758         final ArrayList<String> keys = Lists.newArrayList();
   23759         keys.addAll(found.keySet());
   23760         Collections.sort(keys);
   23761         for (String key : keys) {
   23762             Log.d(VIEW_LOG_TAG, found.get(key));
   23763         }
   23764     }
   23765 
   23766     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
   23767         // Sort flags by prefix, then by bits, always keeping unique keys
   23768         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
   23769         final int prefix = name.indexOf('_');
   23770         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
   23771         final String output = bits + " " + name;
   23772         found.put(key, output);
   23773     }
   23774 
   23775     /** {@hide} */
   23776     public void encode(@NonNull ViewHierarchyEncoder stream) {
   23777         stream.beginObject(this);
   23778         encodeProperties(stream);
   23779         stream.endObject();
   23780     }
   23781 
   23782     /** {@hide} */
   23783     @CallSuper
   23784     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
   23785         Object resolveId = ViewDebug.resolveId(getContext(), mID);
   23786         if (resolveId instanceof String) {
   23787             stream.addProperty("id", (String) resolveId);
   23788         } else {
   23789             stream.addProperty("id", mID);
   23790         }
   23791 
   23792         stream.addProperty("misc:transformation.alpha",
   23793                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
   23794         stream.addProperty("misc:transitionName", getTransitionName());
   23795 
   23796         // layout
   23797         stream.addProperty("layout:left", mLeft);
   23798         stream.addProperty("layout:right", mRight);
   23799         stream.addProperty("layout:top", mTop);
   23800         stream.addProperty("layout:bottom", mBottom);
   23801         stream.addProperty("layout:width", getWidth());
   23802         stream.addProperty("layout:height", getHeight());
   23803         stream.addProperty("layout:layoutDirection", getLayoutDirection());
   23804         stream.addProperty("layout:layoutRtl", isLayoutRtl());
   23805         stream.addProperty("layout:hasTransientState", hasTransientState());
   23806         stream.addProperty("layout:baseline", getBaseline());
   23807 
   23808         // layout params
   23809         ViewGroup.LayoutParams layoutParams = getLayoutParams();
   23810         if (layoutParams != null) {
   23811             stream.addPropertyKey("layoutParams");
   23812             layoutParams.encode(stream);
   23813         }
   23814 
   23815         // scrolling
   23816         stream.addProperty("scrolling:scrollX", mScrollX);
   23817         stream.addProperty("scrolling:scrollY", mScrollY);
   23818 
   23819         // padding
   23820         stream.addProperty("padding:paddingLeft", mPaddingLeft);
   23821         stream.addProperty("padding:paddingRight", mPaddingRight);
   23822         stream.addProperty("padding:paddingTop", mPaddingTop);
   23823         stream.addProperty("padding:paddingBottom", mPaddingBottom);
   23824         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
   23825         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
   23826         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
   23827         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
   23828         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
   23829 
   23830         // measurement
   23831         stream.addProperty("measurement:minHeight", mMinHeight);
   23832         stream.addProperty("measurement:minWidth", mMinWidth);
   23833         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
   23834         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
   23835 
   23836         // drawing
   23837         stream.addProperty("drawing:elevation", getElevation());
   23838         stream.addProperty("drawing:translationX", getTranslationX());
   23839         stream.addProperty("drawing:translationY", getTranslationY());
   23840         stream.addProperty("drawing:translationZ", getTranslationZ());
   23841         stream.addProperty("drawing:rotation", getRotation());
   23842         stream.addProperty("drawing:rotationX", getRotationX());
   23843         stream.addProperty("drawing:rotationY", getRotationY());
   23844         stream.addProperty("drawing:scaleX", getScaleX());
   23845         stream.addProperty("drawing:scaleY", getScaleY());
   23846         stream.addProperty("drawing:pivotX", getPivotX());
   23847         stream.addProperty("drawing:pivotY", getPivotY());
   23848         stream.addProperty("drawing:opaque", isOpaque());
   23849         stream.addProperty("drawing:alpha", getAlpha());
   23850         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
   23851         stream.addProperty("drawing:shadow", hasShadow());
   23852         stream.addProperty("drawing:solidColor", getSolidColor());
   23853         stream.addProperty("drawing:layerType", mLayerType);
   23854         stream.addProperty("drawing:willNotDraw", willNotDraw());
   23855         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
   23856         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
   23857         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
   23858         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
   23859 
   23860         // focus
   23861         stream.addProperty("focus:hasFocus", hasFocus());
   23862         stream.addProperty("focus:isFocused", isFocused());
   23863         stream.addProperty("focus:isFocusable", isFocusable());
   23864         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
   23865 
   23866         stream.addProperty("misc:clickable", isClickable());
   23867         stream.addProperty("misc:pressed", isPressed());
   23868         stream.addProperty("misc:selected", isSelected());
   23869         stream.addProperty("misc:touchMode", isInTouchMode());
   23870         stream.addProperty("misc:hovered", isHovered());
   23871         stream.addProperty("misc:activated", isActivated());
   23872 
   23873         stream.addProperty("misc:visibility", getVisibility());
   23874         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
   23875         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
   23876 
   23877         stream.addProperty("misc:enabled", isEnabled());
   23878         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
   23879         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
   23880 
   23881         // theme attributes
   23882         Resources.Theme theme = getContext().getTheme();
   23883         if (theme != null) {
   23884             stream.addPropertyKey("theme");
   23885             theme.encode(stream);
   23886         }
   23887 
   23888         // view attribute information
   23889         int n = mAttributes != null ? mAttributes.length : 0;
   23890         stream.addProperty("meta:__attrCount__", n/2);
   23891         for (int i = 0; i < n; i += 2) {
   23892             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
   23893         }
   23894 
   23895         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
   23896 
   23897         // text
   23898         stream.addProperty("text:textDirection", getTextDirection());
   23899         stream.addProperty("text:textAlignment", getTextAlignment());
   23900 
   23901         // accessibility
   23902         CharSequence contentDescription = getContentDescription();
   23903         stream.addProperty("accessibility:contentDescription",
   23904                 contentDescription == null ? "" : contentDescription.toString());
   23905         stream.addProperty("accessibility:labelFor", getLabelFor());
   23906         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
   23907     }
   23908 
   23909     /**
   23910      * Determine if this view is rendered on a round wearable device and is the main view
   23911      * on the screen.
   23912      */
   23913     private boolean shouldDrawRoundScrollbar() {
   23914         if (!mResources.getConfiguration().isScreenRound()) {
   23915             return false;
   23916         }
   23917 
   23918         final View rootView = getRootView();
   23919         final WindowInsets insets = getRootWindowInsets();
   23920 
   23921         int height = getHeight();
   23922         int width = getWidth();
   23923         int displayHeight = rootView.getHeight();
   23924         int displayWidth = rootView.getWidth();
   23925 
   23926         if (height != displayHeight || width != displayWidth) {
   23927             return false;
   23928         }
   23929 
   23930         getLocationOnScreen(mAttachInfo.mTmpLocation);
   23931         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
   23932                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
   23933     }
   23934 }
   23935