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 static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
     20 
     21 import static java.lang.Math.max;
     22 
     23 import android.animation.AnimatorInflater;
     24 import android.animation.StateListAnimator;
     25 import android.annotation.CallSuper;
     26 import android.annotation.ColorInt;
     27 import android.annotation.DrawableRes;
     28 import android.annotation.FloatRange;
     29 import android.annotation.IdRes;
     30 import android.annotation.IntDef;
     31 import android.annotation.IntRange;
     32 import android.annotation.LayoutRes;
     33 import android.annotation.NonNull;
     34 import android.annotation.Nullable;
     35 import android.annotation.Size;
     36 import android.annotation.TestApi;
     37 import android.annotation.UiThread;
     38 import android.content.ClipData;
     39 import android.content.Context;
     40 import android.content.ContextWrapper;
     41 import android.content.Intent;
     42 import android.content.res.ColorStateList;
     43 import android.content.res.Configuration;
     44 import android.content.res.Resources;
     45 import android.content.res.TypedArray;
     46 import android.graphics.Bitmap;
     47 import android.graphics.Canvas;
     48 import android.graphics.Color;
     49 import android.graphics.Insets;
     50 import android.graphics.Interpolator;
     51 import android.graphics.LinearGradient;
     52 import android.graphics.Matrix;
     53 import android.graphics.Outline;
     54 import android.graphics.Paint;
     55 import android.graphics.PixelFormat;
     56 import android.graphics.Point;
     57 import android.graphics.PorterDuff;
     58 import android.graphics.PorterDuffXfermode;
     59 import android.graphics.Rect;
     60 import android.graphics.RectF;
     61 import android.graphics.Region;
     62 import android.graphics.Shader;
     63 import android.graphics.drawable.ColorDrawable;
     64 import android.graphics.drawable.Drawable;
     65 import android.hardware.display.DisplayManagerGlobal;
     66 import android.net.Uri;
     67 import android.os.Build;
     68 import android.os.Bundle;
     69 import android.os.Handler;
     70 import android.os.IBinder;
     71 import android.os.Message;
     72 import android.os.Parcel;
     73 import android.os.Parcelable;
     74 import android.os.RemoteException;
     75 import android.os.SystemClock;
     76 import android.os.SystemProperties;
     77 import android.os.Trace;
     78 import android.text.InputType;
     79 import android.text.TextUtils;
     80 import android.util.AttributeSet;
     81 import android.util.FloatProperty;
     82 import android.util.LayoutDirection;
     83 import android.util.Log;
     84 import android.util.LongSparseLongArray;
     85 import android.util.Pools.SynchronizedPool;
     86 import android.util.Property;
     87 import android.util.SparseArray;
     88 import android.util.StateSet;
     89 import android.util.SuperNotCalledException;
     90 import android.util.TypedValue;
     91 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
     92 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
     93 import android.view.AccessibilityIterators.TextSegmentIterator;
     94 import android.view.AccessibilityIterators.WordTextSegmentIterator;
     95 import android.view.ContextMenu.ContextMenuInfo;
     96 import android.view.accessibility.AccessibilityEvent;
     97 import android.view.accessibility.AccessibilityEventSource;
     98 import android.view.accessibility.AccessibilityManager;
     99 import android.view.accessibility.AccessibilityNodeInfo;
    100 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
    101 import android.view.accessibility.AccessibilityNodeProvider;
    102 import android.view.accessibility.AccessibilityWindowInfo;
    103 import android.view.animation.Animation;
    104 import android.view.animation.AnimationUtils;
    105 import android.view.animation.Transformation;
    106 import android.view.autofill.AutofillId;
    107 import android.view.autofill.AutofillManager;
    108 import android.view.autofill.AutofillValue;
    109 import android.view.inputmethod.EditorInfo;
    110 import android.view.inputmethod.InputConnection;
    111 import android.view.inputmethod.InputMethodManager;
    112 import android.widget.Checkable;
    113 import android.widget.FrameLayout;
    114 import android.widget.ScrollBarDrawable;
    115 
    116 import com.android.internal.R;
    117 import com.android.internal.view.TooltipPopup;
    118 import com.android.internal.view.menu.MenuBuilder;
    119 import com.android.internal.widget.ScrollBarUtils;
    120 
    121 import com.google.android.collect.Lists;
    122 import com.google.android.collect.Maps;
    123 
    124 import java.lang.annotation.Retention;
    125 import java.lang.annotation.RetentionPolicy;
    126 import java.lang.ref.WeakReference;
    127 import java.lang.reflect.Field;
    128 import java.lang.reflect.InvocationTargetException;
    129 import java.lang.reflect.Method;
    130 import java.lang.reflect.Modifier;
    131 import java.util.ArrayList;
    132 import java.util.Arrays;
    133 import java.util.Calendar;
    134 import java.util.Collection;
    135 import java.util.Collections;
    136 import java.util.HashMap;
    137 import java.util.List;
    138 import java.util.Locale;
    139 import java.util.Map;
    140 import java.util.concurrent.CopyOnWriteArrayList;
    141 import java.util.concurrent.atomic.AtomicInteger;
    142 import java.util.function.Predicate;
    143 
    144 /**
    145  * <p>
    146  * This class represents the basic building block for user interface components. A View
    147  * occupies a rectangular area on the screen and is responsible for drawing and
    148  * event handling. View is the base class for <em>widgets</em>, which are
    149  * used to create interactive UI components (buttons, text fields, etc.). The
    150  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
    151  * are invisible containers that hold other Views (or other ViewGroups) and define
    152  * their layout properties.
    153  * </p>
    154  *
    155  * <div class="special reference">
    156  * <h3>Developer Guides</h3>
    157  * <p>For information about using this class to develop your application's user interface,
    158  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
    159  * </div>
    160  *
    161  * <a name="Using"></a>
    162  * <h3>Using Views</h3>
    163  * <p>
    164  * All of the views in a window are arranged in a single tree. You can add views
    165  * either from code or by specifying a tree of views in one or more XML layout
    166  * files. There are many specialized subclasses of views that act as controls or
    167  * are capable of displaying text, images, or other content.
    168  * </p>
    169  * <p>
    170  * Once you have created a tree of views, there are typically a few types of
    171  * common operations you may wish to perform:
    172  * <ul>
    173  * <li><strong>Set properties:</strong> for example setting the text of a
    174  * {@link android.widget.TextView}. The available properties and the methods
    175  * that set them will vary among the different subclasses of views. Note that
    176  * properties that are known at build time can be set in the XML layout
    177  * files.</li>
    178  * <li><strong>Set focus:</strong> The framework will handle moving focus in
    179  * response to user input. To force focus to a specific view, call
    180  * {@link #requestFocus}.</li>
    181  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
    182  * that will be notified when something interesting happens to the view. For
    183  * example, all views will let you set a listener to be notified when the view
    184  * gains or loses focus. You can register such a listener using
    185  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
    186  * Other view subclasses offer more specialized listeners. For example, a Button
    187  * exposes a listener to notify clients when the button is clicked.</li>
    188  * <li><strong>Set visibility:</strong> You can hide or show views using
    189  * {@link #setVisibility(int)}.</li>
    190  * </ul>
    191  * </p>
    192  * <p><em>
    193  * Note: The Android framework is responsible for measuring, laying out and
    194  * drawing views. You should not call methods that perform these actions on
    195  * views yourself unless you are actually implementing a
    196  * {@link android.view.ViewGroup}.
    197  * </em></p>
    198  *
    199  * <a name="Lifecycle"></a>
    200  * <h3>Implementing a Custom View</h3>
    201  *
    202  * <p>
    203  * To implement a custom view, you will usually begin by providing overrides for
    204  * some of the standard methods that the framework calls on all views. You do
    205  * not need to override all of these methods. In fact, you can start by just
    206  * overriding {@link #onDraw(android.graphics.Canvas)}.
    207  * <table border="2" width="85%" align="center" cellpadding="5">
    208  *     <thead>
    209  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
    210  *     </thead>
    211  *
    212  *     <tbody>
    213  *     <tr>
    214  *         <td rowspan="2">Creation</td>
    215  *         <td>Constructors</td>
    216  *         <td>There is a form of the constructor that are called when the view
    217  *         is created from code and a form that is called when the view is
    218  *         inflated from a layout file. The second form should parse and apply
    219  *         any attributes defined in the layout file.
    220  *         </td>
    221  *     </tr>
    222  *     <tr>
    223  *         <td><code>{@link #onFinishInflate()}</code></td>
    224  *         <td>Called after a view and all of its children has been inflated
    225  *         from XML.</td>
    226  *     </tr>
    227  *
    228  *     <tr>
    229  *         <td rowspan="3">Layout</td>
    230  *         <td><code>{@link #onMeasure(int, int)}</code></td>
    231  *         <td>Called to determine the size requirements for this view and all
    232  *         of its children.
    233  *         </td>
    234  *     </tr>
    235  *     <tr>
    236  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
    237  *         <td>Called when this view should assign a size and position to all
    238  *         of its children.
    239  *         </td>
    240  *     </tr>
    241  *     <tr>
    242  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
    243  *         <td>Called when the size of this view has changed.
    244  *         </td>
    245  *     </tr>
    246  *
    247  *     <tr>
    248  *         <td>Drawing</td>
    249  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
    250  *         <td>Called when the view should render its content.
    251  *         </td>
    252  *     </tr>
    253  *
    254  *     <tr>
    255  *         <td rowspan="4">Event processing</td>
    256  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
    257  *         <td>Called when a new hardware key event occurs.
    258  *         </td>
    259  *     </tr>
    260  *     <tr>
    261  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
    262  *         <td>Called when a hardware key up event occurs.
    263  *         </td>
    264  *     </tr>
    265  *     <tr>
    266  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
    267  *         <td>Called when a trackball motion event occurs.
    268  *         </td>
    269  *     </tr>
    270  *     <tr>
    271  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
    272  *         <td>Called when a touch screen motion event occurs.
    273  *         </td>
    274  *     </tr>
    275  *
    276  *     <tr>
    277  *         <td rowspan="2">Focus</td>
    278  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
    279  *         <td>Called when the view gains or loses focus.
    280  *         </td>
    281  *     </tr>
    282  *
    283  *     <tr>
    284  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
    285  *         <td>Called when the window containing the view gains or loses focus.
    286  *         </td>
    287  *     </tr>
    288  *
    289  *     <tr>
    290  *         <td rowspan="3">Attaching</td>
    291  *         <td><code>{@link #onAttachedToWindow()}</code></td>
    292  *         <td>Called when the view is attached to a window.
    293  *         </td>
    294  *     </tr>
    295  *
    296  *     <tr>
    297  *         <td><code>{@link #onDetachedFromWindow}</code></td>
    298  *         <td>Called when the view is detached from its window.
    299  *         </td>
    300  *     </tr>
    301  *
    302  *     <tr>
    303  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
    304  *         <td>Called when the visibility of the window containing the view
    305  *         has changed.
    306  *         </td>
    307  *     </tr>
    308  *     </tbody>
    309  *
    310  * </table>
    311  * </p>
    312  *
    313  * <a name="IDs"></a>
    314  * <h3>IDs</h3>
    315  * Views may have an integer id associated with them. These ids are typically
    316  * assigned in the layout XML files, and are used to find specific views within
    317  * the view tree. A common pattern is to:
    318  * <ul>
    319  * <li>Define a Button in the layout file and assign it a unique ID.
    320  * <pre>
    321  * &lt;Button
    322  *     android:id="@+id/my_button"
    323  *     android:layout_width="wrap_content"
    324  *     android:layout_height="wrap_content"
    325  *     android:text="@string/my_button_text"/&gt;
    326  * </pre></li>
    327  * <li>From the onCreate method of an Activity, find the Button
    328  * <pre class="prettyprint">
    329  *      Button myButton = findViewById(R.id.my_button);
    330  * </pre></li>
    331  * </ul>
    332  * <p>
    333  * View IDs need not be unique throughout the tree, but it is good practice to
    334  * ensure that they are at least unique within the part of the tree you are
    335  * searching.
    336  * </p>
    337  *
    338  * <a name="Position"></a>
    339  * <h3>Position</h3>
    340  * <p>
    341  * The geometry of a view is that of a rectangle. A view has a location,
    342  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
    343  * two dimensions, expressed as a width and a height. The unit for location
    344  * and dimensions is the pixel.
    345  * </p>
    346  *
    347  * <p>
    348  * It is possible to retrieve the location of a view by invoking the methods
    349  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
    350  * coordinate of the rectangle representing the view. The latter returns the
    351  * top, or Y, coordinate of the rectangle representing the view. These methods
    352  * both return the location of the view relative to its parent. For instance,
    353  * when getLeft() returns 20, that means the view is located 20 pixels to the
    354  * right of the left edge of its direct parent.
    355  * </p>
    356  *
    357  * <p>
    358  * In addition, several convenience methods are offered to avoid unnecessary
    359  * computations, namely {@link #getRight()} and {@link #getBottom()}.
    360  * These methods return the coordinates of the right and bottom edges of the
    361  * rectangle representing the view. For instance, calling {@link #getRight()}
    362  * is similar to the following computation: <code>getLeft() + getWidth()</code>
    363  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
    364  * </p>
    365  *
    366  * <a name="SizePaddingMargins"></a>
    367  * <h3>Size, padding and margins</h3>
    368  * <p>
    369  * The size of a view is expressed with a width and a height. A view actually
    370  * possess two pairs of width and height values.
    371  * </p>
    372  *
    373  * <p>
    374  * The first pair is known as <em>measured width</em> and
    375  * <em>measured height</em>. These dimensions define how big a view wants to be
    376  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
    377  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
    378  * and {@link #getMeasuredHeight()}.
    379  * </p>
    380  *
    381  * <p>
    382  * The second pair is simply known as <em>width</em> and <em>height</em>, or
    383  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
    384  * dimensions define the actual size of the view on screen, at drawing time and
    385  * after layout. These values may, but do not have to, be different from the
    386  * measured width and height. The width and height can be obtained by calling
    387  * {@link #getWidth()} and {@link #getHeight()}.
    388  * </p>
    389  *
    390  * <p>
    391  * To measure its dimensions, a view takes into account its padding. The padding
    392  * is expressed in pixels for the left, top, right and bottom parts of the view.
    393  * Padding can be used to offset the content of the view by a specific amount of
    394  * pixels. For instance, a left padding of 2 will push the view's content by
    395  * 2 pixels to the right of the left edge. Padding can be set using the
    396  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
    397  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
    398  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
    399  * {@link #getPaddingEnd()}.
    400  * </p>
    401  *
    402  * <p>
    403  * Even though a view can define a padding, it does not provide any support for
    404  * margins. However, view groups provide such a support. Refer to
    405  * {@link android.view.ViewGroup} and
    406  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
    407  * </p>
    408  *
    409  * <a name="Layout"></a>
    410  * <h3>Layout</h3>
    411  * <p>
    412  * Layout is a two pass process: a measure pass and a layout pass. The measuring
    413  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
    414  * of the view tree. Each view pushes dimension specifications down the tree
    415  * during the recursion. At the end of the measure pass, every view has stored
    416  * its measurements. The second pass happens in
    417  * {@link #layout(int,int,int,int)} and is also top-down. During
    418  * this pass each parent is responsible for positioning all of its children
    419  * using the sizes computed in the measure pass.
    420  * </p>
    421  *
    422  * <p>
    423  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
    424  * {@link #getMeasuredHeight()} values must be set, along with those for all of
    425  * that view's descendants. A view's measured width and measured height values
    426  * must respect the constraints imposed by the view's parents. This guarantees
    427  * that at the end of the measure pass, all parents accept all of their
    428  * children's measurements. A parent view may call measure() more than once on
    429  * its children. For example, the parent may measure each child once with
    430  * unspecified dimensions to find out how big they want to be, then call
    431  * measure() on them again with actual numbers if the sum of all the children's
    432  * unconstrained sizes is too big or too small.
    433  * </p>
    434  *
    435  * <p>
    436  * The measure pass uses two classes to communicate dimensions. The
    437  * {@link MeasureSpec} class is used by views to tell their parents how they
    438  * want to be measured and positioned. The base LayoutParams class just
    439  * describes how big the view wants to be for both width and height. For each
    440  * dimension, it can specify one of:
    441  * <ul>
    442  * <li> an exact number
    443  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
    444  * (minus padding)
    445  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
    446  * enclose its content (plus padding).
    447  * </ul>
    448  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
    449  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
    450  * an X and Y value.
    451  * </p>
    452  *
    453  * <p>
    454  * MeasureSpecs are used to push requirements down the tree from parent to
    455  * child. A MeasureSpec can be in one of three modes:
    456  * <ul>
    457  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
    458  * of a child view. For example, a LinearLayout may call measure() on its child
    459  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
    460  * tall the child view wants to be given a width of 240 pixels.
    461  * <li>EXACTLY: This is used by the parent to impose an exact size on the
    462  * child. The child must use this size, and guarantee that all of its
    463  * descendants will fit within this size.
    464  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
    465  * child. The child must guarantee that it and all of its descendants will fit
    466  * within this size.
    467  * </ul>
    468  * </p>
    469  *
    470  * <p>
    471  * To initiate a layout, call {@link #requestLayout}. This method is typically
    472  * called by a view on itself when it believes that is can no longer fit within
    473  * its current bounds.
    474  * </p>
    475  *
    476  * <a name="Drawing"></a>
    477  * <h3>Drawing</h3>
    478  * <p>
    479  * Drawing is handled by walking the tree and recording the drawing commands of
    480  * any View that needs to update. After this, the drawing commands of the
    481  * entire tree are issued to screen, clipped to the newly damaged area.
    482  * </p>
    483  *
    484  * <p>
    485  * The tree is largely recorded and drawn in order, with parents drawn before
    486  * (i.e., behind) their children, with siblings drawn in the order they appear
    487  * in the tree. If you set a background drawable for a View, then the View will
    488  * draw it before calling back to its <code>onDraw()</code> method. The child
    489  * drawing order can be overridden with
    490  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
    491  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
    492  * </p>
    493  *
    494  * <p>
    495  * To force a view to draw, call {@link #invalidate()}.
    496  * </p>
    497  *
    498  * <a name="EventHandlingThreading"></a>
    499  * <h3>Event Handling and Threading</h3>
    500  * <p>
    501  * The basic cycle of a view is as follows:
    502  * <ol>
    503  * <li>An event comes in and is dispatched to the appropriate view. The view
    504  * handles the event and notifies any listeners.</li>
    505  * <li>If in the course of processing the event, the view's bounds may need
    506  * to be changed, the view will call {@link #requestLayout()}.</li>
    507  * <li>Similarly, if in the course of processing the event the view's appearance
    508  * may need to be changed, the view will call {@link #invalidate()}.</li>
    509  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
    510  * the framework will take care of measuring, laying out, and drawing the tree
    511  * as appropriate.</li>
    512  * </ol>
    513  * </p>
    514  *
    515  * <p><em>Note: The entire view tree is single threaded. You must always be on
    516  * the UI thread when calling any method on any view.</em>
    517  * If you are doing work on other threads and want to update the state of a view
    518  * from that thread, you should use a {@link Handler}.
    519  * </p>
    520  *
    521  * <a name="FocusHandling"></a>
    522  * <h3>Focus Handling</h3>
    523  * <p>
    524  * The framework will handle routine focus movement in response to user input.
    525  * This includes changing the focus as views are removed or hidden, or as new
    526  * views become available. Views indicate their willingness to take focus
    527  * through the {@link #isFocusable} method. To change whether a view can take
    528  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
    529  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
    530  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
    531  * </p>
    532  * <p>
    533  * Focus movement is based on an algorithm which finds the nearest neighbor in a
    534  * given direction. In rare cases, the default algorithm may not match the
    535  * intended behavior of the developer. In these situations, you can provide
    536  * explicit overrides by using these XML attributes in the layout file:
    537  * <pre>
    538  * nextFocusDown
    539  * nextFocusLeft
    540  * nextFocusRight
    541  * nextFocusUp
    542  * </pre>
    543  * </p>
    544  *
    545  *
    546  * <p>
    547  * To get a particular view to take focus, call {@link #requestFocus()}.
    548  * </p>
    549  *
    550  * <a name="TouchMode"></a>
    551  * <h3>Touch Mode</h3>
    552  * <p>
    553  * When a user is navigating a user interface via directional keys such as a D-pad, it is
    554  * necessary to give focus to actionable items such as buttons so the user can see
    555  * what will take input.  If the device has touch capabilities, however, and the user
    556  * begins interacting with the interface by touching it, it is no longer necessary to
    557  * always highlight, or give focus to, a particular view.  This motivates a mode
    558  * for interaction named 'touch mode'.
    559  * </p>
    560  * <p>
    561  * For a touch capable device, once the user touches the screen, the device
    562  * will enter touch mode.  From this point onward, only views for which
    563  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
    564  * Other views that are touchable, like buttons, will not take focus when touched; they will
    565  * only fire the on click listeners.
    566  * </p>
    567  * <p>
    568  * Any time a user hits a directional key, such as a D-pad direction, the view device will
    569  * exit touch mode, and find a view to take focus, so that the user may resume interacting
    570  * with the user interface without touching the screen again.
    571  * </p>
    572  * <p>
    573  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
    574  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
    575  * </p>
    576  *
    577  * <a name="Scrolling"></a>
    578  * <h3>Scrolling</h3>
    579  * <p>
    580  * The framework provides basic support for views that wish to internally
    581  * scroll their content. This includes keeping track of the X and Y scroll
    582  * offset as well as mechanisms for drawing scrollbars. See
    583  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
    584  * {@link #awakenScrollBars()} for more details.
    585  * </p>
    586  *
    587  * <a name="Tags"></a>
    588  * <h3>Tags</h3>
    589  * <p>
    590  * Unlike IDs, tags are not used to identify views. Tags are essentially an
    591  * extra piece of information that can be associated with a view. They are most
    592  * often used as a convenience to store data related to views in the views
    593  * themselves rather than by putting them in a separate structure.
    594  * </p>
    595  * <p>
    596  * Tags may be specified with character sequence values in layout XML as either
    597  * a single tag using the {@link android.R.styleable#View_tag android:tag}
    598  * attribute or multiple tags using the {@code <tag>} child element:
    599  * <pre>
    600  *     &lt;View ...
    601  *           android:tag="@string/mytag_value" /&gt;
    602  *     &lt;View ...&gt;
    603  *         &lt;tag android:id="@+id/mytag"
    604  *              android:value="@string/mytag_value" /&gt;
    605  *     &lt;/View>
    606  * </pre>
    607  * </p>
    608  * <p>
    609  * Tags may also be specified with arbitrary objects from code using
    610  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
    611  * </p>
    612  *
    613  * <a name="Themes"></a>
    614  * <h3>Themes</h3>
    615  * <p>
    616  * By default, Views are created using the theme of the Context object supplied
    617  * to their constructor; however, a different theme may be specified by using
    618  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
    619  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
    620  * code.
    621  * </p>
    622  * <p>
    623  * When the {@link android.R.styleable#View_theme android:theme} attribute is
    624  * used in XML, the specified theme is applied on top of the inflation
    625  * context's theme (see {@link LayoutInflater}) and used for the view itself as
    626  * well as any child elements.
    627  * </p>
    628  * <p>
    629  * In the following example, both views will be created using the Material dark
    630  * color scheme; however, because an overlay theme is used which only defines a
    631  * subset of attributes, the value of
    632  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
    633  * the inflation context's theme (e.g. the Activity theme) will be preserved.
    634  * <pre>
    635  *     &lt;LinearLayout
    636  *             ...
    637  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
    638  *         &lt;View ...&gt;
    639  *     &lt;/LinearLayout&gt;
    640  * </pre>
    641  * </p>
    642  *
    643  * <a name="Properties"></a>
    644  * <h3>Properties</h3>
    645  * <p>
    646  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
    647  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
    648  * available both in the {@link Property} form as well as in similarly-named setter/getter
    649  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
    650  * be used to set persistent state associated with these rendering-related properties on the view.
    651  * The properties and methods can also be used in conjunction with
    652  * {@link android.animation.Animator Animator}-based animations, described more in the
    653  * <a href="#Animation">Animation</a> section.
    654  * </p>
    655  *
    656  * <a name="Animation"></a>
    657  * <h3>Animation</h3>
    658  * <p>
    659  * Starting with Android 3.0, the preferred way of animating views is to use the
    660  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
    661  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
    662  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
    663  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
    664  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
    665  * makes animating these View properties particularly easy and efficient.
    666  * </p>
    667  * <p>
    668  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
    669  * You can attach an {@link Animation} object to a view using
    670  * {@link #setAnimation(Animation)} or
    671  * {@link #startAnimation(Animation)}. The animation can alter the scale,
    672  * rotation, translation and alpha of a view over time. If the animation is
    673  * attached to a view that has children, the animation will affect the entire
    674  * subtree rooted by that node. When an animation is started, the framework will
    675  * take care of redrawing the appropriate views until the animation completes.
    676  * </p>
    677  *
    678  * <a name="Security"></a>
    679  * <h3>Security</h3>
    680  * <p>
    681  * Sometimes it is essential that an application be able to verify that an action
    682  * is being performed with the full knowledge and consent of the user, such as
    683  * granting a permission request, making a purchase or clicking on an advertisement.
    684  * Unfortunately, a malicious application could try to spoof the user into
    685  * performing these actions, unaware, by concealing the intended purpose of the view.
    686  * As a remedy, the framework offers a touch filtering mechanism that can be used to
    687  * improve the security of views that provide access to sensitive functionality.
    688  * </p><p>
    689  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
    690  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
    691  * will discard touches that are received whenever the view's window is obscured by
    692  * another visible window.  As a result, the view will not receive touches whenever a
    693  * toast, dialog or other window appears above the view's window.
    694  * </p><p>
    695  * For more fine-grained control over security, consider overriding the
    696  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
    697  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
    698  * </p>
    699  *
    700  * @attr ref android.R.styleable#View_accessibilityHeading
    701  * @attr ref android.R.styleable#View_alpha
    702  * @attr ref android.R.styleable#View_background
    703  * @attr ref android.R.styleable#View_clickable
    704  * @attr ref android.R.styleable#View_contentDescription
    705  * @attr ref android.R.styleable#View_drawingCacheQuality
    706  * @attr ref android.R.styleable#View_duplicateParentState
    707  * @attr ref android.R.styleable#View_id
    708  * @attr ref android.R.styleable#View_requiresFadingEdge
    709  * @attr ref android.R.styleable#View_fadeScrollbars
    710  * @attr ref android.R.styleable#View_fadingEdgeLength
    711  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
    712  * @attr ref android.R.styleable#View_fitsSystemWindows
    713  * @attr ref android.R.styleable#View_isScrollContainer
    714  * @attr ref android.R.styleable#View_focusable
    715  * @attr ref android.R.styleable#View_focusableInTouchMode
    716  * @attr ref android.R.styleable#View_focusedByDefault
    717  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
    718  * @attr ref android.R.styleable#View_keepScreenOn
    719  * @attr ref android.R.styleable#View_keyboardNavigationCluster
    720  * @attr ref android.R.styleable#View_layerType
    721  * @attr ref android.R.styleable#View_layoutDirection
    722  * @attr ref android.R.styleable#View_longClickable
    723  * @attr ref android.R.styleable#View_minHeight
    724  * @attr ref android.R.styleable#View_minWidth
    725  * @attr ref android.R.styleable#View_nextClusterForward
    726  * @attr ref android.R.styleable#View_nextFocusDown
    727  * @attr ref android.R.styleable#View_nextFocusLeft
    728  * @attr ref android.R.styleable#View_nextFocusRight
    729  * @attr ref android.R.styleable#View_nextFocusUp
    730  * @attr ref android.R.styleable#View_onClick
    731  * @attr ref android.R.styleable#View_outlineSpotShadowColor
    732  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
    733  * @attr ref android.R.styleable#View_padding
    734  * @attr ref android.R.styleable#View_paddingHorizontal
    735  * @attr ref android.R.styleable#View_paddingVertical
    736  * @attr ref android.R.styleable#View_paddingBottom
    737  * @attr ref android.R.styleable#View_paddingLeft
    738  * @attr ref android.R.styleable#View_paddingRight
    739  * @attr ref android.R.styleable#View_paddingTop
    740  * @attr ref android.R.styleable#View_paddingStart
    741  * @attr ref android.R.styleable#View_paddingEnd
    742  * @attr ref android.R.styleable#View_saveEnabled
    743  * @attr ref android.R.styleable#View_rotation
    744  * @attr ref android.R.styleable#View_rotationX
    745  * @attr ref android.R.styleable#View_rotationY
    746  * @attr ref android.R.styleable#View_scaleX
    747  * @attr ref android.R.styleable#View_scaleY
    748  * @attr ref android.R.styleable#View_scrollX
    749  * @attr ref android.R.styleable#View_scrollY
    750  * @attr ref android.R.styleable#View_scrollbarSize
    751  * @attr ref android.R.styleable#View_scrollbarStyle
    752  * @attr ref android.R.styleable#View_scrollbars
    753  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
    754  * @attr ref android.R.styleable#View_scrollbarFadeDuration
    755  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
    756  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
    757  * @attr ref android.R.styleable#View_scrollbarThumbVertical
    758  * @attr ref android.R.styleable#View_scrollbarTrackVertical
    759  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
    760  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
    761  * @attr ref android.R.styleable#View_stateListAnimator
    762  * @attr ref android.R.styleable#View_transitionName
    763  * @attr ref android.R.styleable#View_soundEffectsEnabled
    764  * @attr ref android.R.styleable#View_tag
    765  * @attr ref android.R.styleable#View_textAlignment
    766  * @attr ref android.R.styleable#View_textDirection
    767  * @attr ref android.R.styleable#View_transformPivotX
    768  * @attr ref android.R.styleable#View_transformPivotY
    769  * @attr ref android.R.styleable#View_translationX
    770  * @attr ref android.R.styleable#View_translationY
    771  * @attr ref android.R.styleable#View_translationZ
    772  * @attr ref android.R.styleable#View_visibility
    773  * @attr ref android.R.styleable#View_theme
    774  *
    775  * @see android.view.ViewGroup
    776  */
    777 @UiThread
    778 public class View implements Drawable.Callback, KeyEvent.Callback,
    779         AccessibilityEventSource {
    780     private static final boolean DBG = false;
    781 
    782     /** @hide */
    783     public static boolean DEBUG_DRAW = false;
    784 
    785     /**
    786      * The logging tag used by this class with android.util.Log.
    787      */
    788     protected static final String VIEW_LOG_TAG = "View";
    789 
    790     /**
    791      * When set to true, apps will draw debugging information about their layouts.
    792      *
    793      * @hide
    794      */
    795     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
    796 
    797     /**
    798      * When set to true, this view will save its attribute data.
    799      *
    800      * @hide
    801      */
    802     public static boolean mDebugViewAttributes = false;
    803 
    804     /**
    805      * Used to mark a View that has no ID.
    806      */
    807     public static final int NO_ID = -1;
    808 
    809     /**
    810      * Last ID that is given to Views that are no part of activities.
    811      *
    812      * {@hide}
    813      */
    814     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
    815 
    816     /**
    817      * Attribute to find the autofilled highlight
    818      *
    819      * @see #getAutofilledDrawable()
    820      */
    821     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
    822             new int[]{android.R.attr.autofilledHighlight};
    823 
    824     /**
    825      * Signals that compatibility booleans have been initialized according to
    826      * target SDK versions.
    827      */
    828     private static boolean sCompatibilityDone = false;
    829 
    830     /**
    831      * Use the old (broken) way of building MeasureSpecs.
    832      */
    833     private static boolean sUseBrokenMakeMeasureSpec = false;
    834 
    835     /**
    836      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
    837      */
    838     static boolean sUseZeroUnspecifiedMeasureSpec = false;
    839 
    840     /**
    841      * Ignore any optimizations using the measure cache.
    842      */
    843     private static boolean sIgnoreMeasureCache = false;
    844 
    845     /**
    846      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
    847      */
    848     private static boolean sAlwaysRemeasureExactly = false;
    849 
    850     /**
    851      * Relax constraints around whether setLayoutParams() must be called after
    852      * modifying the layout params.
    853      */
    854     private static boolean sLayoutParamsAlwaysChanged = false;
    855 
    856     /**
    857      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
    858      * without throwing
    859      */
    860     static boolean sTextureViewIgnoresDrawableSetters = false;
    861 
    862     /**
    863      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
    864      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
    865      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
    866      * check is implemented for backwards compatibility.
    867      *
    868      * {@hide}
    869      */
    870     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
    871 
    872     /**
    873      * Prior to N, when drag enters into child of a view that has already received an
    874      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
    875      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
    876      * false from its event handler for these events.
    877      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
    878      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
    879      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
    880      */
    881     static boolean sCascadedDragDrop;
    882 
    883     /**
    884      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
    885      * to determine things like whether or not to permit item click events. We can't break
    886      * apps that do this just because more things (clickable things) are now auto-focusable
    887      * and they would get different results, so give old behavior to old apps.
    888      */
    889     static boolean sHasFocusableExcludeAutoFocusable;
    890 
    891     /**
    892      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
    893      * made focusable by default. As a result, apps could (incorrectly) change the clickable
    894      * setting of views off the UI thread. Now that clickable can effect the focusable state,
    895      * changing the clickable attribute off the UI thread will cause an exception (since changing
    896      * the focusable state checks). In order to prevent apps from crashing, we will handle this
    897      * specific case and just not notify parents on new focusables resulting from marking views
    898      * clickable from outside the UI thread.
    899      */
    900     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
    901 
    902     /**
    903      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
    904      * Float.NaN. If the app is targetting P or later then passing these values will result in an
    905      * exception being thrown. If the app is targetting an earlier SDK version, then we will
    906      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
    907      * these bogus values.
    908      */
    909     private static boolean sThrowOnInvalidFloatProperties;
    910 
    911     /**
    912      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
    913      * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface
    914      * instead.
    915      */
    916     private static boolean sAcceptZeroSizeDragShadow;
    917 
    918     /** @hide */
    919     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
    920     @Retention(RetentionPolicy.SOURCE)
    921     public @interface Focusable {}
    922 
    923     /**
    924      * This view does not want keystrokes.
    925      * <p>
    926      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
    927      * android:focusable}.
    928      */
    929     public static final int NOT_FOCUSABLE = 0x00000000;
    930 
    931     /**
    932      * This view wants keystrokes.
    933      * <p>
    934      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
    935      * android:focusable}.
    936      */
    937     public static final int FOCUSABLE = 0x00000001;
    938 
    939     /**
    940      * This view determines focusability automatically. This is the default.
    941      * <p>
    942      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
    943      * android:focusable}.
    944      */
    945     public static final int FOCUSABLE_AUTO = 0x00000010;
    946 
    947     /**
    948      * Mask for use with setFlags indicating bits used for focus.
    949      */
    950     private static final int FOCUSABLE_MASK = 0x00000011;
    951 
    952     /**
    953      * This view will adjust its padding to fit sytem windows (e.g. status bar)
    954      */
    955     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
    956 
    957     /** @hide */
    958     @IntDef({VISIBLE, INVISIBLE, GONE})
    959     @Retention(RetentionPolicy.SOURCE)
    960     public @interface Visibility {}
    961 
    962     /**
    963      * This view is visible.
    964      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    965      * android:visibility}.
    966      */
    967     public static final int VISIBLE = 0x00000000;
    968 
    969     /**
    970      * This view is invisible, but it still takes up space for layout purposes.
    971      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    972      * android:visibility}.
    973      */
    974     public static final int INVISIBLE = 0x00000004;
    975 
    976     /**
    977      * This view is invisible, and it doesn't take any space for layout
    978      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    979      * android:visibility}.
    980      */
    981     public static final int GONE = 0x00000008;
    982 
    983     /**
    984      * Mask for use with setFlags indicating bits used for visibility.
    985      * {@hide}
    986      */
    987     static final int VISIBILITY_MASK = 0x0000000C;
    988 
    989     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
    990 
    991     /**
    992      * Hint indicating that this view can be autofilled with an email address.
    993      *
    994      * <p>Can be used with either {@link #setAutofillHints(String[])} or
    995      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
    996      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
    997      *
    998      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
    999      */
   1000     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
   1001 
   1002     /**
   1003      * Hint indicating that this view can be autofilled with a user's real name.
   1004      *
   1005      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1006      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1007      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
   1008      *
   1009      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1010      */
   1011     public static final String AUTOFILL_HINT_NAME = "name";
   1012 
   1013     /**
   1014      * Hint indicating that this view can be autofilled with a username.
   1015      *
   1016      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1017      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1018      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
   1019      *
   1020      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1021      */
   1022     public static final String AUTOFILL_HINT_USERNAME = "username";
   1023 
   1024     /**
   1025      * Hint indicating that this view can be autofilled with a password.
   1026      *
   1027      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1028      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1029      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
   1030      *
   1031      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1032      */
   1033     public static final String AUTOFILL_HINT_PASSWORD = "password";
   1034 
   1035     /**
   1036      * Hint indicating that this view can be autofilled with a phone number.
   1037      *
   1038      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1039      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1040      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
   1041      *
   1042      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1043      */
   1044     public static final String AUTOFILL_HINT_PHONE = "phone";
   1045 
   1046     /**
   1047      * Hint indicating that this view can be autofilled with a postal address.
   1048      *
   1049      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1050      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1051      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
   1052      *
   1053      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1054      */
   1055     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
   1056 
   1057     /**
   1058      * Hint indicating that this view can be autofilled with a postal code.
   1059      *
   1060      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1061      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1062      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
   1063      *
   1064      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1065      */
   1066     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
   1067 
   1068     /**
   1069      * Hint indicating that this view can be autofilled with a credit card number.
   1070      *
   1071      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1072      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1073      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
   1074      *
   1075      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1076      */
   1077     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
   1078 
   1079     /**
   1080      * Hint indicating that this view can be autofilled with a credit card security code.
   1081      *
   1082      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1083      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1084      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
   1085      *
   1086      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1087      */
   1088     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
   1089 
   1090     /**
   1091      * Hint indicating that this view can be autofilled with a credit card expiration date.
   1092      *
   1093      * <p>It should be used when the credit card expiration date is represented by just one view;
   1094      * if it is represented by more than one (for example, one view for the month and another view
   1095      * for the year), then each of these views should use the hint specific for the unit
   1096      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
   1097      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
   1098      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
   1099      *
   1100      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1101      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1102      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
   1103      *
   1104      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
   1105      * avoid ambiguity when the autofill service provides a value for it. To understand why a
   1106      * value can be ambiguous, consider "April of 2020", which could be represented as either of
   1107      * the following options:
   1108      *
   1109      * <ul>
   1110      *   <li>{@code "04/2020"}
   1111      *   <li>{@code "4/2020"}
   1112      *   <li>{@code "2020/04"}
   1113      *   <li>{@code "2020/4"}
   1114      *   <li>{@code "April/2020"}
   1115      *   <li>{@code "Apr/2020"}
   1116      * </ul>
   1117      *
   1118      * <p>You define a date autofill value for the view by overriding the following methods:
   1119      *
   1120      * <ol>
   1121      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
   1122      *   <li>{@link #getAutofillValue()} to return a
   1123      *       {@link AutofillValue#forDate(long) date autofillvalue}.
   1124      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
   1125      * </ol>
   1126      *
   1127      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1128      */
   1129     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
   1130             "creditCardExpirationDate";
   1131 
   1132     /**
   1133      * Hint indicating that this view can be autofilled with a credit card expiration month.
   1134      *
   1135      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1136      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1137      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
   1138      *
   1139      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
   1140      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
   1141      * ambiguity when the autofill service provides a value for it. To understand why a
   1142      * value can be ambiguous, consider "January", which could be represented as either of
   1143      *
   1144      * <ul>
   1145      *   <li>{@code "1"}: recommended way.
   1146      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
   1147      *   <li>{@code "January"}: full name, in English.
   1148      *   <li>{@code "jan"}: abbreviated name, in English.
   1149      *   <li>{@code "Janeiro"}: full name, in another language.
   1150      * </ul>
   1151      *
   1152      * <p>Another recommended approach is to use a date autofill value - see
   1153      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
   1154      *
   1155      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1156      */
   1157     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
   1158             "creditCardExpirationMonth";
   1159 
   1160     /**
   1161      * Hint indicating that this view can be autofilled with a credit card expiration year.
   1162      *
   1163      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1164      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1165      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
   1166      *
   1167      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1168      */
   1169     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
   1170             "creditCardExpirationYear";
   1171 
   1172     /**
   1173      * Hint indicating that this view can be autofilled with a credit card expiration day.
   1174      *
   1175      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1176      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1177      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
   1178      *
   1179      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1180      */
   1181     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
   1182 
   1183     /**
   1184      * Hints for the autofill services that describes the content of the view.
   1185      */
   1186     private @Nullable String[] mAutofillHints;
   1187 
   1188     /**
   1189      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
   1190      */
   1191     private AutofillId mAutofillId;
   1192 
   1193     /** @hide */
   1194     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
   1195             AUTOFILL_TYPE_NONE,
   1196             AUTOFILL_TYPE_TEXT,
   1197             AUTOFILL_TYPE_TOGGLE,
   1198             AUTOFILL_TYPE_LIST,
   1199             AUTOFILL_TYPE_DATE
   1200     })
   1201     @Retention(RetentionPolicy.SOURCE)
   1202     public @interface AutofillType {}
   1203 
   1204     /**
   1205      * Autofill type for views that cannot be autofilled.
   1206      *
   1207      * <p>Typically used when the view is read-only; for example, a text label.
   1208      *
   1209      * @see #getAutofillType()
   1210      */
   1211     public static final int AUTOFILL_TYPE_NONE = 0;
   1212 
   1213     /**
   1214      * Autofill type for a text field, which is filled by a {@link CharSequence}.
   1215      *
   1216      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
   1217      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
   1218      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
   1219      *
   1220      * @see #getAutofillType()
   1221      */
   1222     public static final int AUTOFILL_TYPE_TEXT = 1;
   1223 
   1224     /**
   1225      * Autofill type for a togglable field, which is filled by a {@code boolean}.
   1226      *
   1227      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
   1228      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
   1229      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
   1230      *
   1231      * @see #getAutofillType()
   1232      */
   1233     public static final int AUTOFILL_TYPE_TOGGLE = 2;
   1234 
   1235     /**
   1236      * Autofill type for a selection list field, which is filled by an {@code int}
   1237      * representing the element index inside the list (starting at {@code 0}).
   1238      *
   1239      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
   1240      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
   1241      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
   1242      *
   1243      * <p>The available options in the selection list are typically provided by
   1244      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
   1245      *
   1246      * @see #getAutofillType()
   1247      */
   1248     public static final int AUTOFILL_TYPE_LIST = 3;
   1249 
   1250 
   1251     /**
   1252      * Autofill type for a field that contains a date, which is represented by a long representing
   1253      * the number of milliseconds since the standard base time known as "the epoch", namely
   1254      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
   1255      *
   1256      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
   1257      * {@link AutofillValue#forDate(long)}, and the values passed to
   1258      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
   1259      *
   1260      * @see #getAutofillType()
   1261      */
   1262     public static final int AUTOFILL_TYPE_DATE = 4;
   1263 
   1264     /** @hide */
   1265     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
   1266             IMPORTANT_FOR_AUTOFILL_AUTO,
   1267             IMPORTANT_FOR_AUTOFILL_YES,
   1268             IMPORTANT_FOR_AUTOFILL_NO,
   1269             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
   1270             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
   1271     })
   1272     @Retention(RetentionPolicy.SOURCE)
   1273     public @interface AutofillImportance {}
   1274 
   1275     /**
   1276      * Automatically determine whether a view is important for autofill.
   1277      *
   1278      * @see #isImportantForAutofill()
   1279      * @see #setImportantForAutofill(int)
   1280      */
   1281     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
   1282 
   1283     /**
   1284      * The view is important for autofill, and its children (if any) will be traversed.
   1285      *
   1286      * @see #isImportantForAutofill()
   1287      * @see #setImportantForAutofill(int)
   1288      */
   1289     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
   1290 
   1291     /**
   1292      * The view is not important for autofill, but its children (if any) will be traversed.
   1293      *
   1294      * @see #isImportantForAutofill()
   1295      * @see #setImportantForAutofill(int)
   1296      */
   1297     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
   1298 
   1299     /**
   1300      * The view is important for autofill, but its children (if any) will not be traversed.
   1301      *
   1302      * @see #isImportantForAutofill()
   1303      * @see #setImportantForAutofill(int)
   1304      */
   1305     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
   1306 
   1307     /**
   1308      * The view is not important for autofill, and its children (if any) will not be traversed.
   1309      *
   1310      * @see #isImportantForAutofill()
   1311      * @see #setImportantForAutofill(int)
   1312      */
   1313     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
   1314 
   1315     /** @hide */
   1316     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
   1317             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   1318     })
   1319     @Retention(RetentionPolicy.SOURCE)
   1320     public @interface AutofillFlags {}
   1321 
   1322     /**
   1323      * Flag requesting you to add views that are marked as not important for autofill
   1324      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
   1325      */
   1326     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
   1327 
   1328     /**
   1329      * This view is enabled. Interpretation varies by subclass.
   1330      * Use with ENABLED_MASK when calling setFlags.
   1331      * {@hide}
   1332      */
   1333     static final int ENABLED = 0x00000000;
   1334 
   1335     /**
   1336      * This view is disabled. Interpretation varies by subclass.
   1337      * Use with ENABLED_MASK when calling setFlags.
   1338      * {@hide}
   1339      */
   1340     static final int DISABLED = 0x00000020;
   1341 
   1342    /**
   1343     * Mask for use with setFlags indicating bits used for indicating whether
   1344     * this view is enabled
   1345     * {@hide}
   1346     */
   1347     static final int ENABLED_MASK = 0x00000020;
   1348 
   1349     /**
   1350      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
   1351      * called and further optimizations will be performed. It is okay to have
   1352      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
   1353      * {@hide}
   1354      */
   1355     static final int WILL_NOT_DRAW = 0x00000080;
   1356 
   1357     /**
   1358      * Mask for use with setFlags indicating bits used for indicating whether
   1359      * this view is will draw
   1360      * {@hide}
   1361      */
   1362     static final int DRAW_MASK = 0x00000080;
   1363 
   1364     /**
   1365      * <p>This view doesn't show scrollbars.</p>
   1366      * {@hide}
   1367      */
   1368     static final int SCROLLBARS_NONE = 0x00000000;
   1369 
   1370     /**
   1371      * <p>This view shows horizontal scrollbars.</p>
   1372      * {@hide}
   1373      */
   1374     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
   1375 
   1376     /**
   1377      * <p>This view shows vertical scrollbars.</p>
   1378      * {@hide}
   1379      */
   1380     static final int SCROLLBARS_VERTICAL = 0x00000200;
   1381 
   1382     /**
   1383      * <p>Mask for use with setFlags indicating bits used for indicating which
   1384      * scrollbars are enabled.</p>
   1385      * {@hide}
   1386      */
   1387     static final int SCROLLBARS_MASK = 0x00000300;
   1388 
   1389     /**
   1390      * Indicates that the view should filter touches when its window is obscured.
   1391      * Refer to the class comments for more information about this security feature.
   1392      * {@hide}
   1393      */
   1394     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
   1395 
   1396     /**
   1397      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
   1398      * that they are optional and should be skipped if the window has
   1399      * requested system UI flags that ignore those insets for layout.
   1400      */
   1401     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
   1402 
   1403     /**
   1404      * <p>This view doesn't show fading edges.</p>
   1405      * {@hide}
   1406      */
   1407     static final int FADING_EDGE_NONE = 0x00000000;
   1408 
   1409     /**
   1410      * <p>This view shows horizontal fading edges.</p>
   1411      * {@hide}
   1412      */
   1413     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
   1414 
   1415     /**
   1416      * <p>This view shows vertical fading edges.</p>
   1417      * {@hide}
   1418      */
   1419     static final int FADING_EDGE_VERTICAL = 0x00002000;
   1420 
   1421     /**
   1422      * <p>Mask for use with setFlags indicating bits used for indicating which
   1423      * fading edges are enabled.</p>
   1424      * {@hide}
   1425      */
   1426     static final int FADING_EDGE_MASK = 0x00003000;
   1427 
   1428     /**
   1429      * <p>Indicates this view can be clicked. When clickable, a View reacts
   1430      * to clicks by notifying the OnClickListener.<p>
   1431      * {@hide}
   1432      */
   1433     static final int CLICKABLE = 0x00004000;
   1434 
   1435     /**
   1436      * <p>Indicates this view is caching its drawing into a bitmap.</p>
   1437      * {@hide}
   1438      */
   1439     static final int DRAWING_CACHE_ENABLED = 0x00008000;
   1440 
   1441     /**
   1442      * <p>Indicates that no icicle should be saved for this view.<p>
   1443      * {@hide}
   1444      */
   1445     static final int SAVE_DISABLED = 0x000010000;
   1446 
   1447     /**
   1448      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
   1449      * property.</p>
   1450      * {@hide}
   1451      */
   1452     static final int SAVE_DISABLED_MASK = 0x000010000;
   1453 
   1454     /**
   1455      * <p>Indicates that no drawing cache should ever be created for this view.<p>
   1456      * {@hide}
   1457      */
   1458     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
   1459 
   1460     /**
   1461      * <p>Indicates this view can take / keep focus when int touch mode.</p>
   1462      * {@hide}
   1463      */
   1464     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
   1465 
   1466     /** @hide */
   1467     @Retention(RetentionPolicy.SOURCE)
   1468     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
   1469             DRAWING_CACHE_QUALITY_LOW,
   1470             DRAWING_CACHE_QUALITY_HIGH,
   1471             DRAWING_CACHE_QUALITY_AUTO
   1472     })
   1473     public @interface DrawingCacheQuality {}
   1474 
   1475     /**
   1476      * <p>Enables low quality mode for the drawing cache.</p>
   1477      *
   1478      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   1479      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   1480      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   1481      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   1482      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   1483      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   1484      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   1485      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   1486      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   1487      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   1488      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   1489      * reports or unit testing the {@link PixelCopy} API is recommended.
   1490      */
   1491     @Deprecated
   1492     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
   1493 
   1494     /**
   1495      * <p>Enables high quality mode for the drawing cache.</p>
   1496      *
   1497      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   1498      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   1499      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   1500      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   1501      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   1502      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   1503      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   1504      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   1505      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   1506      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   1507      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   1508      * reports or unit testing the {@link PixelCopy} API is recommended.
   1509      */
   1510     @Deprecated
   1511     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
   1512 
   1513     /**
   1514      * <p>Enables automatic quality mode for the drawing cache.</p>
   1515      *
   1516      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   1517      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   1518      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   1519      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   1520      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   1521      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   1522      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   1523      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   1524      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   1525      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   1526      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   1527      * reports or unit testing the {@link PixelCopy} API is recommended.
   1528      */
   1529     @Deprecated
   1530     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
   1531 
   1532     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
   1533             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
   1534     };
   1535 
   1536     /**
   1537      * <p>Mask for use with setFlags indicating bits used for the cache
   1538      * quality property.</p>
   1539      * {@hide}
   1540      */
   1541     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
   1542 
   1543     /**
   1544      * <p>
   1545      * Indicates this view can be long clicked. When long clickable, a View
   1546      * reacts to long clicks by notifying the OnLongClickListener or showing a
   1547      * context menu.
   1548      * </p>
   1549      * {@hide}
   1550      */
   1551     static final int LONG_CLICKABLE = 0x00200000;
   1552 
   1553     /**
   1554      * <p>Indicates that this view gets its drawable states from its direct parent
   1555      * and ignores its original internal states.</p>
   1556      *
   1557      * @hide
   1558      */
   1559     static final int DUPLICATE_PARENT_STATE = 0x00400000;
   1560 
   1561     /**
   1562      * <p>
   1563      * Indicates this view can be context clicked. When context clickable, a View reacts to a
   1564      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
   1565      * OnContextClickListener.
   1566      * </p>
   1567      * {@hide}
   1568      */
   1569     static final int CONTEXT_CLICKABLE = 0x00800000;
   1570 
   1571     /** @hide */
   1572     @IntDef(prefix = { "SCROLLBARS_" }, value = {
   1573             SCROLLBARS_INSIDE_OVERLAY,
   1574             SCROLLBARS_INSIDE_INSET,
   1575             SCROLLBARS_OUTSIDE_OVERLAY,
   1576             SCROLLBARS_OUTSIDE_INSET
   1577     })
   1578     @Retention(RetentionPolicy.SOURCE)
   1579     public @interface ScrollBarStyle {}
   1580 
   1581     /**
   1582      * The scrollbar style to display the scrollbars inside the content area,
   1583      * without increasing the padding. The scrollbars will be overlaid with
   1584      * translucency on the view's content.
   1585      */
   1586     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
   1587 
   1588     /**
   1589      * The scrollbar style to display the scrollbars inside the padded area,
   1590      * increasing the padding of the view. The scrollbars will not overlap the
   1591      * content area of the view.
   1592      */
   1593     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
   1594 
   1595     /**
   1596      * The scrollbar style to display the scrollbars at the edge of the view,
   1597      * without increasing the padding. The scrollbars will be overlaid with
   1598      * translucency.
   1599      */
   1600     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
   1601 
   1602     /**
   1603      * The scrollbar style to display the scrollbars at the edge of the view,
   1604      * increasing the padding of the view. The scrollbars will only overlap the
   1605      * background, if any.
   1606      */
   1607     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
   1608 
   1609     /**
   1610      * Mask to check if the scrollbar style is overlay or inset.
   1611      * {@hide}
   1612      */
   1613     static final int SCROLLBARS_INSET_MASK = 0x01000000;
   1614 
   1615     /**
   1616      * Mask to check if the scrollbar style is inside or outside.
   1617      * {@hide}
   1618      */
   1619     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
   1620 
   1621     /**
   1622      * Mask for scrollbar style.
   1623      * {@hide}
   1624      */
   1625     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
   1626 
   1627     /**
   1628      * View flag indicating that the screen should remain on while the
   1629      * window containing this view is visible to the user.  This effectively
   1630      * takes care of automatically setting the WindowManager's
   1631      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
   1632      */
   1633     public static final int KEEP_SCREEN_ON = 0x04000000;
   1634 
   1635     /**
   1636      * View flag indicating whether this view should have sound effects enabled
   1637      * for events such as clicking and touching.
   1638      */
   1639     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
   1640 
   1641     /**
   1642      * View flag indicating whether this view should have haptic feedback
   1643      * enabled for events such as long presses.
   1644      */
   1645     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
   1646 
   1647     /**
   1648      * <p>Indicates that the view hierarchy should stop saving state when
   1649      * it reaches this view.  If state saving is initiated immediately at
   1650      * the view, it will be allowed.
   1651      * {@hide}
   1652      */
   1653     static final int PARENT_SAVE_DISABLED = 0x20000000;
   1654 
   1655     /**
   1656      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
   1657      * {@hide}
   1658      */
   1659     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
   1660 
   1661     private static Paint sDebugPaint;
   1662 
   1663     /**
   1664      * <p>Indicates this view can display a tooltip on hover or long press.</p>
   1665      * {@hide}
   1666      */
   1667     static final int TOOLTIP = 0x40000000;
   1668 
   1669     /** @hide */
   1670     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
   1671             FOCUSABLES_ALL,
   1672             FOCUSABLES_TOUCH_MODE
   1673     })
   1674     @Retention(RetentionPolicy.SOURCE)
   1675     public @interface FocusableMode {}
   1676 
   1677     /**
   1678      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1679      * should add all focusable Views regardless if they are focusable in touch mode.
   1680      */
   1681     public static final int FOCUSABLES_ALL = 0x00000000;
   1682 
   1683     /**
   1684      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1685      * should add only Views focusable in touch mode.
   1686      */
   1687     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
   1688 
   1689     /** @hide */
   1690     @IntDef(prefix = { "FOCUS_" }, value = {
   1691             FOCUS_BACKWARD,
   1692             FOCUS_FORWARD,
   1693             FOCUS_LEFT,
   1694             FOCUS_UP,
   1695             FOCUS_RIGHT,
   1696             FOCUS_DOWN
   1697     })
   1698     @Retention(RetentionPolicy.SOURCE)
   1699     public @interface FocusDirection {}
   1700 
   1701     /** @hide */
   1702     @IntDef(prefix = { "FOCUS_" }, value = {
   1703             FOCUS_LEFT,
   1704             FOCUS_UP,
   1705             FOCUS_RIGHT,
   1706             FOCUS_DOWN
   1707     })
   1708     @Retention(RetentionPolicy.SOURCE)
   1709     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
   1710 
   1711     /**
   1712      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
   1713      * item.
   1714      */
   1715     public static final int FOCUS_BACKWARD = 0x00000001;
   1716 
   1717     /**
   1718      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
   1719      * item.
   1720      */
   1721     public static final int FOCUS_FORWARD = 0x00000002;
   1722 
   1723     /**
   1724      * Use with {@link #focusSearch(int)}. Move focus to the left.
   1725      */
   1726     public static final int FOCUS_LEFT = 0x00000011;
   1727 
   1728     /**
   1729      * Use with {@link #focusSearch(int)}. Move focus up.
   1730      */
   1731     public static final int FOCUS_UP = 0x00000021;
   1732 
   1733     /**
   1734      * Use with {@link #focusSearch(int)}. Move focus to the right.
   1735      */
   1736     public static final int FOCUS_RIGHT = 0x00000042;
   1737 
   1738     /**
   1739      * Use with {@link #focusSearch(int)}. Move focus down.
   1740      */
   1741     public static final int FOCUS_DOWN = 0x00000082;
   1742 
   1743     /**
   1744      * Bits of {@link #getMeasuredWidthAndState()} and
   1745      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
   1746      */
   1747     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
   1748 
   1749     /**
   1750      * Bits of {@link #getMeasuredWidthAndState()} and
   1751      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
   1752      */
   1753     public static final int MEASURED_STATE_MASK = 0xff000000;
   1754 
   1755     /**
   1756      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
   1757      * for functions that combine both width and height into a single int,
   1758      * such as {@link #getMeasuredState()} and the childState argument of
   1759      * {@link #resolveSizeAndState(int, int, int)}.
   1760      */
   1761     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
   1762 
   1763     /**
   1764      * Bit of {@link #getMeasuredWidthAndState()} and
   1765      * {@link #getMeasuredWidthAndState()} that indicates the measured size
   1766      * is smaller that the space the view would like to have.
   1767      */
   1768     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
   1769 
   1770     /**
   1771      * Base View state sets
   1772      */
   1773     // Singles
   1774     /**
   1775      * Indicates the view has no states set. States are used with
   1776      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1777      * view depending on its state.
   1778      *
   1779      * @see android.graphics.drawable.Drawable
   1780      * @see #getDrawableState()
   1781      */
   1782     protected static final int[] EMPTY_STATE_SET;
   1783     /**
   1784      * Indicates the view is enabled. States are used with
   1785      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1786      * view depending on its state.
   1787      *
   1788      * @see android.graphics.drawable.Drawable
   1789      * @see #getDrawableState()
   1790      */
   1791     protected static final int[] ENABLED_STATE_SET;
   1792     /**
   1793      * Indicates the view is focused. States are used with
   1794      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1795      * view depending on its state.
   1796      *
   1797      * @see android.graphics.drawable.Drawable
   1798      * @see #getDrawableState()
   1799      */
   1800     protected static final int[] FOCUSED_STATE_SET;
   1801     /**
   1802      * Indicates the view is selected. States are used with
   1803      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1804      * view depending on its state.
   1805      *
   1806      * @see android.graphics.drawable.Drawable
   1807      * @see #getDrawableState()
   1808      */
   1809     protected static final int[] SELECTED_STATE_SET;
   1810     /**
   1811      * Indicates the view is pressed. States are used with
   1812      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1813      * view depending on its state.
   1814      *
   1815      * @see android.graphics.drawable.Drawable
   1816      * @see #getDrawableState()
   1817      */
   1818     protected static final int[] PRESSED_STATE_SET;
   1819     /**
   1820      * Indicates the view's window has focus. States are used with
   1821      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1822      * view depending on its state.
   1823      *
   1824      * @see android.graphics.drawable.Drawable
   1825      * @see #getDrawableState()
   1826      */
   1827     protected static final int[] WINDOW_FOCUSED_STATE_SET;
   1828     // Doubles
   1829     /**
   1830      * Indicates the view is enabled and has the focus.
   1831      *
   1832      * @see #ENABLED_STATE_SET
   1833      * @see #FOCUSED_STATE_SET
   1834      */
   1835     protected static final int[] ENABLED_FOCUSED_STATE_SET;
   1836     /**
   1837      * Indicates the view is enabled and selected.
   1838      *
   1839      * @see #ENABLED_STATE_SET
   1840      * @see #SELECTED_STATE_SET
   1841      */
   1842     protected static final int[] ENABLED_SELECTED_STATE_SET;
   1843     /**
   1844      * Indicates the view is enabled and that its window has focus.
   1845      *
   1846      * @see #ENABLED_STATE_SET
   1847      * @see #WINDOW_FOCUSED_STATE_SET
   1848      */
   1849     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
   1850     /**
   1851      * Indicates the view is focused and selected.
   1852      *
   1853      * @see #FOCUSED_STATE_SET
   1854      * @see #SELECTED_STATE_SET
   1855      */
   1856     protected static final int[] FOCUSED_SELECTED_STATE_SET;
   1857     /**
   1858      * Indicates the view has the focus and that its window has the focus.
   1859      *
   1860      * @see #FOCUSED_STATE_SET
   1861      * @see #WINDOW_FOCUSED_STATE_SET
   1862      */
   1863     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1864     /**
   1865      * Indicates the view is selected and that its window has the focus.
   1866      *
   1867      * @see #SELECTED_STATE_SET
   1868      * @see #WINDOW_FOCUSED_STATE_SET
   1869      */
   1870     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
   1871     // Triples
   1872     /**
   1873      * Indicates the view is enabled, focused and selected.
   1874      *
   1875      * @see #ENABLED_STATE_SET
   1876      * @see #FOCUSED_STATE_SET
   1877      * @see #SELECTED_STATE_SET
   1878      */
   1879     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
   1880     /**
   1881      * Indicates the view is enabled, focused and its window has the focus.
   1882      *
   1883      * @see #ENABLED_STATE_SET
   1884      * @see #FOCUSED_STATE_SET
   1885      * @see #WINDOW_FOCUSED_STATE_SET
   1886      */
   1887     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1888     /**
   1889      * Indicates the view is enabled, selected and its window has the focus.
   1890      *
   1891      * @see #ENABLED_STATE_SET
   1892      * @see #SELECTED_STATE_SET
   1893      * @see #WINDOW_FOCUSED_STATE_SET
   1894      */
   1895     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1896     /**
   1897      * Indicates the view is focused, selected and its window has the focus.
   1898      *
   1899      * @see #FOCUSED_STATE_SET
   1900      * @see #SELECTED_STATE_SET
   1901      * @see #WINDOW_FOCUSED_STATE_SET
   1902      */
   1903     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1904     /**
   1905      * Indicates the view is enabled, focused, selected and its window
   1906      * has the focus.
   1907      *
   1908      * @see #ENABLED_STATE_SET
   1909      * @see #FOCUSED_STATE_SET
   1910      * @see #SELECTED_STATE_SET
   1911      * @see #WINDOW_FOCUSED_STATE_SET
   1912      */
   1913     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1914     /**
   1915      * Indicates the view is pressed and its window has the focus.
   1916      *
   1917      * @see #PRESSED_STATE_SET
   1918      * @see #WINDOW_FOCUSED_STATE_SET
   1919      */
   1920     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
   1921     /**
   1922      * Indicates the view is pressed and selected.
   1923      *
   1924      * @see #PRESSED_STATE_SET
   1925      * @see #SELECTED_STATE_SET
   1926      */
   1927     protected static final int[] PRESSED_SELECTED_STATE_SET;
   1928     /**
   1929      * Indicates the view is pressed, selected and its window has the focus.
   1930      *
   1931      * @see #PRESSED_STATE_SET
   1932      * @see #SELECTED_STATE_SET
   1933      * @see #WINDOW_FOCUSED_STATE_SET
   1934      */
   1935     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1936     /**
   1937      * Indicates the view is pressed and focused.
   1938      *
   1939      * @see #PRESSED_STATE_SET
   1940      * @see #FOCUSED_STATE_SET
   1941      */
   1942     protected static final int[] PRESSED_FOCUSED_STATE_SET;
   1943     /**
   1944      * Indicates the view is pressed, focused and its window has the focus.
   1945      *
   1946      * @see #PRESSED_STATE_SET
   1947      * @see #FOCUSED_STATE_SET
   1948      * @see #WINDOW_FOCUSED_STATE_SET
   1949      */
   1950     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1951     /**
   1952      * Indicates the view is pressed, focused and selected.
   1953      *
   1954      * @see #PRESSED_STATE_SET
   1955      * @see #SELECTED_STATE_SET
   1956      * @see #FOCUSED_STATE_SET
   1957      */
   1958     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
   1959     /**
   1960      * Indicates the view is pressed, focused, selected and its window has the focus.
   1961      *
   1962      * @see #PRESSED_STATE_SET
   1963      * @see #FOCUSED_STATE_SET
   1964      * @see #SELECTED_STATE_SET
   1965      * @see #WINDOW_FOCUSED_STATE_SET
   1966      */
   1967     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1968     /**
   1969      * Indicates the view is pressed and enabled.
   1970      *
   1971      * @see #PRESSED_STATE_SET
   1972      * @see #ENABLED_STATE_SET
   1973      */
   1974     protected static final int[] PRESSED_ENABLED_STATE_SET;
   1975     /**
   1976      * Indicates the view is pressed, enabled and its window has the focus.
   1977      *
   1978      * @see #PRESSED_STATE_SET
   1979      * @see #ENABLED_STATE_SET
   1980      * @see #WINDOW_FOCUSED_STATE_SET
   1981      */
   1982     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
   1983     /**
   1984      * Indicates the view is pressed, enabled and selected.
   1985      *
   1986      * @see #PRESSED_STATE_SET
   1987      * @see #ENABLED_STATE_SET
   1988      * @see #SELECTED_STATE_SET
   1989      */
   1990     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
   1991     /**
   1992      * Indicates the view is pressed, enabled, selected and its window has the
   1993      * focus.
   1994      *
   1995      * @see #PRESSED_STATE_SET
   1996      * @see #ENABLED_STATE_SET
   1997      * @see #SELECTED_STATE_SET
   1998      * @see #WINDOW_FOCUSED_STATE_SET
   1999      */
   2000     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   2001     /**
   2002      * Indicates the view is pressed, enabled and focused.
   2003      *
   2004      * @see #PRESSED_STATE_SET
   2005      * @see #ENABLED_STATE_SET
   2006      * @see #FOCUSED_STATE_SET
   2007      */
   2008     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
   2009     /**
   2010      * Indicates the view is pressed, enabled, focused and its window has the
   2011      * focus.
   2012      *
   2013      * @see #PRESSED_STATE_SET
   2014      * @see #ENABLED_STATE_SET
   2015      * @see #FOCUSED_STATE_SET
   2016      * @see #WINDOW_FOCUSED_STATE_SET
   2017      */
   2018     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   2019     /**
   2020      * Indicates the view is pressed, enabled, focused and selected.
   2021      *
   2022      * @see #PRESSED_STATE_SET
   2023      * @see #ENABLED_STATE_SET
   2024      * @see #SELECTED_STATE_SET
   2025      * @see #FOCUSED_STATE_SET
   2026      */
   2027     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
   2028     /**
   2029      * Indicates the view is pressed, enabled, focused, selected and its window
   2030      * has the focus.
   2031      *
   2032      * @see #PRESSED_STATE_SET
   2033      * @see #ENABLED_STATE_SET
   2034      * @see #SELECTED_STATE_SET
   2035      * @see #FOCUSED_STATE_SET
   2036      * @see #WINDOW_FOCUSED_STATE_SET
   2037      */
   2038     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   2039 
   2040     static {
   2041         EMPTY_STATE_SET = StateSet.get(0);
   2042 
   2043         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
   2044 
   2045         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
   2046         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2047                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
   2048 
   2049         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
   2050         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2051                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
   2052         FOCUSED_SELECTED_STATE_SET = StateSet.get(
   2053                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
   2054         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2055                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2056                         | StateSet.VIEW_STATE_FOCUSED);
   2057 
   2058         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
   2059         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2060                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   2061         ENABLED_SELECTED_STATE_SET = StateSet.get(
   2062                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
   2063         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2064                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2065                         | StateSet.VIEW_STATE_ENABLED);
   2066         ENABLED_FOCUSED_STATE_SET = StateSet.get(
   2067                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   2068         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2069                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   2070                         | StateSet.VIEW_STATE_ENABLED);
   2071         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   2072                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   2073                         | StateSet.VIEW_STATE_ENABLED);
   2074         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2075                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2076                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
   2077 
   2078         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
   2079         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2080                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   2081         PRESSED_SELECTED_STATE_SET = StateSet.get(
   2082                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
   2083         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2084                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2085                         | StateSet.VIEW_STATE_PRESSED);
   2086         PRESSED_FOCUSED_STATE_SET = StateSet.get(
   2087                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   2088         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2089                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   2090                         | StateSet.VIEW_STATE_PRESSED);
   2091         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   2092                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   2093                         | StateSet.VIEW_STATE_PRESSED);
   2094         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2095                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2096                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   2097         PRESSED_ENABLED_STATE_SET = StateSet.get(
   2098                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   2099         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2100                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
   2101                         | StateSet.VIEW_STATE_PRESSED);
   2102         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
   2103                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
   2104                         | StateSet.VIEW_STATE_PRESSED);
   2105         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2106                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2107                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   2108         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
   2109                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
   2110                         | StateSet.VIEW_STATE_PRESSED);
   2111         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2112                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   2113                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   2114         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   2115                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   2116                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   2117         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2118                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2119                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
   2120                         | StateSet.VIEW_STATE_PRESSED);
   2121     }
   2122 
   2123     /**
   2124      * Accessibility event types that are dispatched for text population.
   2125      */
   2126     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
   2127             AccessibilityEvent.TYPE_VIEW_CLICKED
   2128             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   2129             | AccessibilityEvent.TYPE_VIEW_SELECTED
   2130             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   2131             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   2132             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   2133             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   2134             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   2135             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
   2136             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
   2137             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
   2138 
   2139     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
   2140 
   2141     static final int DEBUG_CORNERS_SIZE_DIP = 8;
   2142 
   2143     /**
   2144      * Temporary Rect currently for use in setBackground().  This will probably
   2145      * be extended in the future to hold our own class with more than just
   2146      * a Rect. :)
   2147      */
   2148     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
   2149 
   2150     /**
   2151      * Map used to store views' tags.
   2152      */
   2153     private SparseArray<Object> mKeyedTags;
   2154 
   2155     /**
   2156      * The next available accessibility id.
   2157      */
   2158     private static int sNextAccessibilityViewId;
   2159 
   2160     /**
   2161      * The animation currently associated with this view.
   2162      * @hide
   2163      */
   2164     protected Animation mCurrentAnimation = null;
   2165 
   2166     /**
   2167      * Width as measured during measure pass.
   2168      * {@hide}
   2169      */
   2170     @ViewDebug.ExportedProperty(category = "measurement")
   2171     int mMeasuredWidth;
   2172 
   2173     /**
   2174      * Height as measured during measure pass.
   2175      * {@hide}
   2176      */
   2177     @ViewDebug.ExportedProperty(category = "measurement")
   2178     int mMeasuredHeight;
   2179 
   2180     /**
   2181      * Flag to indicate that this view was marked INVALIDATED, or had its display list
   2182      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
   2183      * its display list. This flag, used only when hw accelerated, allows us to clear the
   2184      * flag while retaining this information until it's needed (at getDisplayList() time and
   2185      * in drawChild(), when we decide to draw a view's children's display lists into our own).
   2186      *
   2187      * {@hide}
   2188      */
   2189     boolean mRecreateDisplayList = false;
   2190 
   2191     /**
   2192      * The view's identifier.
   2193      * {@hide}
   2194      *
   2195      * @see #setId(int)
   2196      * @see #getId()
   2197      */
   2198     @IdRes
   2199     @ViewDebug.ExportedProperty(resolveId = true)
   2200     int mID = NO_ID;
   2201 
   2202     /** The ID of this view for autofill purposes.
   2203      * <ul>
   2204      *     <li>== {@link #NO_ID}: ID has not been assigned yet
   2205      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
   2206      *                                                  unique in the process. This might change
   2207      *                                                  over activity lifecycle events.
   2208      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
   2209      *                                                  unique in the activity. This stays the same
   2210      *                                                  over activity lifecycle events.
   2211      */
   2212     private int mAutofillViewId = NO_ID;
   2213 
   2214     // ID for accessibility purposes. This ID must be unique for every window
   2215     private int mAccessibilityViewId = NO_ID;
   2216 
   2217     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   2218 
   2219     /**
   2220      * The view's tag.
   2221      * {@hide}
   2222      *
   2223      * @see #setTag(Object)
   2224      * @see #getTag()
   2225      */
   2226     protected Object mTag = null;
   2227 
   2228     // for mPrivateFlags:
   2229     /** {@hide} */
   2230     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
   2231     /** {@hide} */
   2232     static final int PFLAG_FOCUSED                     = 0x00000002;
   2233     /** {@hide} */
   2234     static final int PFLAG_SELECTED                    = 0x00000004;
   2235     /** {@hide} */
   2236     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
   2237     /** {@hide} */
   2238     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
   2239     /** {@hide} */
   2240     static final int PFLAG_DRAWN                       = 0x00000020;
   2241     /**
   2242      * When this flag is set, this view is running an animation on behalf of its
   2243      * children and should therefore not cancel invalidate requests, even if they
   2244      * lie outside of this view's bounds.
   2245      *
   2246      * {@hide}
   2247      */
   2248     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
   2249     /** {@hide} */
   2250     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
   2251     /** {@hide} */
   2252     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
   2253     /** {@hide} */
   2254     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
   2255     /** {@hide} */
   2256     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
   2257     /** {@hide} */
   2258     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
   2259     /** {@hide} */
   2260     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
   2261 
   2262     private static final int PFLAG_PRESSED             = 0x00004000;
   2263 
   2264     /** {@hide} */
   2265     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
   2266     /**
   2267      * Flag used to indicate that this view should be drawn once more (and only once
   2268      * more) after its animation has completed.
   2269      * {@hide}
   2270      */
   2271     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
   2272 
   2273     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
   2274 
   2275     /**
   2276      * Indicates that the View returned true when onSetAlpha() was called and that
   2277      * the alpha must be restored.
   2278      * {@hide}
   2279      */
   2280     static final int PFLAG_ALPHA_SET                   = 0x00040000;
   2281 
   2282     /**
   2283      * Set by {@link #setScrollContainer(boolean)}.
   2284      */
   2285     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
   2286 
   2287     /**
   2288      * Set by {@link #setScrollContainer(boolean)}.
   2289      */
   2290     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
   2291 
   2292     /**
   2293      * View flag indicating whether this view was invalidated (fully or partially.)
   2294      *
   2295      * @hide
   2296      */
   2297     static final int PFLAG_DIRTY                       = 0x00200000;
   2298 
   2299     /**
   2300      * View flag indicating whether this view was invalidated by an opaque
   2301      * invalidate request.
   2302      *
   2303      * @hide
   2304      */
   2305     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
   2306 
   2307     /**
   2308      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
   2309      *
   2310      * @hide
   2311      */
   2312     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
   2313 
   2314     /**
   2315      * Indicates whether the background is opaque.
   2316      *
   2317      * @hide
   2318      */
   2319     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
   2320 
   2321     /**
   2322      * Indicates whether the scrollbars are opaque.
   2323      *
   2324      * @hide
   2325      */
   2326     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
   2327 
   2328     /**
   2329      * Indicates whether the view is opaque.
   2330      *
   2331      * @hide
   2332      */
   2333     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
   2334 
   2335     /**
   2336      * Indicates a prepressed state;
   2337      * the short time between ACTION_DOWN and recognizing
   2338      * a 'real' press. Prepressed is used to recognize quick taps
   2339      * even when they are shorter than ViewConfiguration.getTapTimeout().
   2340      *
   2341      * @hide
   2342      */
   2343     private static final int PFLAG_PREPRESSED          = 0x02000000;
   2344 
   2345     /**
   2346      * Indicates whether the view is temporarily detached.
   2347      *
   2348      * @hide
   2349      */
   2350     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
   2351 
   2352     /**
   2353      * Indicates that we should awaken scroll bars once attached
   2354      *
   2355      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
   2356      * during window attachment and it is no longer needed. Feel free to repurpose it.
   2357      *
   2358      * @hide
   2359      */
   2360     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
   2361 
   2362     /**
   2363      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
   2364      * @hide
   2365      */
   2366     private static final int PFLAG_HOVERED             = 0x10000000;
   2367 
   2368     /**
   2369      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
   2370      */
   2371     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
   2372 
   2373     /** {@hide} */
   2374     static final int PFLAG_ACTIVATED                   = 0x40000000;
   2375 
   2376     /**
   2377      * Indicates that this view was specifically invalidated, not just dirtied because some
   2378      * child view was invalidated. The flag is used to determine when we need to recreate
   2379      * a view's display list (as opposed to just returning a reference to its existing
   2380      * display list).
   2381      *
   2382      * @hide
   2383      */
   2384     static final int PFLAG_INVALIDATED                 = 0x80000000;
   2385 
   2386     /**
   2387      * Masks for mPrivateFlags2, as generated by dumpFlags():
   2388      *
   2389      * |-------|-------|-------|-------|
   2390      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
   2391      *                                1  PFLAG2_DRAG_HOVERED
   2392      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
   2393      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
   2394      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
   2395      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
   2396      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
   2397      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
   2398      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
   2399      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
   2400      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
   2401      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
   2402      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
   2403      *                         111       PFLAG2_TEXT_DIRECTION_MASK
   2404      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
   2405      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
   2406      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
   2407      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
   2408      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
   2409      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
   2410      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
   2411      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
   2412      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
   2413      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
   2414      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
   2415      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
   2416      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
   2417      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
   2418      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
   2419      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
   2420      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
   2421      *     1                             PFLAG2_VIEW_QUICK_REJECTED
   2422      *    1                              PFLAG2_PADDING_RESOLVED
   2423      *   1                               PFLAG2_DRAWABLE_RESOLVED
   2424      *  1                                PFLAG2_HAS_TRANSIENT_STATE
   2425      * |-------|-------|-------|-------|
   2426      */
   2427 
   2428     /**
   2429      * Indicates that this view has reported that it can accept the current drag's content.
   2430      * Cleared when the drag operation concludes.
   2431      * @hide
   2432      */
   2433     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
   2434 
   2435     /**
   2436      * Indicates that this view is currently directly under the drag location in a
   2437      * drag-and-drop operation involving content that it can accept.  Cleared when
   2438      * the drag exits the view, or when the drag operation concludes.
   2439      * @hide
   2440      */
   2441     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
   2442 
   2443     /** @hide */
   2444     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
   2445             LAYOUT_DIRECTION_LTR,
   2446             LAYOUT_DIRECTION_RTL,
   2447             LAYOUT_DIRECTION_INHERIT,
   2448             LAYOUT_DIRECTION_LOCALE
   2449     })
   2450     @Retention(RetentionPolicy.SOURCE)
   2451     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
   2452     public @interface LayoutDir {}
   2453 
   2454     /** @hide */
   2455     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
   2456             LAYOUT_DIRECTION_LTR,
   2457             LAYOUT_DIRECTION_RTL
   2458     })
   2459     @Retention(RetentionPolicy.SOURCE)
   2460     public @interface ResolvedLayoutDir {}
   2461 
   2462     /**
   2463      * A flag to indicate that the layout direction of this view has not been defined yet.
   2464      * @hide
   2465      */
   2466     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
   2467 
   2468     /**
   2469      * Horizontal layout direction of this view is from Left to Right.
   2470      * Use with {@link #setLayoutDirection}.
   2471      */
   2472     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
   2473 
   2474     /**
   2475      * Horizontal layout direction of this view is from Right to Left.
   2476      * Use with {@link #setLayoutDirection}.
   2477      */
   2478     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
   2479 
   2480     /**
   2481      * Horizontal layout direction of this view is inherited from its parent.
   2482      * Use with {@link #setLayoutDirection}.
   2483      */
   2484     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
   2485 
   2486     /**
   2487      * Horizontal layout direction of this view is from deduced from the default language
   2488      * script for the locale. Use with {@link #setLayoutDirection}.
   2489      */
   2490     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
   2491 
   2492     /**
   2493      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2494      * @hide
   2495      */
   2496     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
   2497 
   2498     /**
   2499      * Mask for use with private flags indicating bits used for horizontal layout direction.
   2500      * @hide
   2501      */
   2502     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2503 
   2504     /**
   2505      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
   2506      * right-to-left direction.
   2507      * @hide
   2508      */
   2509     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2510 
   2511     /**
   2512      * Indicates whether the view horizontal layout direction has been resolved.
   2513      * @hide
   2514      */
   2515     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2516 
   2517     /**
   2518      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
   2519      * @hide
   2520      */
   2521     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
   2522             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2523 
   2524     /*
   2525      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
   2526      * flag value.
   2527      * @hide
   2528      */
   2529     private static final int[] LAYOUT_DIRECTION_FLAGS = {
   2530             LAYOUT_DIRECTION_LTR,
   2531             LAYOUT_DIRECTION_RTL,
   2532             LAYOUT_DIRECTION_INHERIT,
   2533             LAYOUT_DIRECTION_LOCALE
   2534     };
   2535 
   2536     /**
   2537      * Default horizontal layout direction.
   2538      */
   2539     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
   2540 
   2541     /**
   2542      * Default horizontal layout direction.
   2543      * @hide
   2544      */
   2545     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
   2546 
   2547     /**
   2548      * Text direction is inherited through {@link ViewGroup}
   2549      */
   2550     public static final int TEXT_DIRECTION_INHERIT = 0;
   2551 
   2552     /**
   2553      * Text direction is using "first strong algorithm". The first strong directional character
   2554      * determines the paragraph direction. If there is no strong directional character, the
   2555      * paragraph direction is the view's resolved layout direction.
   2556      */
   2557     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
   2558 
   2559     /**
   2560      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
   2561      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
   2562      * If there are neither, the paragraph direction is the view's resolved layout direction.
   2563      */
   2564     public static final int TEXT_DIRECTION_ANY_RTL = 2;
   2565 
   2566     /**
   2567      * Text direction is forced to LTR.
   2568      */
   2569     public static final int TEXT_DIRECTION_LTR = 3;
   2570 
   2571     /**
   2572      * Text direction is forced to RTL.
   2573      */
   2574     public static final int TEXT_DIRECTION_RTL = 4;
   2575 
   2576     /**
   2577      * Text direction is coming from the system Locale.
   2578      */
   2579     public static final int TEXT_DIRECTION_LOCALE = 5;
   2580 
   2581     /**
   2582      * Text direction is using "first strong algorithm". The first strong directional character
   2583      * determines the paragraph direction. If there is no strong directional character, the
   2584      * paragraph direction is LTR.
   2585      */
   2586     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
   2587 
   2588     /**
   2589      * Text direction is using "first strong algorithm". The first strong directional character
   2590      * determines the paragraph direction. If there is no strong directional character, the
   2591      * paragraph direction is RTL.
   2592      */
   2593     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
   2594 
   2595     /**
   2596      * Default text direction is inherited
   2597      */
   2598     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
   2599 
   2600     /**
   2601      * Default resolved text direction
   2602      * @hide
   2603      */
   2604     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
   2605 
   2606     /**
   2607      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
   2608      * @hide
   2609      */
   2610     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
   2611 
   2612     /**
   2613      * Mask for use with private flags indicating bits used for text direction.
   2614      * @hide
   2615      */
   2616     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
   2617             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2618 
   2619     /**
   2620      * Array of text direction flags for mapping attribute "textDirection" to correct
   2621      * flag value.
   2622      * @hide
   2623      */
   2624     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
   2625             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2626             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2627             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2628             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2629             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2630             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2631             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2632             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
   2633     };
   2634 
   2635     /**
   2636      * Indicates whether the view text direction has been resolved.
   2637      * @hide
   2638      */
   2639     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
   2640             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2641 
   2642     /**
   2643      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2644      * @hide
   2645      */
   2646     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
   2647 
   2648     /**
   2649      * Mask for use with private flags indicating bits used for resolved text direction.
   2650      * @hide
   2651      */
   2652     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
   2653             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2654 
   2655     /**
   2656      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
   2657      * @hide
   2658      */
   2659     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
   2660             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2661 
   2662     /** @hide */
   2663     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
   2664             TEXT_ALIGNMENT_INHERIT,
   2665             TEXT_ALIGNMENT_GRAVITY,
   2666             TEXT_ALIGNMENT_CENTER,
   2667             TEXT_ALIGNMENT_TEXT_START,
   2668             TEXT_ALIGNMENT_TEXT_END,
   2669             TEXT_ALIGNMENT_VIEW_START,
   2670             TEXT_ALIGNMENT_VIEW_END
   2671     })
   2672     @Retention(RetentionPolicy.SOURCE)
   2673     public @interface TextAlignment {}
   2674 
   2675     /**
   2676      * Default text alignment. The text alignment of this View is inherited from its parent.
   2677      * Use with {@link #setTextAlignment(int)}
   2678      */
   2679     public static final int TEXT_ALIGNMENT_INHERIT = 0;
   2680 
   2681     /**
   2682      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
   2683      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraphs text direction.
   2684      *
   2685      * Use with {@link #setTextAlignment(int)}
   2686      */
   2687     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
   2688 
   2689     /**
   2690      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
   2691      *
   2692      * Use with {@link #setTextAlignment(int)}
   2693      */
   2694     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
   2695 
   2696     /**
   2697      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
   2698      *
   2699      * Use with {@link #setTextAlignment(int)}
   2700      */
   2701     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
   2702 
   2703     /**
   2704      * Center the paragraph, e.g. ALIGN_CENTER.
   2705      *
   2706      * Use with {@link #setTextAlignment(int)}
   2707      */
   2708     public static final int TEXT_ALIGNMENT_CENTER = 4;
   2709 
   2710     /**
   2711      * Align to the start of the view, which is ALIGN_LEFT if the views resolved
   2712      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
   2713      *
   2714      * Use with {@link #setTextAlignment(int)}
   2715      */
   2716     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
   2717 
   2718     /**
   2719      * Align to the end of the view, which is ALIGN_RIGHT if the views resolved
   2720      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
   2721      *
   2722      * Use with {@link #setTextAlignment(int)}
   2723      */
   2724     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
   2725 
   2726     /**
   2727      * Default text alignment is inherited
   2728      */
   2729     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2730 
   2731     /**
   2732      * Default resolved text alignment
   2733      * @hide
   2734      */
   2735     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2736 
   2737     /**
   2738       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2739       * @hide
   2740       */
   2741     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
   2742 
   2743     /**
   2744       * Mask for use with private flags indicating bits used for text alignment.
   2745       * @hide
   2746       */
   2747     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2748 
   2749     /**
   2750      * Array of text direction flags for mapping attribute "textAlignment" to correct
   2751      * flag value.
   2752      * @hide
   2753      */
   2754     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
   2755             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2756             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2757             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2758             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2759             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2760             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2761             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
   2762     };
   2763 
   2764     /**
   2765      * Indicates whether the view text alignment has been resolved.
   2766      * @hide
   2767      */
   2768     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2769 
   2770     /**
   2771      * Bit shift to get the resolved text alignment.
   2772      * @hide
   2773      */
   2774     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
   2775 
   2776     /**
   2777      * Mask for use with private flags indicating bits used for text alignment.
   2778      * @hide
   2779      */
   2780     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
   2781             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2782 
   2783     /**
   2784      * Indicates whether if the view text alignment has been resolved to gravity
   2785      */
   2786     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
   2787             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2788 
   2789     // Accessiblity constants for mPrivateFlags2
   2790 
   2791     /**
   2792      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2793      * "importantForAccessibility" attribute.
   2794      */
   2795     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
   2796 
   2797     /**
   2798      * Automatically determine whether a view is important for accessibility.
   2799      */
   2800     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
   2801 
   2802     /**
   2803      * The view is important for accessibility.
   2804      */
   2805     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
   2806 
   2807     /**
   2808      * The view is not important for accessibility.
   2809      */
   2810     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
   2811 
   2812     /**
   2813      * The view is not important for accessibility, nor are any of its
   2814      * descendant views.
   2815      */
   2816     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
   2817 
   2818     /**
   2819      * The default whether the view is important for accessibility.
   2820      */
   2821     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   2822 
   2823     /**
   2824      * Mask for obtaining the bits which specify how to determine
   2825      * whether a view is important for accessibility.
   2826      */
   2827     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
   2828         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
   2829         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
   2830         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   2831 
   2832     /**
   2833      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2834      * "accessibilityLiveRegion" attribute.
   2835      */
   2836     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
   2837 
   2838     /**
   2839      * Live region mode specifying that accessibility services should not
   2840      * automatically announce changes to this view. This is the default live
   2841      * region mode for most views.
   2842      * <p>
   2843      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2844      */
   2845     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
   2846 
   2847     /**
   2848      * Live region mode specifying that accessibility services should announce
   2849      * changes to this view.
   2850      * <p>
   2851      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2852      */
   2853     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
   2854 
   2855     /**
   2856      * Live region mode specifying that accessibility services should interrupt
   2857      * ongoing speech to immediately announce changes to this view.
   2858      * <p>
   2859      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2860      */
   2861     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
   2862 
   2863     /**
   2864      * The default whether the view is important for accessibility.
   2865      */
   2866     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
   2867 
   2868     /**
   2869      * Mask for obtaining the bits which specify a view's accessibility live
   2870      * region mode.
   2871      */
   2872     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
   2873             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
   2874             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   2875 
   2876     /**
   2877      * Flag indicating whether a view has accessibility focus.
   2878      */
   2879     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
   2880 
   2881     /**
   2882      * Flag whether the accessibility state of the subtree rooted at this view changed.
   2883      */
   2884     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
   2885 
   2886     /**
   2887      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
   2888      * is used to check whether later changes to the view's transform should invalidate the
   2889      * view to force the quickReject test to run again.
   2890      */
   2891     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
   2892 
   2893     /**
   2894      * Flag indicating that start/end padding has been resolved into left/right padding
   2895      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
   2896      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
   2897      * during measurement. In some special cases this is required such as when an adapter-based
   2898      * view measures prospective children without attaching them to a window.
   2899      */
   2900     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
   2901 
   2902     /**
   2903      * Flag indicating that the start/end drawables has been resolved into left/right ones.
   2904      */
   2905     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
   2906 
   2907     /**
   2908      * Indicates that the view is tracking some sort of transient state
   2909      * that the app should not need to be aware of, but that the framework
   2910      * should take special care to preserve.
   2911      */
   2912     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
   2913 
   2914     /**
   2915      * Group of bits indicating that RTL properties resolution is done.
   2916      */
   2917     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
   2918             PFLAG2_TEXT_DIRECTION_RESOLVED |
   2919             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   2920             PFLAG2_PADDING_RESOLVED |
   2921             PFLAG2_DRAWABLE_RESOLVED;
   2922 
   2923     // There are a couple of flags left in mPrivateFlags2
   2924 
   2925     /* End of masks for mPrivateFlags2 */
   2926 
   2927     /**
   2928      * Masks for mPrivateFlags3, as generated by dumpFlags():
   2929      *
   2930      * |-------|-------|-------|-------|
   2931      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
   2932      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
   2933      *                               1   PFLAG3_IS_LAID_OUT
   2934      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
   2935      *                             1     PFLAG3_CALLED_SUPER
   2936      *                            1      PFLAG3_APPLYING_INSETS
   2937      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
   2938      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
   2939      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
   2940      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
   2941      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
   2942      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
   2943      *                     1             PFLAG3_SCROLL_INDICATOR_START
   2944      *                    1              PFLAG3_SCROLL_INDICATOR_END
   2945      *                   1               PFLAG3_ASSIST_BLOCKED
   2946      *                  1                PFLAG3_CLUSTER
   2947      *                 1                 PFLAG3_IS_AUTOFILLED
   2948      *                1                  PFLAG3_FINGER_DOWN
   2949      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
   2950      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
   2951      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
   2952      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
   2953      *        1                          PFLAG3_TEMPORARY_DETACH
   2954      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
   2955      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
   2956      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
   2957      *    1                              PFLAG3_AGGREGATED_VISIBLE
   2958      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
   2959      *  1                                PFLAG3_ACCESSIBILITY_HEADING
   2960      * |-------|-------|-------|-------|
   2961      */
   2962 
   2963     /**
   2964      * Flag indicating that view has a transform animation set on it. This is used to track whether
   2965      * an animation is cleared between successive frames, in order to tell the associated
   2966      * DisplayList to clear its animation matrix.
   2967      */
   2968     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
   2969 
   2970     /**
   2971      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
   2972      * animation is cleared between successive frames, in order to tell the associated
   2973      * DisplayList to restore its alpha value.
   2974      */
   2975     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
   2976 
   2977     /**
   2978      * Flag indicating that the view has been through at least one layout since it
   2979      * was last attached to a window.
   2980      */
   2981     static final int PFLAG3_IS_LAID_OUT = 0x4;
   2982 
   2983     /**
   2984      * Flag indicating that a call to measure() was skipped and should be done
   2985      * instead when layout() is invoked.
   2986      */
   2987     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
   2988 
   2989     /**
   2990      * Flag indicating that an overridden method correctly called down to
   2991      * the superclass implementation as required by the API spec.
   2992      */
   2993     static final int PFLAG3_CALLED_SUPER = 0x10;
   2994 
   2995     /**
   2996      * Flag indicating that we're in the process of applying window insets.
   2997      */
   2998     static final int PFLAG3_APPLYING_INSETS = 0x20;
   2999 
   3000     /**
   3001      * Flag indicating that we're in the process of fitting system windows using the old method.
   3002      */
   3003     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
   3004 
   3005     /**
   3006      * Flag indicating that nested scrolling is enabled for this view.
   3007      * The view will optionally cooperate with views up its parent chain to allow for
   3008      * integrated nested scrolling along the same axis.
   3009      */
   3010     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
   3011 
   3012     /**
   3013      * Flag indicating that the bottom scroll indicator should be displayed
   3014      * when this view can scroll up.
   3015      */
   3016     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
   3017 
   3018     /**
   3019      * Flag indicating that the bottom scroll indicator should be displayed
   3020      * when this view can scroll down.
   3021      */
   3022     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
   3023 
   3024     /**
   3025      * Flag indicating that the left scroll indicator should be displayed
   3026      * when this view can scroll left.
   3027      */
   3028     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
   3029 
   3030     /**
   3031      * Flag indicating that the right scroll indicator should be displayed
   3032      * when this view can scroll right.
   3033      */
   3034     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
   3035 
   3036     /**
   3037      * Flag indicating that the start scroll indicator should be displayed
   3038      * when this view can scroll in the start direction.
   3039      */
   3040     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
   3041 
   3042     /**
   3043      * Flag indicating that the end scroll indicator should be displayed
   3044      * when this view can scroll in the end direction.
   3045      */
   3046     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
   3047 
   3048     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
   3049 
   3050     static final int SCROLL_INDICATORS_NONE = 0x0000;
   3051 
   3052     /**
   3053      * Mask for use with setFlags indicating bits used for indicating which
   3054      * scroll indicators are enabled.
   3055      */
   3056     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
   3057             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
   3058             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
   3059             | PFLAG3_SCROLL_INDICATOR_END;
   3060 
   3061     /**
   3062      * Left-shift required to translate between public scroll indicator flags
   3063      * and internal PFLAGS3 flags. When used as a right-shift, translates
   3064      * PFLAGS3 flags to public flags.
   3065      */
   3066     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
   3067 
   3068     /** @hide */
   3069     @Retention(RetentionPolicy.SOURCE)
   3070     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
   3071             SCROLL_INDICATOR_TOP,
   3072             SCROLL_INDICATOR_BOTTOM,
   3073             SCROLL_INDICATOR_LEFT,
   3074             SCROLL_INDICATOR_RIGHT,
   3075             SCROLL_INDICATOR_START,
   3076             SCROLL_INDICATOR_END,
   3077     })
   3078     public @interface ScrollIndicators {}
   3079 
   3080     /**
   3081      * Scroll indicator direction for the top edge of the view.
   3082      *
   3083      * @see #setScrollIndicators(int)
   3084      * @see #setScrollIndicators(int, int)
   3085      * @see #getScrollIndicators()
   3086      */
   3087     public static final int SCROLL_INDICATOR_TOP =
   3088             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3089 
   3090     /**
   3091      * Scroll indicator direction for the bottom edge of the view.
   3092      *
   3093      * @see #setScrollIndicators(int)
   3094      * @see #setScrollIndicators(int, int)
   3095      * @see #getScrollIndicators()
   3096      */
   3097     public static final int SCROLL_INDICATOR_BOTTOM =
   3098             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3099 
   3100     /**
   3101      * Scroll indicator direction for the left edge of the view.
   3102      *
   3103      * @see #setScrollIndicators(int)
   3104      * @see #setScrollIndicators(int, int)
   3105      * @see #getScrollIndicators()
   3106      */
   3107     public static final int SCROLL_INDICATOR_LEFT =
   3108             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3109 
   3110     /**
   3111      * Scroll indicator direction for the right edge of the view.
   3112      *
   3113      * @see #setScrollIndicators(int)
   3114      * @see #setScrollIndicators(int, int)
   3115      * @see #getScrollIndicators()
   3116      */
   3117     public static final int SCROLL_INDICATOR_RIGHT =
   3118             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3119 
   3120     /**
   3121      * Scroll indicator direction for the starting edge of the view.
   3122      * <p>
   3123      * Resolved according to the view's layout direction, see
   3124      * {@link #getLayoutDirection()} for more information.
   3125      *
   3126      * @see #setScrollIndicators(int)
   3127      * @see #setScrollIndicators(int, int)
   3128      * @see #getScrollIndicators()
   3129      */
   3130     public static final int SCROLL_INDICATOR_START =
   3131             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3132 
   3133     /**
   3134      * Scroll indicator direction for the ending edge of the view.
   3135      * <p>
   3136      * Resolved according to the view's layout direction, see
   3137      * {@link #getLayoutDirection()} for more information.
   3138      *
   3139      * @see #setScrollIndicators(int)
   3140      * @see #setScrollIndicators(int, int)
   3141      * @see #getScrollIndicators()
   3142      */
   3143     public static final int SCROLL_INDICATOR_END =
   3144             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3145 
   3146     /**
   3147      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
   3148      * into this view.<p>
   3149      */
   3150     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
   3151 
   3152     /**
   3153      * Flag indicating that the view is a root of a keyboard navigation cluster.
   3154      *
   3155      * @see #isKeyboardNavigationCluster()
   3156      * @see #setKeyboardNavigationCluster(boolean)
   3157      */
   3158     private static final int PFLAG3_CLUSTER = 0x8000;
   3159 
   3160     /**
   3161      * Flag indicating that the view is autofilled
   3162      *
   3163      * @see #isAutofilled()
   3164      * @see #setAutofilled(boolean)
   3165      */
   3166     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
   3167 
   3168     /**
   3169      * Indicates that the user is currently touching the screen.
   3170      * Currently used for the tooltip positioning only.
   3171      */
   3172     private static final int PFLAG3_FINGER_DOWN = 0x20000;
   3173 
   3174     /**
   3175      * Flag indicating that this view is the default-focus view.
   3176      *
   3177      * @see #isFocusedByDefault()
   3178      * @see #setFocusedByDefault(boolean)
   3179      */
   3180     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
   3181 
   3182     /**
   3183      * Shift for the bits in {@link #mPrivateFlags3} related to the
   3184      * "importantForAutofill" attribute.
   3185      */
   3186     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
   3187 
   3188     /**
   3189      * Mask for obtaining the bits which specify how to determine
   3190      * whether a view is important for autofill.
   3191      */
   3192     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
   3193             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
   3194             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
   3195             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
   3196             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
   3197 
   3198     /**
   3199      * Whether this view has rendered elements that overlap (see {@link
   3200      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
   3201      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
   3202      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
   3203      * determined by whatever {@link #hasOverlappingRendering()} returns.
   3204      */
   3205     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
   3206 
   3207     /**
   3208      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
   3209      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
   3210      */
   3211     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
   3212 
   3213     /**
   3214      * Flag indicating that the view is temporarily detached from the parent view.
   3215      *
   3216      * @see #onStartTemporaryDetach()
   3217      * @see #onFinishTemporaryDetach()
   3218      */
   3219     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
   3220 
   3221     /**
   3222      * Flag indicating that the view does not wish to be revealed within its parent
   3223      * hierarchy when it gains focus. Expressed in the negative since the historical
   3224      * default behavior is to reveal on focus; this flag suppresses that behavior.
   3225      *
   3226      * @see #setRevealOnFocusHint(boolean)
   3227      * @see #getRevealOnFocusHint()
   3228      */
   3229     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
   3230 
   3231     /**
   3232      * Flag indicating that when layout is completed we should notify
   3233      * that the view was entered for autofill purposes. To minimize
   3234      * showing autofill for views not visible to the user we evaluate
   3235      * user visibility which cannot be done until the view is laid out.
   3236      */
   3237     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
   3238 
   3239     /**
   3240      * Works like focusable for screen readers, but without the side effects on input focus.
   3241      * @see #setScreenReaderFocusable(boolean)
   3242      */
   3243     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
   3244 
   3245     /**
   3246      * The last aggregated visibility. Used to detect when it truly changes.
   3247      */
   3248     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
   3249 
   3250     /**
   3251      * Used to indicate that {@link #mAutofillId} was explicitly set through
   3252      * {@link #setAutofillId(AutofillId)}.
   3253      */
   3254     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
   3255 
   3256     /**
   3257      * Indicates if the View is a heading for accessibility purposes
   3258      */
   3259     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
   3260 
   3261     /* End of masks for mPrivateFlags3 */
   3262 
   3263     /**
   3264      * Always allow a user to over-scroll this view, provided it is a
   3265      * view that can scroll.
   3266      *
   3267      * @see #getOverScrollMode()
   3268      * @see #setOverScrollMode(int)
   3269      */
   3270     public static final int OVER_SCROLL_ALWAYS = 0;
   3271 
   3272     /**
   3273      * Allow a user to over-scroll this view only if the content is large
   3274      * enough to meaningfully scroll, provided it is a view that can scroll.
   3275      *
   3276      * @see #getOverScrollMode()
   3277      * @see #setOverScrollMode(int)
   3278      */
   3279     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
   3280 
   3281     /**
   3282      * Never allow a user to over-scroll this view.
   3283      *
   3284      * @see #getOverScrollMode()
   3285      * @see #setOverScrollMode(int)
   3286      */
   3287     public static final int OVER_SCROLL_NEVER = 2;
   3288 
   3289     /**
   3290      * Special constant for {@link #setSystemUiVisibility(int)}: View has
   3291      * requested the system UI (status bar) to be visible (the default).
   3292      *
   3293      * @see #setSystemUiVisibility(int)
   3294      */
   3295     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
   3296 
   3297     /**
   3298      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
   3299      * system UI to enter an unobtrusive "low profile" mode.
   3300      *
   3301      * <p>This is for use in games, book readers, video players, or any other
   3302      * "immersive" application where the usual system chrome is deemed too distracting.
   3303      *
   3304      * <p>In low profile mode, the status bar and/or navigation icons may dim.
   3305      *
   3306      * @see #setSystemUiVisibility(int)
   3307      */
   3308     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
   3309 
   3310     /**
   3311      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
   3312      * system navigation be temporarily hidden.
   3313      *
   3314      * <p>This is an even less obtrusive state than that called for by
   3315      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
   3316      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
   3317      * those to disappear. This is useful (in conjunction with the
   3318      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
   3319      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
   3320      * window flags) for displaying content using every last pixel on the display.
   3321      *
   3322      * <p>There is a limitation: because navigation controls are so important, the least user
   3323      * interaction will cause them to reappear immediately.  When this happens, both
   3324      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
   3325      * so that both elements reappear at the same time.
   3326      *
   3327      * @see #setSystemUiVisibility(int)
   3328      */
   3329     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
   3330 
   3331     /**
   3332      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
   3333      * into the normal fullscreen mode so that its content can take over the screen
   3334      * while still allowing the user to interact with the application.
   3335      *
   3336      * <p>This has the same visual effect as
   3337      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
   3338      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
   3339      * meaning that non-critical screen decorations (such as the status bar) will be
   3340      * hidden while the user is in the View's window, focusing the experience on
   3341      * that content.  Unlike the window flag, if you are using ActionBar in
   3342      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   3343      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
   3344      * hide the action bar.
   3345      *
   3346      * <p>This approach to going fullscreen is best used over the window flag when
   3347      * it is a transient state -- that is, the application does this at certain
   3348      * points in its user interaction where it wants to allow the user to focus
   3349      * on content, but not as a continuous state.  For situations where the application
   3350      * would like to simply stay full screen the entire time (such as a game that
   3351      * wants to take over the screen), the
   3352      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
   3353      * is usually a better approach.  The state set here will be removed by the system
   3354      * in various situations (such as the user moving to another application) like
   3355      * the other system UI states.
   3356      *
   3357      * <p>When using this flag, the application should provide some easy facility
   3358      * for the user to go out of it.  A common example would be in an e-book
   3359      * reader, where tapping on the screen brings back whatever screen and UI
   3360      * decorations that had been hidden while the user was immersed in reading
   3361      * the book.
   3362      *
   3363      * @see #setSystemUiVisibility(int)
   3364      */
   3365     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
   3366 
   3367     /**
   3368      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
   3369      * flags, we would like a stable view of the content insets given to
   3370      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
   3371      * will always represent the worst case that the application can expect
   3372      * as a continuous state.  In the stock Android UI this is the space for
   3373      * the system bar, nav bar, and status bar, but not more transient elements
   3374      * such as an input method.
   3375      *
   3376      * The stable layout your UI sees is based on the system UI modes you can
   3377      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   3378      * then you will get a stable layout for changes of the
   3379      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
   3380      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
   3381      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
   3382      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
   3383      * with a stable layout.  (Note that you should avoid using
   3384      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
   3385      *
   3386      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
   3387      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
   3388      * then a hidden status bar will be considered a "stable" state for purposes
   3389      * here.  This allows your UI to continually hide the status bar, while still
   3390      * using the system UI flags to hide the action bar while still retaining
   3391      * a stable layout.  Note that changing the window fullscreen flag will never
   3392      * provide a stable layout for a clean transition.
   3393      *
   3394      * <p>If you are using ActionBar in
   3395      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   3396      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
   3397      * insets it adds to those given to the application.
   3398      */
   3399     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
   3400 
   3401     /**
   3402      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   3403      * to be laid out as if it has requested
   3404      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
   3405      * allows it to avoid artifacts when switching in and out of that mode, at
   3406      * the expense that some of its user interface may be covered by screen
   3407      * decorations when they are shown.  You can perform layout of your inner
   3408      * UI elements to account for the navigation system UI through the
   3409      * {@link #fitSystemWindows(Rect)} method.
   3410      */
   3411     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
   3412 
   3413     /**
   3414      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   3415      * to be laid out as if it has requested
   3416      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
   3417      * allows it to avoid artifacts when switching in and out of that mode, at
   3418      * the expense that some of its user interface may be covered by screen
   3419      * decorations when they are shown.  You can perform layout of your inner
   3420      * UI elements to account for non-fullscreen system UI through the
   3421      * {@link #fitSystemWindows(Rect)} method.
   3422      *
   3423      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
   3424      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
   3425      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
   3426      *  layoutInDisplayCutoutMode} is
   3427      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
   3428      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
   3429      *
   3430      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
   3431      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
   3432      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
   3433      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
   3434      */
   3435     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
   3436 
   3437     /**
   3438      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   3439      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
   3440      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
   3441      * user interaction.
   3442      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
   3443      * has an effect when used in combination with that flag.</p>
   3444      */
   3445     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
   3446 
   3447     /**
   3448      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   3449      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
   3450      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
   3451      * experience while also hiding the system bars.  If this flag is not set,
   3452      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
   3453      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
   3454      * if the user swipes from the top of the screen.
   3455      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
   3456      * system gestures, such as swiping from the top of the screen.  These transient system bars
   3457      * will overlay apps content, may have some degree of transparency, and will automatically
   3458      * hide after a short timeout.
   3459      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
   3460      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
   3461      * with one or both of those flags.</p>
   3462      */
   3463     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
   3464 
   3465     /**
   3466      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
   3467      * is compatible with light status bar backgrounds.
   3468      *
   3469      * <p>For this to take effect, the window must request
   3470      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
   3471      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
   3472      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
   3473      *         FLAG_TRANSLUCENT_STATUS}.
   3474      *
   3475      * @see android.R.attr#windowLightStatusBar
   3476      */
   3477     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
   3478 
   3479     /**
   3480      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
   3481      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
   3482      */
   3483     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
   3484 
   3485     /**
   3486      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
   3487      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
   3488      */
   3489     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
   3490 
   3491     /**
   3492      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
   3493      * that is compatible with light navigation bar backgrounds.
   3494      *
   3495      * <p>For this to take effect, the window must request
   3496      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
   3497      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
   3498      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
   3499      *         FLAG_TRANSLUCENT_NAVIGATION}.
   3500      *
   3501      * @see android.R.attr#windowLightNavigationBar
   3502      */
   3503     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
   3504 
   3505     /**
   3506      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
   3507      */
   3508     @Deprecated
   3509     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
   3510 
   3511     /**
   3512      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
   3513      */
   3514     @Deprecated
   3515     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
   3516 
   3517     /**
   3518      * @hide
   3519      *
   3520      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3521      * out of the public fields to keep the undefined bits out of the developer's way.
   3522      *
   3523      * Flag to make the status bar not expandable.  Unless you also
   3524      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
   3525      */
   3526     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
   3527 
   3528     /**
   3529      * @hide
   3530      *
   3531      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3532      * out of the public fields to keep the undefined bits out of the developer's way.
   3533      *
   3534      * Flag to hide notification icons and scrolling ticker text.
   3535      */
   3536     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
   3537 
   3538     /**
   3539      * @hide
   3540      *
   3541      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3542      * out of the public fields to keep the undefined bits out of the developer's way.
   3543      *
   3544      * Flag to disable incoming notification alerts.  This will not block
   3545      * icons, but it will block sound, vibrating and other visual or aural notifications.
   3546      */
   3547     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
   3548 
   3549     /**
   3550      * @hide
   3551      *
   3552      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3553      * out of the public fields to keep the undefined bits out of the developer's way.
   3554      *
   3555      * Flag to hide only the scrolling ticker.  Note that
   3556      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
   3557      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
   3558      */
   3559     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
   3560 
   3561     /**
   3562      * @hide
   3563      *
   3564      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3565      * out of the public fields to keep the undefined bits out of the developer's way.
   3566      *
   3567      * Flag to hide the center system info area.
   3568      */
   3569     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
   3570 
   3571     /**
   3572      * @hide
   3573      *
   3574      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3575      * out of the public fields to keep the undefined bits out of the developer's way.
   3576      *
   3577      * Flag to hide only the home button.  Don't use this
   3578      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3579      */
   3580     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
   3581 
   3582     /**
   3583      * @hide
   3584      *
   3585      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3586      * out of the public fields to keep the undefined bits out of the developer's way.
   3587      *
   3588      * Flag to hide only the back button. Don't use this
   3589      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3590      */
   3591     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
   3592 
   3593     /**
   3594      * @hide
   3595      *
   3596      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3597      * out of the public fields to keep the undefined bits out of the developer's way.
   3598      *
   3599      * Flag to hide only the clock.  You might use this if your activity has
   3600      * its own clock making the status bar's clock redundant.
   3601      */
   3602     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
   3603 
   3604     /**
   3605      * @hide
   3606      *
   3607      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3608      * out of the public fields to keep the undefined bits out of the developer's way.
   3609      *
   3610      * Flag to hide only the recent apps button. Don't use this
   3611      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3612      */
   3613     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
   3614 
   3615     /**
   3616      * @hide
   3617      *
   3618      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3619      * out of the public fields to keep the undefined bits out of the developer's way.
   3620      *
   3621      * Flag to disable the global search gesture. Don't use this
   3622      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3623      */
   3624     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
   3625 
   3626     /**
   3627      * @hide
   3628      *
   3629      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3630      * out of the public fields to keep the undefined bits out of the developer's way.
   3631      *
   3632      * Flag to specify that the status bar is displayed in transient mode.
   3633      */
   3634     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
   3635 
   3636     /**
   3637      * @hide
   3638      *
   3639      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3640      * out of the public fields to keep the undefined bits out of the developer's way.
   3641      *
   3642      * Flag to specify that the navigation bar is displayed in transient mode.
   3643      */
   3644     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
   3645 
   3646     /**
   3647      * @hide
   3648      *
   3649      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3650      * out of the public fields to keep the undefined bits out of the developer's way.
   3651      *
   3652      * Flag to specify that the hidden status bar would like to be shown.
   3653      */
   3654     public static final int STATUS_BAR_UNHIDE = 0x10000000;
   3655 
   3656     /**
   3657      * @hide
   3658      *
   3659      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3660      * out of the public fields to keep the undefined bits out of the developer's way.
   3661      *
   3662      * Flag to specify that the hidden navigation bar would like to be shown.
   3663      */
   3664     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
   3665 
   3666     /**
   3667      * @hide
   3668      *
   3669      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3670      * out of the public fields to keep the undefined bits out of the developer's way.
   3671      *
   3672      * Flag to specify that the status bar is displayed in translucent mode.
   3673      */
   3674     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
   3675 
   3676     /**
   3677      * @hide
   3678      *
   3679      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3680      * out of the public fields to keep the undefined bits out of the developer's way.
   3681      *
   3682      * Flag to specify that the navigation bar is displayed in translucent mode.
   3683      */
   3684     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
   3685 
   3686     /**
   3687      * @hide
   3688      *
   3689      * Makes navigation bar transparent (but not the status bar).
   3690      */
   3691     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
   3692 
   3693     /**
   3694      * @hide
   3695      *
   3696      * Makes status bar transparent (but not the navigation bar).
   3697      */
   3698     public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
   3699 
   3700     /**
   3701      * @hide
   3702      *
   3703      * Makes both status bar and navigation bar transparent.
   3704      */
   3705     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
   3706             | STATUS_BAR_TRANSPARENT;
   3707 
   3708     /**
   3709      * @hide
   3710      */
   3711     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
   3712 
   3713     /**
   3714      * These are the system UI flags that can be cleared by events outside
   3715      * of an application.  Currently this is just the ability to tap on the
   3716      * screen while hiding the navigation bar to have it return.
   3717      * @hide
   3718      */
   3719     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
   3720             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
   3721             | SYSTEM_UI_FLAG_FULLSCREEN;
   3722 
   3723     /**
   3724      * Flags that can impact the layout in relation to system UI.
   3725      */
   3726     public static final int SYSTEM_UI_LAYOUT_FLAGS =
   3727             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
   3728             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
   3729 
   3730     /** @hide */
   3731     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
   3732             FIND_VIEWS_WITH_TEXT,
   3733             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
   3734     })
   3735     @Retention(RetentionPolicy.SOURCE)
   3736     public @interface FindViewFlags {}
   3737 
   3738     /**
   3739      * Find views that render the specified text.
   3740      *
   3741      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3742      */
   3743     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
   3744 
   3745     /**
   3746      * Find find views that contain the specified content description.
   3747      *
   3748      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3749      */
   3750     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
   3751 
   3752     /**
   3753      * Find views that contain {@link AccessibilityNodeProvider}. Such
   3754      * a View is a root of virtual view hierarchy and may contain the searched
   3755      * text. If this flag is set Views with providers are automatically
   3756      * added and it is a responsibility of the client to call the APIs of
   3757      * the provider to determine whether the virtual tree rooted at this View
   3758      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
   3759      * representing the virtual views with this text.
   3760      *
   3761      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3762      *
   3763      * @hide
   3764      */
   3765     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
   3766 
   3767     /**
   3768      * The undefined cursor position.
   3769      *
   3770      * @hide
   3771      */
   3772     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
   3773 
   3774     /**
   3775      * Indicates that the screen has changed state and is now off.
   3776      *
   3777      * @see #onScreenStateChanged(int)
   3778      */
   3779     public static final int SCREEN_STATE_OFF = 0x0;
   3780 
   3781     /**
   3782      * Indicates that the screen has changed state and is now on.
   3783      *
   3784      * @see #onScreenStateChanged(int)
   3785      */
   3786     public static final int SCREEN_STATE_ON = 0x1;
   3787 
   3788     /**
   3789      * Indicates no axis of view scrolling.
   3790      */
   3791     public static final int SCROLL_AXIS_NONE = 0;
   3792 
   3793     /**
   3794      * Indicates scrolling along the horizontal axis.
   3795      */
   3796     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
   3797 
   3798     /**
   3799      * Indicates scrolling along the vertical axis.
   3800      */
   3801     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
   3802 
   3803     /**
   3804      * Controls the over-scroll mode for this view.
   3805      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
   3806      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
   3807      * and {@link #OVER_SCROLL_NEVER}.
   3808      */
   3809     private int mOverScrollMode;
   3810 
   3811     /**
   3812      * The parent this view is attached to.
   3813      * {@hide}
   3814      *
   3815      * @see #getParent()
   3816      */
   3817     protected ViewParent mParent;
   3818 
   3819     /**
   3820      * {@hide}
   3821      */
   3822     AttachInfo mAttachInfo;
   3823 
   3824     /**
   3825      * {@hide}
   3826      */
   3827     @ViewDebug.ExportedProperty(flagMapping = {
   3828         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
   3829                 name = "FORCE_LAYOUT"),
   3830         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
   3831                 name = "LAYOUT_REQUIRED"),
   3832         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
   3833             name = "DRAWING_CACHE_INVALID", outputIf = false),
   3834         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
   3835         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
   3836         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
   3837         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
   3838     }, formatToHexString = true)
   3839 
   3840     /* @hide */
   3841     public int mPrivateFlags;
   3842     int mPrivateFlags2;
   3843     int mPrivateFlags3;
   3844 
   3845     /**
   3846      * This view's request for the visibility of the status bar.
   3847      * @hide
   3848      */
   3849     @ViewDebug.ExportedProperty(flagMapping = {
   3850             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
   3851                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
   3852                     name = "LOW_PROFILE"),
   3853             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3854                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3855                     name = "HIDE_NAVIGATION"),
   3856             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
   3857                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
   3858                     name = "FULLSCREEN"),
   3859             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
   3860                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
   3861                     name = "LAYOUT_STABLE"),
   3862             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
   3863                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
   3864                     name = "LAYOUT_HIDE_NAVIGATION"),
   3865             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
   3866                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
   3867                     name = "LAYOUT_FULLSCREEN"),
   3868             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
   3869                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
   3870                     name = "IMMERSIVE"),
   3871             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
   3872                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
   3873                     name = "IMMERSIVE_STICKY"),
   3874             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
   3875                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
   3876                     name = "LIGHT_STATUS_BAR"),
   3877             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
   3878                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
   3879                     name = "LIGHT_NAVIGATION_BAR"),
   3880             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
   3881                     equals = STATUS_BAR_DISABLE_EXPAND,
   3882                     name = "STATUS_BAR_DISABLE_EXPAND"),
   3883             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
   3884                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
   3885                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
   3886             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
   3887                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
   3888                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
   3889             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
   3890                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
   3891                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
   3892             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
   3893                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
   3894                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
   3895             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
   3896                     equals = STATUS_BAR_DISABLE_HOME,
   3897                     name = "STATUS_BAR_DISABLE_HOME"),
   3898             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
   3899                     equals = STATUS_BAR_DISABLE_BACK,
   3900                     name = "STATUS_BAR_DISABLE_BACK"),
   3901             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
   3902                     equals = STATUS_BAR_DISABLE_CLOCK,
   3903                     name = "STATUS_BAR_DISABLE_CLOCK"),
   3904             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
   3905                     equals = STATUS_BAR_DISABLE_RECENT,
   3906                     name = "STATUS_BAR_DISABLE_RECENT"),
   3907             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
   3908                     equals = STATUS_BAR_DISABLE_SEARCH,
   3909                     name = "STATUS_BAR_DISABLE_SEARCH"),
   3910             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSIENT,
   3911                     equals = STATUS_BAR_TRANSIENT,
   3912                     name = "STATUS_BAR_TRANSIENT"),
   3913             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSIENT,
   3914                     equals = NAVIGATION_BAR_TRANSIENT,
   3915                     name = "NAVIGATION_BAR_TRANSIENT"),
   3916             @ViewDebug.FlagToString(mask = STATUS_BAR_UNHIDE,
   3917                     equals = STATUS_BAR_UNHIDE,
   3918                     name = "STATUS_BAR_UNHIDE"),
   3919             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_UNHIDE,
   3920                     equals = NAVIGATION_BAR_UNHIDE,
   3921                     name = "NAVIGATION_BAR_UNHIDE"),
   3922             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSLUCENT,
   3923                     equals = STATUS_BAR_TRANSLUCENT,
   3924                     name = "STATUS_BAR_TRANSLUCENT"),
   3925             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSLUCENT,
   3926                     equals = NAVIGATION_BAR_TRANSLUCENT,
   3927                     name = "NAVIGATION_BAR_TRANSLUCENT"),
   3928             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSPARENT,
   3929                     equals = NAVIGATION_BAR_TRANSPARENT,
   3930                     name = "NAVIGATION_BAR_TRANSPARENT"),
   3931             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSPARENT,
   3932                     equals = STATUS_BAR_TRANSPARENT,
   3933                     name = "STATUS_BAR_TRANSPARENT")
   3934     }, formatToHexString = true)
   3935     int mSystemUiVisibility;
   3936 
   3937     /**
   3938      * Reference count for transient state.
   3939      * @see #setHasTransientState(boolean)
   3940      */
   3941     int mTransientStateCount = 0;
   3942 
   3943     /**
   3944      * Count of how many windows this view has been attached to.
   3945      */
   3946     int mWindowAttachCount;
   3947 
   3948     /**
   3949      * The layout parameters associated with this view and used by the parent
   3950      * {@link android.view.ViewGroup} to determine how this view should be
   3951      * laid out.
   3952      * {@hide}
   3953      */
   3954     protected ViewGroup.LayoutParams mLayoutParams;
   3955 
   3956     /**
   3957      * The view flags hold various views states.
   3958      * {@hide}
   3959      */
   3960     @ViewDebug.ExportedProperty(formatToHexString = true)
   3961     int mViewFlags;
   3962 
   3963     static class TransformationInfo {
   3964         /**
   3965          * The transform matrix for the View. This transform is calculated internally
   3966          * based on the translation, rotation, and scale properties.
   3967          *
   3968          * Do *not* use this variable directly; instead call getMatrix(), which will
   3969          * load the value from the View's RenderNode.
   3970          */
   3971         private final Matrix mMatrix = new Matrix();
   3972 
   3973         /**
   3974          * The inverse transform matrix for the View. This transform is calculated
   3975          * internally based on the translation, rotation, and scale properties.
   3976          *
   3977          * Do *not* use this variable directly; instead call getInverseMatrix(),
   3978          * which will load the value from the View's RenderNode.
   3979          */
   3980         private Matrix mInverseMatrix;
   3981 
   3982         /**
   3983          * The opacity of the View. This is a value from 0 to 1, where 0 means
   3984          * completely transparent and 1 means completely opaque.
   3985          */
   3986         @ViewDebug.ExportedProperty
   3987         float mAlpha = 1f;
   3988 
   3989         /**
   3990          * The opacity of the view as manipulated by the Fade transition. This is a hidden
   3991          * property only used by transitions, which is composited with the other alpha
   3992          * values to calculate the final visual alpha value.
   3993          */
   3994         float mTransitionAlpha = 1f;
   3995     }
   3996 
   3997     /** @hide */
   3998     public TransformationInfo mTransformationInfo;
   3999 
   4000     /**
   4001      * Current clip bounds. to which all drawing of this view are constrained.
   4002      */
   4003     @ViewDebug.ExportedProperty(category = "drawing")
   4004     Rect mClipBounds = null;
   4005 
   4006     private boolean mLastIsOpaque;
   4007 
   4008     /**
   4009      * The distance in pixels from the left edge of this view's parent
   4010      * to the left edge of this view.
   4011      * {@hide}
   4012      */
   4013     @ViewDebug.ExportedProperty(category = "layout")
   4014     protected int mLeft;
   4015     /**
   4016      * The distance in pixels from the left edge of this view's parent
   4017      * to the right edge of this view.
   4018      * {@hide}
   4019      */
   4020     @ViewDebug.ExportedProperty(category = "layout")
   4021     protected int mRight;
   4022     /**
   4023      * The distance in pixels from the top edge of this view's parent
   4024      * to the top edge of this view.
   4025      * {@hide}
   4026      */
   4027     @ViewDebug.ExportedProperty(category = "layout")
   4028     protected int mTop;
   4029     /**
   4030      * The distance in pixels from the top edge of this view's parent
   4031      * to the bottom edge of this view.
   4032      * {@hide}
   4033      */
   4034     @ViewDebug.ExportedProperty(category = "layout")
   4035     protected int mBottom;
   4036 
   4037     /**
   4038      * The offset, in pixels, by which the content of this view is scrolled
   4039      * horizontally.
   4040      * {@hide}
   4041      */
   4042     @ViewDebug.ExportedProperty(category = "scrolling")
   4043     protected int mScrollX;
   4044     /**
   4045      * The offset, in pixels, by which the content of this view is scrolled
   4046      * vertically.
   4047      * {@hide}
   4048      */
   4049     @ViewDebug.ExportedProperty(category = "scrolling")
   4050     protected int mScrollY;
   4051 
   4052     /**
   4053      * The left padding in pixels, that is the distance in pixels between the
   4054      * left edge of this view and the left edge of its content.
   4055      * {@hide}
   4056      */
   4057     @ViewDebug.ExportedProperty(category = "padding")
   4058     protected int mPaddingLeft = 0;
   4059     /**
   4060      * The right padding in pixels, that is the distance in pixels between the
   4061      * right edge of this view and the right edge of its content.
   4062      * {@hide}
   4063      */
   4064     @ViewDebug.ExportedProperty(category = "padding")
   4065     protected int mPaddingRight = 0;
   4066     /**
   4067      * The top padding in pixels, that is the distance in pixels between the
   4068      * top edge of this view and the top edge of its content.
   4069      * {@hide}
   4070      */
   4071     @ViewDebug.ExportedProperty(category = "padding")
   4072     protected int mPaddingTop;
   4073     /**
   4074      * The bottom padding in pixels, that is the distance in pixels between the
   4075      * bottom edge of this view and the bottom edge of its content.
   4076      * {@hide}
   4077      */
   4078     @ViewDebug.ExportedProperty(category = "padding")
   4079     protected int mPaddingBottom;
   4080 
   4081     /**
   4082      * The layout insets in pixels, that is the distance in pixels between the
   4083      * visible edges of this view its bounds.
   4084      */
   4085     private Insets mLayoutInsets;
   4086 
   4087     /**
   4088      * Briefly describes the view and is primarily used for accessibility support.
   4089      */
   4090     private CharSequence mContentDescription;
   4091 
   4092     /**
   4093      * If this view represents a distinct part of the window, it can have a title that labels the
   4094      * area.
   4095      */
   4096     private CharSequence mAccessibilityPaneTitle;
   4097 
   4098     /**
   4099      * Specifies the id of a view for which this view serves as a label for
   4100      * accessibility purposes.
   4101      */
   4102     private int mLabelForId = View.NO_ID;
   4103 
   4104     /**
   4105      * Predicate for matching labeled view id with its label for
   4106      * accessibility purposes.
   4107      */
   4108     private MatchLabelForPredicate mMatchLabelForPredicate;
   4109 
   4110     /**
   4111      * Specifies a view before which this one is visited in accessibility traversal.
   4112      */
   4113     private int mAccessibilityTraversalBeforeId = NO_ID;
   4114 
   4115     /**
   4116      * Specifies a view after which this one is visited in accessibility traversal.
   4117      */
   4118     private int mAccessibilityTraversalAfterId = NO_ID;
   4119 
   4120     /**
   4121      * Predicate for matching a view by its id.
   4122      */
   4123     private MatchIdPredicate mMatchIdPredicate;
   4124 
   4125     /**
   4126      * Cache the paddingRight set by the user to append to the scrollbar's size.
   4127      *
   4128      * @hide
   4129      */
   4130     @ViewDebug.ExportedProperty(category = "padding")
   4131     protected int mUserPaddingRight;
   4132 
   4133     /**
   4134      * Cache the paddingBottom set by the user to append to the scrollbar's size.
   4135      *
   4136      * @hide
   4137      */
   4138     @ViewDebug.ExportedProperty(category = "padding")
   4139     protected int mUserPaddingBottom;
   4140 
   4141     /**
   4142      * Cache the paddingLeft set by the user to append to the scrollbar's size.
   4143      *
   4144      * @hide
   4145      */
   4146     @ViewDebug.ExportedProperty(category = "padding")
   4147     protected int mUserPaddingLeft;
   4148 
   4149     /**
   4150      * Cache the paddingStart set by the user to append to the scrollbar's size.
   4151      *
   4152      */
   4153     @ViewDebug.ExportedProperty(category = "padding")
   4154     int mUserPaddingStart;
   4155 
   4156     /**
   4157      * Cache the paddingEnd set by the user to append to the scrollbar's size.
   4158      *
   4159      */
   4160     @ViewDebug.ExportedProperty(category = "padding")
   4161     int mUserPaddingEnd;
   4162 
   4163     /**
   4164      * Cache initial left padding.
   4165      *
   4166      * @hide
   4167      */
   4168     int mUserPaddingLeftInitial;
   4169 
   4170     /**
   4171      * Cache initial right padding.
   4172      *
   4173      * @hide
   4174      */
   4175     int mUserPaddingRightInitial;
   4176 
   4177     /**
   4178      * Default undefined padding
   4179      */
   4180     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
   4181 
   4182     /**
   4183      * Cache if a left padding has been defined
   4184      */
   4185     private boolean mLeftPaddingDefined = false;
   4186 
   4187     /**
   4188      * Cache if a right padding has been defined
   4189      */
   4190     private boolean mRightPaddingDefined = false;
   4191 
   4192     /**
   4193      * @hide
   4194      */
   4195     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
   4196     /**
   4197      * @hide
   4198      */
   4199     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
   4200 
   4201     private LongSparseLongArray mMeasureCache;
   4202 
   4203     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
   4204     private Drawable mBackground;
   4205     private TintInfo mBackgroundTint;
   4206 
   4207     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
   4208     private ForegroundInfo mForegroundInfo;
   4209 
   4210     private Drawable mScrollIndicatorDrawable;
   4211 
   4212     /**
   4213      * RenderNode used for backgrounds.
   4214      * <p>
   4215      * When non-null and valid, this is expected to contain an up-to-date copy
   4216      * of the background drawable. It is cleared on temporary detach, and reset
   4217      * on cleanup.
   4218      */
   4219     private RenderNode mBackgroundRenderNode;
   4220 
   4221     private int mBackgroundResource;
   4222     private boolean mBackgroundSizeChanged;
   4223 
   4224     /** The default focus highlight.
   4225      * @see #mDefaultFocusHighlightEnabled
   4226      * @see Drawable#hasFocusStateSpecified()
   4227      */
   4228     private Drawable mDefaultFocusHighlight;
   4229     private Drawable mDefaultFocusHighlightCache;
   4230     private boolean mDefaultFocusHighlightSizeChanged;
   4231     /**
   4232      * True if the default focus highlight is needed on the target device.
   4233      */
   4234     private static boolean sUseDefaultFocusHighlight;
   4235 
   4236     /**
   4237      * True if zero-sized views can be focused.
   4238      */
   4239     private static boolean sCanFocusZeroSized;
   4240 
   4241     /**
   4242      * Always assign focus if a focusable View is available.
   4243      */
   4244     private static boolean sAlwaysAssignFocus;
   4245 
   4246     private String mTransitionName;
   4247 
   4248     static class TintInfo {
   4249         ColorStateList mTintList;
   4250         PorterDuff.Mode mTintMode;
   4251         boolean mHasTintMode;
   4252         boolean mHasTintList;
   4253     }
   4254 
   4255     private static class ForegroundInfo {
   4256         private Drawable mDrawable;
   4257         private TintInfo mTintInfo;
   4258         private int mGravity = Gravity.FILL;
   4259         private boolean mInsidePadding = true;
   4260         private boolean mBoundsChanged = true;
   4261         private final Rect mSelfBounds = new Rect();
   4262         private final Rect mOverlayBounds = new Rect();
   4263     }
   4264 
   4265     static class ListenerInfo {
   4266         /**
   4267          * Listener used to dispatch focus change events.
   4268          * This field should be made private, so it is hidden from the SDK.
   4269          * {@hide}
   4270          */
   4271         protected OnFocusChangeListener mOnFocusChangeListener;
   4272 
   4273         /**
   4274          * Listeners for layout change events.
   4275          */
   4276         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
   4277 
   4278         protected OnScrollChangeListener mOnScrollChangeListener;
   4279 
   4280         /**
   4281          * Listeners for attach events.
   4282          */
   4283         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
   4284 
   4285         /**
   4286          * Listener used to dispatch click events.
   4287          * This field should be made private, so it is hidden from the SDK.
   4288          * {@hide}
   4289          */
   4290         public OnClickListener mOnClickListener;
   4291 
   4292         /**
   4293          * Listener used to dispatch long click events.
   4294          * This field should be made private, so it is hidden from the SDK.
   4295          * {@hide}
   4296          */
   4297         protected OnLongClickListener mOnLongClickListener;
   4298 
   4299         /**
   4300          * Listener used to dispatch context click events. This field should be made private, so it
   4301          * is hidden from the SDK.
   4302          * {@hide}
   4303          */
   4304         protected OnContextClickListener mOnContextClickListener;
   4305 
   4306         /**
   4307          * Listener used to build the context menu.
   4308          * This field should be made private, so it is hidden from the SDK.
   4309          * {@hide}
   4310          */
   4311         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
   4312 
   4313         private OnKeyListener mOnKeyListener;
   4314 
   4315         private OnTouchListener mOnTouchListener;
   4316 
   4317         private OnHoverListener mOnHoverListener;
   4318 
   4319         private OnGenericMotionListener mOnGenericMotionListener;
   4320 
   4321         private OnDragListener mOnDragListener;
   4322 
   4323         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
   4324 
   4325         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
   4326 
   4327         OnCapturedPointerListener mOnCapturedPointerListener;
   4328 
   4329         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
   4330     }
   4331 
   4332     ListenerInfo mListenerInfo;
   4333 
   4334     private static class TooltipInfo {
   4335         /**
   4336          * Text to be displayed in a tooltip popup.
   4337          */
   4338         @Nullable
   4339         CharSequence mTooltipText;
   4340 
   4341         /**
   4342          * View-relative position of the tooltip anchor point.
   4343          */
   4344         int mAnchorX;
   4345         int mAnchorY;
   4346 
   4347         /**
   4348          * The tooltip popup.
   4349          */
   4350         @Nullable
   4351         TooltipPopup mTooltipPopup;
   4352 
   4353         /**
   4354          * Set to true if the tooltip was shown as a result of a long click.
   4355          */
   4356         boolean mTooltipFromLongClick;
   4357 
   4358         /**
   4359          * Keep these Runnables so that they can be used to reschedule.
   4360          */
   4361         Runnable mShowTooltipRunnable;
   4362         Runnable mHideTooltipRunnable;
   4363 
   4364         /**
   4365          * Hover move is ignored if it is within this distance in pixels from the previous one.
   4366          */
   4367         int mHoverSlop;
   4368 
   4369         /**
   4370          * Update the anchor position if it significantly (that is by at least mHoverSlop)
   4371          * different from the previously stored position. Ignoring insignificant changes
   4372          * filters out the jitter which is typical for such input sources as stylus.
   4373          *
   4374          * @return True if the position has been updated.
   4375          */
   4376         private boolean updateAnchorPos(MotionEvent event) {
   4377             final int newAnchorX = (int) event.getX();
   4378             final int newAnchorY = (int) event.getY();
   4379             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
   4380                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
   4381                 return false;
   4382             }
   4383             mAnchorX = newAnchorX;
   4384             mAnchorY = newAnchorY;
   4385             return true;
   4386         }
   4387 
   4388         /**
   4389          *  Clear the anchor position to ensure that the next change is considered significant.
   4390          */
   4391         private void clearAnchorPos() {
   4392             mAnchorX = Integer.MAX_VALUE;
   4393             mAnchorY = Integer.MAX_VALUE;
   4394         }
   4395     }
   4396 
   4397     TooltipInfo mTooltipInfo;
   4398 
   4399     // Temporary values used to hold (x,y) coordinates when delegating from the
   4400     // two-arg performLongClick() method to the legacy no-arg version.
   4401     private float mLongClickX = Float.NaN;
   4402     private float mLongClickY = Float.NaN;
   4403 
   4404     /**
   4405      * The application environment this view lives in.
   4406      * This field should be made private, so it is hidden from the SDK.
   4407      * {@hide}
   4408      */
   4409     @ViewDebug.ExportedProperty(deepExport = true)
   4410     protected Context mContext;
   4411 
   4412     private final Resources mResources;
   4413 
   4414     private ScrollabilityCache mScrollCache;
   4415 
   4416     private int[] mDrawableState = null;
   4417 
   4418     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
   4419 
   4420     /**
   4421      * Animator that automatically runs based on state changes.
   4422      */
   4423     private StateListAnimator mStateListAnimator;
   4424 
   4425     /**
   4426      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
   4427      * the user may specify which view to go to next.
   4428      */
   4429     private int mNextFocusLeftId = View.NO_ID;
   4430 
   4431     /**
   4432      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
   4433      * the user may specify which view to go to next.
   4434      */
   4435     private int mNextFocusRightId = View.NO_ID;
   4436 
   4437     /**
   4438      * When this view has focus and the next focus is {@link #FOCUS_UP},
   4439      * the user may specify which view to go to next.
   4440      */
   4441     private int mNextFocusUpId = View.NO_ID;
   4442 
   4443     /**
   4444      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
   4445      * the user may specify which view to go to next.
   4446      */
   4447     private int mNextFocusDownId = View.NO_ID;
   4448 
   4449     /**
   4450      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
   4451      * the user may specify which view to go to next.
   4452      */
   4453     int mNextFocusForwardId = View.NO_ID;
   4454 
   4455     /**
   4456      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
   4457      *
   4458      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
   4459      */
   4460     int mNextClusterForwardId = View.NO_ID;
   4461 
   4462     /**
   4463      * Whether this View should use a default focus highlight when it gets focused but doesn't
   4464      * have {@link android.R.attr#state_focused} defined in its background.
   4465      */
   4466     boolean mDefaultFocusHighlightEnabled = true;
   4467 
   4468     private CheckForLongPress mPendingCheckForLongPress;
   4469     private CheckForTap mPendingCheckForTap = null;
   4470     private PerformClick mPerformClick;
   4471     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
   4472 
   4473     private UnsetPressedState mUnsetPressedState;
   4474 
   4475     /**
   4476      * Whether the long press's action has been invoked.  The tap's action is invoked on the
   4477      * up event while a long press is invoked as soon as the long press duration is reached, so
   4478      * a long press could be performed before the tap is checked, in which case the tap's action
   4479      * should not be invoked.
   4480      */
   4481     private boolean mHasPerformedLongPress;
   4482 
   4483     /**
   4484      * Whether a context click button is currently pressed down. This is true when the stylus is
   4485      * touching the screen and the primary button has been pressed, or if a mouse's right button is
   4486      * pressed. This is false once the button is released or if the stylus has been lifted.
   4487      */
   4488     private boolean mInContextButtonPress;
   4489 
   4490     /**
   4491      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
   4492      * true after a stylus button press has occured, when the next up event should not be recognized
   4493      * as a tap.
   4494      */
   4495     private boolean mIgnoreNextUpEvent;
   4496 
   4497     /**
   4498      * The minimum height of the view. We'll try our best to have the height
   4499      * of this view to at least this amount.
   4500      */
   4501     @ViewDebug.ExportedProperty(category = "measurement")
   4502     private int mMinHeight;
   4503 
   4504     /**
   4505      * The minimum width of the view. We'll try our best to have the width
   4506      * of this view to at least this amount.
   4507      */
   4508     @ViewDebug.ExportedProperty(category = "measurement")
   4509     private int mMinWidth;
   4510 
   4511     /**
   4512      * The delegate to handle touch events that are physically in this view
   4513      * but should be handled by another view.
   4514      */
   4515     private TouchDelegate mTouchDelegate = null;
   4516 
   4517     /**
   4518      * Solid color to use as a background when creating the drawing cache. Enables
   4519      * the cache to use 16 bit bitmaps instead of 32 bit.
   4520      */
   4521     private int mDrawingCacheBackgroundColor = 0;
   4522 
   4523     /**
   4524      * Special tree observer used when mAttachInfo is null.
   4525      */
   4526     private ViewTreeObserver mFloatingTreeObserver;
   4527 
   4528     /**
   4529      * Cache the touch slop from the context that created the view.
   4530      */
   4531     private int mTouchSlop;
   4532 
   4533     /**
   4534      * Object that handles automatic animation of view properties.
   4535      */
   4536     private ViewPropertyAnimator mAnimator = null;
   4537 
   4538     /**
   4539      * List of registered FrameMetricsObservers.
   4540      */
   4541     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
   4542 
   4543     /**
   4544      * Flag indicating that a drag can cross window boundaries.  When
   4545      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
   4546      * with this flag set, all visible applications with targetSdkVersion >=
   4547      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
   4548      * in the drag operation and receive the dragged content.
   4549      *
   4550      * <p>If this is the only flag set, then the drag recipient will only have access to text data
   4551      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
   4552      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
   4553      */
   4554     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
   4555 
   4556     /**
   4557      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
   4558      * request read access to the content URI(s) contained in the {@link ClipData} object.
   4559      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
   4560      */
   4561     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
   4562 
   4563     /**
   4564      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
   4565      * request write access to the content URI(s) contained in the {@link ClipData} object.
   4566      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
   4567      */
   4568     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
   4569 
   4570     /**
   4571      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
   4572      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
   4573      * reboots until explicitly revoked with
   4574      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
   4575      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
   4576      */
   4577     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
   4578             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
   4579 
   4580     /**
   4581      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
   4582      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
   4583      * match against the original granted URI.
   4584      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
   4585      */
   4586     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
   4587             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
   4588 
   4589     /**
   4590      * Flag indicating that the drag shadow will be opaque.  When
   4591      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
   4592      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
   4593      */
   4594     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
   4595 
   4596     /**
   4597      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
   4598      */
   4599     private float mVerticalScrollFactor;
   4600 
   4601     /**
   4602      * Position of the vertical scroll bar.
   4603      */
   4604     private int mVerticalScrollbarPosition;
   4605 
   4606     /**
   4607      * Position the scroll bar at the default position as determined by the system.
   4608      */
   4609     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
   4610 
   4611     /**
   4612      * Position the scroll bar along the left edge.
   4613      */
   4614     public static final int SCROLLBAR_POSITION_LEFT = 1;
   4615 
   4616     /**
   4617      * Position the scroll bar along the right edge.
   4618      */
   4619     public static final int SCROLLBAR_POSITION_RIGHT = 2;
   4620 
   4621     /**
   4622      * Indicates that the view does not have a layer.
   4623      *
   4624      * @see #getLayerType()
   4625      * @see #setLayerType(int, android.graphics.Paint)
   4626      * @see #LAYER_TYPE_SOFTWARE
   4627      * @see #LAYER_TYPE_HARDWARE
   4628      */
   4629     public static final int LAYER_TYPE_NONE = 0;
   4630 
   4631     /**
   4632      * <p>Indicates that the view has a software layer. A software layer is backed
   4633      * by a bitmap and causes the view to be rendered using Android's software
   4634      * rendering pipeline, even if hardware acceleration is enabled.</p>
   4635      *
   4636      * <p>Software layers have various usages:</p>
   4637      * <p>When the application is not using hardware acceleration, a software layer
   4638      * is useful to apply a specific color filter and/or blending mode and/or
   4639      * translucency to a view and all its children.</p>
   4640      * <p>When the application is using hardware acceleration, a software layer
   4641      * is useful to render drawing primitives not supported by the hardware
   4642      * accelerated pipeline. It can also be used to cache a complex view tree
   4643      * into a texture and reduce the complexity of drawing operations. For instance,
   4644      * when animating a complex view tree with a translation, a software layer can
   4645      * be used to render the view tree only once.</p>
   4646      * <p>Software layers should be avoided when the affected view tree updates
   4647      * often. Every update will require to re-render the software layer, which can
   4648      * potentially be slow (particularly when hardware acceleration is turned on
   4649      * since the layer will have to be uploaded into a hardware texture after every
   4650      * update.)</p>
   4651      *
   4652      * @see #getLayerType()
   4653      * @see #setLayerType(int, android.graphics.Paint)
   4654      * @see #LAYER_TYPE_NONE
   4655      * @see #LAYER_TYPE_HARDWARE
   4656      */
   4657     public static final int LAYER_TYPE_SOFTWARE = 1;
   4658 
   4659     /**
   4660      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
   4661      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
   4662      * OpenGL hardware) and causes the view to be rendered using Android's hardware
   4663      * rendering pipeline, but only if hardware acceleration is turned on for the
   4664      * view hierarchy. When hardware acceleration is turned off, hardware layers
   4665      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
   4666      *
   4667      * <p>A hardware layer is useful to apply a specific color filter and/or
   4668      * blending mode and/or translucency to a view and all its children.</p>
   4669      * <p>A hardware layer can be used to cache a complex view tree into a
   4670      * texture and reduce the complexity of drawing operations. For instance,
   4671      * when animating a complex view tree with a translation, a hardware layer can
   4672      * be used to render the view tree only once.</p>
   4673      * <p>A hardware layer can also be used to increase the rendering quality when
   4674      * rotation transformations are applied on a view. It can also be used to
   4675      * prevent potential clipping issues when applying 3D transforms on a view.</p>
   4676      *
   4677      * @see #getLayerType()
   4678      * @see #setLayerType(int, android.graphics.Paint)
   4679      * @see #LAYER_TYPE_NONE
   4680      * @see #LAYER_TYPE_SOFTWARE
   4681      */
   4682     public static final int LAYER_TYPE_HARDWARE = 2;
   4683 
   4684     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
   4685             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
   4686             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
   4687             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
   4688     })
   4689     int mLayerType = LAYER_TYPE_NONE;
   4690     Paint mLayerPaint;
   4691 
   4692     /**
   4693      * Set to true when drawing cache is enabled and cannot be created.
   4694      *
   4695      * @hide
   4696      */
   4697     public boolean mCachingFailed;
   4698     private Bitmap mDrawingCache;
   4699     private Bitmap mUnscaledDrawingCache;
   4700 
   4701     /**
   4702      * RenderNode holding View properties, potentially holding a DisplayList of View content.
   4703      * <p>
   4704      * When non-null and valid, this is expected to contain an up-to-date copy
   4705      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
   4706      * cleanup.
   4707      */
   4708     final RenderNode mRenderNode;
   4709 
   4710     /**
   4711      * Set to true when the view is sending hover accessibility events because it
   4712      * is the innermost hovered view.
   4713      */
   4714     private boolean mSendingHoverAccessibilityEvents;
   4715 
   4716     /**
   4717      * Delegate for injecting accessibility functionality.
   4718      */
   4719     AccessibilityDelegate mAccessibilityDelegate;
   4720 
   4721     /**
   4722      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
   4723      * and add/remove objects to/from the overlay directly through the Overlay methods.
   4724      */
   4725     ViewOverlay mOverlay;
   4726 
   4727     /**
   4728      * The currently active parent view for receiving delegated nested scrolling events.
   4729      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
   4730      * by {@link #stopNestedScroll()} at the same point where we clear
   4731      * requestDisallowInterceptTouchEvent.
   4732      */
   4733     private ViewParent mNestedScrollingParent;
   4734 
   4735     /**
   4736      * Consistency verifier for debugging purposes.
   4737      * @hide
   4738      */
   4739     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
   4740             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
   4741                     new InputEventConsistencyVerifier(this, 0) : null;
   4742 
   4743     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
   4744 
   4745     private int[] mTempNestedScrollConsumed;
   4746 
   4747     /**
   4748      * An overlay is going to draw this View instead of being drawn as part of this
   4749      * View's parent. mGhostView is the View in the Overlay that must be invalidated
   4750      * when this view is invalidated.
   4751      */
   4752     GhostView mGhostView;
   4753 
   4754     /**
   4755      * Holds pairs of adjacent attribute data: attribute name followed by its value.
   4756      * @hide
   4757      */
   4758     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
   4759     public String[] mAttributes;
   4760 
   4761     /**
   4762      * Maps a Resource id to its name.
   4763      */
   4764     private static SparseArray<String> mAttributeMap;
   4765 
   4766     /**
   4767      * Queue of pending runnables. Used to postpone calls to post() until this
   4768      * view is attached and has a handler.
   4769      */
   4770     private HandlerActionQueue mRunQueue;
   4771 
   4772     /**
   4773      * The pointer icon when the mouse hovers on this view. The default is null.
   4774      */
   4775     private PointerIcon mPointerIcon;
   4776 
   4777     /**
   4778      * @hide
   4779      */
   4780     String mStartActivityRequestWho;
   4781 
   4782     @Nullable
   4783     private RoundScrollbarRenderer mRoundScrollbarRenderer;
   4784 
   4785     /** Used to delay visibility updates sent to the autofill manager */
   4786     private Handler mVisibilityChangeForAutofillHandler;
   4787 
   4788     /**
   4789      * Simple constructor to use when creating a view from code.
   4790      *
   4791      * @param context The Context the view is running in, through which it can
   4792      *        access the current theme, resources, etc.
   4793      */
   4794     public View(Context context) {
   4795         mContext = context;
   4796         mResources = context != null ? context.getResources() : null;
   4797         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
   4798         // Set some flags defaults
   4799         mPrivateFlags2 =
   4800                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
   4801                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
   4802                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
   4803                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
   4804                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
   4805                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
   4806         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
   4807         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
   4808         mUserPaddingStart = UNDEFINED_PADDING;
   4809         mUserPaddingEnd = UNDEFINED_PADDING;
   4810         mRenderNode = RenderNode.create(getClass().getName(), this);
   4811 
   4812         if (!sCompatibilityDone && context != null) {
   4813             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   4814 
   4815             // Older apps may need this compatibility hack for measurement.
   4816             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
   4817 
   4818             // Older apps expect onMeasure() to always be called on a layout pass, regardless
   4819             // of whether a layout was requested on that View.
   4820             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
   4821 
   4822             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
   4823             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
   4824             Canvas.setCompatibilityVersion(targetSdkVersion);
   4825 
   4826             // In M and newer, our widgets can pass a "hint" value in the size
   4827             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
   4828             // know what the expected parent size is going to be, so e.g. list items can size
   4829             // themselves at 1/3 the size of their container. It breaks older apps though,
   4830             // specifically apps that use some popular open source libraries.
   4831             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
   4832 
   4833             // Old versions of the platform would give different results from
   4834             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
   4835             // modes, so we always need to run an additional EXACTLY pass.
   4836             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
   4837 
   4838             // Prior to N, layout params could change without requiring a
   4839             // subsequent call to setLayoutParams() and they would usually
   4840             // work. Partial layout breaks this assumption.
   4841             sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
   4842 
   4843             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
   4844             // On N+, we throw, but that breaks compatibility with apps that use these methods.
   4845             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
   4846 
   4847             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
   4848             // in apps so we target check it to avoid breaking existing apps.
   4849             sPreserveMarginParamsInLayoutParamConversion =
   4850                     targetSdkVersion >= Build.VERSION_CODES.N;
   4851 
   4852             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
   4853 
   4854             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
   4855 
   4856             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
   4857 
   4858             sUseDefaultFocusHighlight = context.getResources().getBoolean(
   4859                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
   4860 
   4861             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
   4862 
   4863             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
   4864 
   4865             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
   4866 
   4867             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
   4868 
   4869             sCompatibilityDone = true;
   4870         }
   4871     }
   4872 
   4873     /**
   4874      * Constructor that is called when inflating a view from XML. This is called
   4875      * when a view is being constructed from an XML file, supplying attributes
   4876      * that were specified in the XML file. This version uses a default style of
   4877      * 0, so the only attribute values applied are those in the Context's Theme
   4878      * and the given AttributeSet.
   4879      *
   4880      * <p>
   4881      * The method onFinishInflate() will be called after all children have been
   4882      * added.
   4883      *
   4884      * @param context The Context the view is running in, through which it can
   4885      *        access the current theme, resources, etc.
   4886      * @param attrs The attributes of the XML tag that is inflating the view.
   4887      * @see #View(Context, AttributeSet, int)
   4888      */
   4889     public View(Context context, @Nullable AttributeSet attrs) {
   4890         this(context, attrs, 0);
   4891     }
   4892 
   4893     /**
   4894      * Perform inflation from XML and apply a class-specific base style from a
   4895      * theme attribute. This constructor of View allows subclasses to use their
   4896      * own base style when they are inflating. For example, a Button class's
   4897      * constructor would call this version of the super class constructor and
   4898      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
   4899      * allows the theme's button style to modify all of the base view attributes
   4900      * (in particular its background) as well as the Button class's attributes.
   4901      *
   4902      * @param context The Context the view is running in, through which it can
   4903      *        access the current theme, resources, etc.
   4904      * @param attrs The attributes of the XML tag that is inflating the view.
   4905      * @param defStyleAttr An attribute in the current theme that contains a
   4906      *        reference to a style resource that supplies default values for
   4907      *        the view. Can be 0 to not look for defaults.
   4908      * @see #View(Context, AttributeSet)
   4909      */
   4910     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
   4911         this(context, attrs, defStyleAttr, 0);
   4912     }
   4913 
   4914     /**
   4915      * Perform inflation from XML and apply a class-specific base style from a
   4916      * theme attribute or style resource. This constructor of View allows
   4917      * subclasses to use their own base style when they are inflating.
   4918      * <p>
   4919      * When determining the final value of a particular attribute, there are
   4920      * four inputs that come into play:
   4921      * <ol>
   4922      * <li>Any attribute values in the given AttributeSet.
   4923      * <li>The style resource specified in the AttributeSet (named "style").
   4924      * <li>The default style specified by <var>defStyleAttr</var>.
   4925      * <li>The default style specified by <var>defStyleRes</var>.
   4926      * <li>The base values in this theme.
   4927      * </ol>
   4928      * <p>
   4929      * Each of these inputs is considered in-order, with the first listed taking
   4930      * precedence over the following ones. In other words, if in the
   4931      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
   4932      * , then the button's text will <em>always</em> be black, regardless of
   4933      * what is specified in any of the styles.
   4934      *
   4935      * @param context The Context the view is running in, through which it can
   4936      *        access the current theme, resources, etc.
   4937      * @param attrs The attributes of the XML tag that is inflating the view.
   4938      * @param defStyleAttr An attribute in the current theme that contains a
   4939      *        reference to a style resource that supplies default values for
   4940      *        the view. Can be 0 to not look for defaults.
   4941      * @param defStyleRes A resource identifier of a style resource that
   4942      *        supplies default values for the view, used only if
   4943      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
   4944      *        to not look for defaults.
   4945      * @see #View(Context, AttributeSet, int)
   4946      */
   4947     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
   4948         this(context);
   4949 
   4950         final TypedArray a = context.obtainStyledAttributes(
   4951                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
   4952 
   4953         if (mDebugViewAttributes) {
   4954             saveAttributeData(attrs, a);
   4955         }
   4956 
   4957         Drawable background = null;
   4958 
   4959         int leftPadding = -1;
   4960         int topPadding = -1;
   4961         int rightPadding = -1;
   4962         int bottomPadding = -1;
   4963         int startPadding = UNDEFINED_PADDING;
   4964         int endPadding = UNDEFINED_PADDING;
   4965 
   4966         int padding = -1;
   4967         int paddingHorizontal = -1;
   4968         int paddingVertical = -1;
   4969 
   4970         int viewFlagValues = 0;
   4971         int viewFlagMasks = 0;
   4972 
   4973         boolean setScrollContainer = false;
   4974 
   4975         int x = 0;
   4976         int y = 0;
   4977 
   4978         float tx = 0;
   4979         float ty = 0;
   4980         float tz = 0;
   4981         float elevation = 0;
   4982         float rotation = 0;
   4983         float rotationX = 0;
   4984         float rotationY = 0;
   4985         float sx = 1f;
   4986         float sy = 1f;
   4987         boolean transformSet = false;
   4988 
   4989         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
   4990         int overScrollMode = mOverScrollMode;
   4991         boolean initializeScrollbars = false;
   4992         boolean initializeScrollIndicators = false;
   4993 
   4994         boolean startPaddingDefined = false;
   4995         boolean endPaddingDefined = false;
   4996         boolean leftPaddingDefined = false;
   4997         boolean rightPaddingDefined = false;
   4998 
   4999         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   5000 
   5001         // Set default values.
   5002         viewFlagValues |= FOCUSABLE_AUTO;
   5003         viewFlagMasks |= FOCUSABLE_AUTO;
   5004 
   5005         final int N = a.getIndexCount();
   5006         for (int i = 0; i < N; i++) {
   5007             int attr = a.getIndex(i);
   5008             switch (attr) {
   5009                 case com.android.internal.R.styleable.View_background:
   5010                     background = a.getDrawable(attr);
   5011                     break;
   5012                 case com.android.internal.R.styleable.View_padding:
   5013                     padding = a.getDimensionPixelSize(attr, -1);
   5014                     mUserPaddingLeftInitial = padding;
   5015                     mUserPaddingRightInitial = padding;
   5016                     leftPaddingDefined = true;
   5017                     rightPaddingDefined = true;
   5018                     break;
   5019                 case com.android.internal.R.styleable.View_paddingHorizontal:
   5020                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
   5021                     mUserPaddingLeftInitial = paddingHorizontal;
   5022                     mUserPaddingRightInitial = paddingHorizontal;
   5023                     leftPaddingDefined = true;
   5024                     rightPaddingDefined = true;
   5025                     break;
   5026                 case com.android.internal.R.styleable.View_paddingVertical:
   5027                     paddingVertical = a.getDimensionPixelSize(attr, -1);
   5028                     break;
   5029                  case com.android.internal.R.styleable.View_paddingLeft:
   5030                     leftPadding = a.getDimensionPixelSize(attr, -1);
   5031                     mUserPaddingLeftInitial = leftPadding;
   5032                     leftPaddingDefined = true;
   5033                     break;
   5034                 case com.android.internal.R.styleable.View_paddingTop:
   5035                     topPadding = a.getDimensionPixelSize(attr, -1);
   5036                     break;
   5037                 case com.android.internal.R.styleable.View_paddingRight:
   5038                     rightPadding = a.getDimensionPixelSize(attr, -1);
   5039                     mUserPaddingRightInitial = rightPadding;
   5040                     rightPaddingDefined = true;
   5041                     break;
   5042                 case com.android.internal.R.styleable.View_paddingBottom:
   5043                     bottomPadding = a.getDimensionPixelSize(attr, -1);
   5044                     break;
   5045                 case com.android.internal.R.styleable.View_paddingStart:
   5046                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   5047                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
   5048                     break;
   5049                 case com.android.internal.R.styleable.View_paddingEnd:
   5050                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   5051                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
   5052                     break;
   5053                 case com.android.internal.R.styleable.View_scrollX:
   5054                     x = a.getDimensionPixelOffset(attr, 0);
   5055                     break;
   5056                 case com.android.internal.R.styleable.View_scrollY:
   5057                     y = a.getDimensionPixelOffset(attr, 0);
   5058                     break;
   5059                 case com.android.internal.R.styleable.View_alpha:
   5060                     setAlpha(a.getFloat(attr, 1f));
   5061                     break;
   5062                 case com.android.internal.R.styleable.View_transformPivotX:
   5063                     setPivotX(a.getDimension(attr, 0));
   5064                     break;
   5065                 case com.android.internal.R.styleable.View_transformPivotY:
   5066                     setPivotY(a.getDimension(attr, 0));
   5067                     break;
   5068                 case com.android.internal.R.styleable.View_translationX:
   5069                     tx = a.getDimension(attr, 0);
   5070                     transformSet = true;
   5071                     break;
   5072                 case com.android.internal.R.styleable.View_translationY:
   5073                     ty = a.getDimension(attr, 0);
   5074                     transformSet = true;
   5075                     break;
   5076                 case com.android.internal.R.styleable.View_translationZ:
   5077                     tz = a.getDimension(attr, 0);
   5078                     transformSet = true;
   5079                     break;
   5080                 case com.android.internal.R.styleable.View_elevation:
   5081                     elevation = a.getDimension(attr, 0);
   5082                     transformSet = true;
   5083                     break;
   5084                 case com.android.internal.R.styleable.View_rotation:
   5085                     rotation = a.getFloat(attr, 0);
   5086                     transformSet = true;
   5087                     break;
   5088                 case com.android.internal.R.styleable.View_rotationX:
   5089                     rotationX = a.getFloat(attr, 0);
   5090                     transformSet = true;
   5091                     break;
   5092                 case com.android.internal.R.styleable.View_rotationY:
   5093                     rotationY = a.getFloat(attr, 0);
   5094                     transformSet = true;
   5095                     break;
   5096                 case com.android.internal.R.styleable.View_scaleX:
   5097                     sx = a.getFloat(attr, 1f);
   5098                     transformSet = true;
   5099                     break;
   5100                 case com.android.internal.R.styleable.View_scaleY:
   5101                     sy = a.getFloat(attr, 1f);
   5102                     transformSet = true;
   5103                     break;
   5104                 case com.android.internal.R.styleable.View_id:
   5105                     mID = a.getResourceId(attr, NO_ID);
   5106                     break;
   5107                 case com.android.internal.R.styleable.View_tag:
   5108                     mTag = a.getText(attr);
   5109                     break;
   5110                 case com.android.internal.R.styleable.View_fitsSystemWindows:
   5111                     if (a.getBoolean(attr, false)) {
   5112                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
   5113                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
   5114                     }
   5115                     break;
   5116                 case com.android.internal.R.styleable.View_focusable:
   5117                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
   5118                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
   5119                         viewFlagMasks |= FOCUSABLE_MASK;
   5120                     }
   5121                     break;
   5122                 case com.android.internal.R.styleable.View_focusableInTouchMode:
   5123                     if (a.getBoolean(attr, false)) {
   5124                         // unset auto focus since focusableInTouchMode implies explicit focusable
   5125                         viewFlagValues &= ~FOCUSABLE_AUTO;
   5126                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
   5127                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
   5128                     }
   5129                     break;
   5130                 case com.android.internal.R.styleable.View_clickable:
   5131                     if (a.getBoolean(attr, false)) {
   5132                         viewFlagValues |= CLICKABLE;
   5133                         viewFlagMasks |= CLICKABLE;
   5134                     }
   5135                     break;
   5136                 case com.android.internal.R.styleable.View_longClickable:
   5137                     if (a.getBoolean(attr, false)) {
   5138                         viewFlagValues |= LONG_CLICKABLE;
   5139                         viewFlagMasks |= LONG_CLICKABLE;
   5140                     }
   5141                     break;
   5142                 case com.android.internal.R.styleable.View_contextClickable:
   5143                     if (a.getBoolean(attr, false)) {
   5144                         viewFlagValues |= CONTEXT_CLICKABLE;
   5145                         viewFlagMasks |= CONTEXT_CLICKABLE;
   5146                     }
   5147                     break;
   5148                 case com.android.internal.R.styleable.View_saveEnabled:
   5149                     if (!a.getBoolean(attr, true)) {
   5150                         viewFlagValues |= SAVE_DISABLED;
   5151                         viewFlagMasks |= SAVE_DISABLED_MASK;
   5152                     }
   5153                     break;
   5154                 case com.android.internal.R.styleable.View_duplicateParentState:
   5155                     if (a.getBoolean(attr, false)) {
   5156                         viewFlagValues |= DUPLICATE_PARENT_STATE;
   5157                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
   5158                     }
   5159                     break;
   5160                 case com.android.internal.R.styleable.View_visibility:
   5161                     final int visibility = a.getInt(attr, 0);
   5162                     if (visibility != 0) {
   5163                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
   5164                         viewFlagMasks |= VISIBILITY_MASK;
   5165                     }
   5166                     break;
   5167                 case com.android.internal.R.styleable.View_layoutDirection:
   5168                     // Clear any layout direction flags (included resolved bits) already set
   5169                     mPrivateFlags2 &=
   5170                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
   5171                     // Set the layout direction flags depending on the value of the attribute
   5172                     final int layoutDirection = a.getInt(attr, -1);
   5173                     final int value = (layoutDirection != -1) ?
   5174                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
   5175                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
   5176                     break;
   5177                 case com.android.internal.R.styleable.View_drawingCacheQuality:
   5178                     final int cacheQuality = a.getInt(attr, 0);
   5179                     if (cacheQuality != 0) {
   5180                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
   5181                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
   5182                     }
   5183                     break;
   5184                 case com.android.internal.R.styleable.View_contentDescription:
   5185                     setContentDescription(a.getString(attr));
   5186                     break;
   5187                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
   5188                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
   5189                     break;
   5190                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
   5191                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
   5192                     break;
   5193                 case com.android.internal.R.styleable.View_labelFor:
   5194                     setLabelFor(a.getResourceId(attr, NO_ID));
   5195                     break;
   5196                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
   5197                     if (!a.getBoolean(attr, true)) {
   5198                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
   5199                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
   5200                     }
   5201                     break;
   5202                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
   5203                     if (!a.getBoolean(attr, true)) {
   5204                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
   5205                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
   5206                     }
   5207                     break;
   5208                 case R.styleable.View_scrollbars:
   5209                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
   5210                     if (scrollbars != SCROLLBARS_NONE) {
   5211                         viewFlagValues |= scrollbars;
   5212                         viewFlagMasks |= SCROLLBARS_MASK;
   5213                         initializeScrollbars = true;
   5214                     }
   5215                     break;
   5216                 //noinspection deprecation
   5217                 case R.styleable.View_fadingEdge:
   5218                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
   5219                         // Ignore the attribute starting with ICS
   5220                         break;
   5221                     }
   5222                     // With builds < ICS, fall through and apply fading edges
   5223                 case R.styleable.View_requiresFadingEdge:
   5224                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
   5225                     if (fadingEdge != FADING_EDGE_NONE) {
   5226                         viewFlagValues |= fadingEdge;
   5227                         viewFlagMasks |= FADING_EDGE_MASK;
   5228                         initializeFadingEdgeInternal(a);
   5229                     }
   5230                     break;
   5231                 case R.styleable.View_scrollbarStyle:
   5232                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
   5233                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   5234                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
   5235                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
   5236                     }
   5237                     break;
   5238                 case R.styleable.View_isScrollContainer:
   5239                     setScrollContainer = true;
   5240                     if (a.getBoolean(attr, false)) {
   5241                         setScrollContainer(true);
   5242                     }
   5243                     break;
   5244                 case com.android.internal.R.styleable.View_keepScreenOn:
   5245                     if (a.getBoolean(attr, false)) {
   5246                         viewFlagValues |= KEEP_SCREEN_ON;
   5247                         viewFlagMasks |= KEEP_SCREEN_ON;
   5248                     }
   5249                     break;
   5250                 case R.styleable.View_filterTouchesWhenObscured:
   5251                     if (a.getBoolean(attr, false)) {
   5252                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
   5253                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
   5254                     }
   5255                     break;
   5256                 case R.styleable.View_nextFocusLeft:
   5257                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
   5258                     break;
   5259                 case R.styleable.View_nextFocusRight:
   5260                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
   5261                     break;
   5262                 case R.styleable.View_nextFocusUp:
   5263                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
   5264                     break;
   5265                 case R.styleable.View_nextFocusDown:
   5266                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
   5267                     break;
   5268                 case R.styleable.View_nextFocusForward:
   5269                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
   5270                     break;
   5271                 case R.styleable.View_nextClusterForward:
   5272                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
   5273                     break;
   5274                 case R.styleable.View_minWidth:
   5275                     mMinWidth = a.getDimensionPixelSize(attr, 0);
   5276                     break;
   5277                 case R.styleable.View_minHeight:
   5278                     mMinHeight = a.getDimensionPixelSize(attr, 0);
   5279                     break;
   5280                 case R.styleable.View_onClick:
   5281                     if (context.isRestricted()) {
   5282                         throw new IllegalStateException("The android:onClick attribute cannot "
   5283                                 + "be used within a restricted context");
   5284                     }
   5285 
   5286                     final String handlerName = a.getString(attr);
   5287                     if (handlerName != null) {
   5288                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
   5289                     }
   5290                     break;
   5291                 case R.styleable.View_overScrollMode:
   5292                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
   5293                     break;
   5294                 case R.styleable.View_verticalScrollbarPosition:
   5295                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
   5296                     break;
   5297                 case R.styleable.View_layerType:
   5298                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
   5299                     break;
   5300                 case R.styleable.View_textDirection:
   5301                     // Clear any text direction flag already set
   5302                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   5303                     // Set the text direction flags depending on the value of the attribute
   5304                     final int textDirection = a.getInt(attr, -1);
   5305                     if (textDirection != -1) {
   5306                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
   5307                     }
   5308                     break;
   5309                 case R.styleable.View_textAlignment:
   5310                     // Clear any text alignment flag already set
   5311                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   5312                     // Set the text alignment flag depending on the value of the attribute
   5313                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
   5314                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
   5315                     break;
   5316                 case R.styleable.View_importantForAccessibility:
   5317                     setImportantForAccessibility(a.getInt(attr,
   5318                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
   5319                     break;
   5320                 case R.styleable.View_accessibilityLiveRegion:
   5321                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
   5322                     break;
   5323                 case R.styleable.View_transitionName:
   5324                     setTransitionName(a.getString(attr));
   5325                     break;
   5326                 case R.styleable.View_nestedScrollingEnabled:
   5327                     setNestedScrollingEnabled(a.getBoolean(attr, false));
   5328                     break;
   5329                 case R.styleable.View_stateListAnimator:
   5330                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
   5331                             a.getResourceId(attr, 0)));
   5332                     break;
   5333                 case R.styleable.View_backgroundTint:
   5334                     // This will get applied later during setBackground().
   5335                     if (mBackgroundTint == null) {
   5336                         mBackgroundTint = new TintInfo();
   5337                     }
   5338                     mBackgroundTint.mTintList = a.getColorStateList(
   5339                             R.styleable.View_backgroundTint);
   5340                     mBackgroundTint.mHasTintList = true;
   5341                     break;
   5342                 case R.styleable.View_backgroundTintMode:
   5343                     // This will get applied later during setBackground().
   5344                     if (mBackgroundTint == null) {
   5345                         mBackgroundTint = new TintInfo();
   5346                     }
   5347                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
   5348                             R.styleable.View_backgroundTintMode, -1), null);
   5349                     mBackgroundTint.mHasTintMode = true;
   5350                     break;
   5351                 case R.styleable.View_outlineProvider:
   5352                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
   5353                             PROVIDER_BACKGROUND));
   5354                     break;
   5355                 case R.styleable.View_foreground:
   5356                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5357                         setForeground(a.getDrawable(attr));
   5358                     }
   5359                     break;
   5360                 case R.styleable.View_foregroundGravity:
   5361                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5362                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
   5363                     }
   5364                     break;
   5365                 case R.styleable.View_foregroundTintMode:
   5366                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5367                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
   5368                     }
   5369                     break;
   5370                 case R.styleable.View_foregroundTint:
   5371                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5372                         setForegroundTintList(a.getColorStateList(attr));
   5373                     }
   5374                     break;
   5375                 case R.styleable.View_foregroundInsidePadding:
   5376                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5377                         if (mForegroundInfo == null) {
   5378                             mForegroundInfo = new ForegroundInfo();
   5379                         }
   5380                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
   5381                                 mForegroundInfo.mInsidePadding);
   5382                     }
   5383                     break;
   5384                 case R.styleable.View_scrollIndicators:
   5385                     final int scrollIndicators =
   5386                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
   5387                                     & SCROLL_INDICATORS_PFLAG3_MASK;
   5388                     if (scrollIndicators != 0) {
   5389                         mPrivateFlags3 |= scrollIndicators;
   5390                         initializeScrollIndicators = true;
   5391                     }
   5392                     break;
   5393                 case R.styleable.View_pointerIcon:
   5394                     final int resourceId = a.getResourceId(attr, 0);
   5395                     if (resourceId != 0) {
   5396                         setPointerIcon(PointerIcon.load(
   5397                                 context.getResources(), resourceId));
   5398                     } else {
   5399                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
   5400                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
   5401                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
   5402                         }
   5403                     }
   5404                     break;
   5405                 case R.styleable.View_forceHasOverlappingRendering:
   5406                     if (a.peekValue(attr) != null) {
   5407                         forceHasOverlappingRendering(a.getBoolean(attr, true));
   5408                     }
   5409                     break;
   5410                 case R.styleable.View_tooltipText:
   5411                     setTooltipText(a.getText(attr));
   5412                     break;
   5413                 case R.styleable.View_keyboardNavigationCluster:
   5414                     if (a.peekValue(attr) != null) {
   5415                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
   5416                     }
   5417                     break;
   5418                 case R.styleable.View_focusedByDefault:
   5419                     if (a.peekValue(attr) != null) {
   5420                         setFocusedByDefault(a.getBoolean(attr, true));
   5421                     }
   5422                     break;
   5423                 case R.styleable.View_autofillHints:
   5424                     if (a.peekValue(attr) != null) {
   5425                         CharSequence[] rawHints = null;
   5426                         String rawString = null;
   5427 
   5428                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
   5429                             int resId = a.getResourceId(attr, 0);
   5430 
   5431                             try {
   5432                                 rawHints = a.getTextArray(attr);
   5433                             } catch (Resources.NotFoundException e) {
   5434                                 rawString = getResources().getString(resId);
   5435                             }
   5436                         } else {
   5437                             rawString = a.getString(attr);
   5438                         }
   5439 
   5440                         if (rawHints == null) {
   5441                             if (rawString == null) {
   5442                                 throw new IllegalArgumentException(
   5443                                         "Could not resolve autofillHints");
   5444                             } else {
   5445                                 rawHints = rawString.split(",");
   5446                             }
   5447                         }
   5448 
   5449                         String[] hints = new String[rawHints.length];
   5450 
   5451                         int numHints = rawHints.length;
   5452                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
   5453                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
   5454                         }
   5455                         setAutofillHints(hints);
   5456                     }
   5457                     break;
   5458                 case R.styleable.View_importantForAutofill:
   5459                     if (a.peekValue(attr) != null) {
   5460                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
   5461                     }
   5462                     break;
   5463                 case R.styleable.View_defaultFocusHighlightEnabled:
   5464                     if (a.peekValue(attr) != null) {
   5465                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
   5466                     }
   5467                     break;
   5468                 case R.styleable.View_screenReaderFocusable:
   5469                     if (a.peekValue(attr) != null) {
   5470                         setScreenReaderFocusable(a.getBoolean(attr, false));
   5471                     }
   5472                     break;
   5473                 case R.styleable.View_accessibilityPaneTitle:
   5474                     if (a.peekValue(attr) != null) {
   5475                         setAccessibilityPaneTitle(a.getString(attr));
   5476                     }
   5477                     break;
   5478                 case R.styleable.View_outlineSpotShadowColor:
   5479                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
   5480                     break;
   5481                 case R.styleable.View_outlineAmbientShadowColor:
   5482                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
   5483                     break;
   5484                 case com.android.internal.R.styleable.View_accessibilityHeading:
   5485                     setAccessibilityHeading(a.getBoolean(attr, false));
   5486             }
   5487         }
   5488 
   5489         setOverScrollMode(overScrollMode);
   5490 
   5491         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
   5492         // the resolved layout direction). Those cached values will be used later during padding
   5493         // resolution.
   5494         mUserPaddingStart = startPadding;
   5495         mUserPaddingEnd = endPadding;
   5496 
   5497         if (background != null) {
   5498             setBackground(background);
   5499         }
   5500 
   5501         // setBackground above will record that padding is currently provided by the background.
   5502         // If we have padding specified via xml, record that here instead and use it.
   5503         mLeftPaddingDefined = leftPaddingDefined;
   5504         mRightPaddingDefined = rightPaddingDefined;
   5505 
   5506         if (padding >= 0) {
   5507             leftPadding = padding;
   5508             topPadding = padding;
   5509             rightPadding = padding;
   5510             bottomPadding = padding;
   5511             mUserPaddingLeftInitial = padding;
   5512             mUserPaddingRightInitial = padding;
   5513         } else {
   5514             if (paddingHorizontal >= 0) {
   5515                 leftPadding = paddingHorizontal;
   5516                 rightPadding = paddingHorizontal;
   5517                 mUserPaddingLeftInitial = paddingHorizontal;
   5518                 mUserPaddingRightInitial = paddingHorizontal;
   5519             }
   5520             if (paddingVertical >= 0) {
   5521                 topPadding = paddingVertical;
   5522                 bottomPadding = paddingVertical;
   5523             }
   5524         }
   5525 
   5526         if (isRtlCompatibilityMode()) {
   5527             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
   5528             // left / right padding are used if defined (meaning here nothing to do). If they are not
   5529             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
   5530             // start / end and resolve them as left / right (layout direction is not taken into account).
   5531             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   5532             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   5533             // defined.
   5534             if (!mLeftPaddingDefined && startPaddingDefined) {
   5535                 leftPadding = startPadding;
   5536             }
   5537             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
   5538             if (!mRightPaddingDefined && endPaddingDefined) {
   5539                 rightPadding = endPadding;
   5540             }
   5541             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
   5542         } else {
   5543             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
   5544             // values defined. Otherwise, left /right values are used.
   5545             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   5546             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   5547             // defined.
   5548             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
   5549 
   5550             if (mLeftPaddingDefined && !hasRelativePadding) {
   5551                 mUserPaddingLeftInitial = leftPadding;
   5552             }
   5553             if (mRightPaddingDefined && !hasRelativePadding) {
   5554                 mUserPaddingRightInitial = rightPadding;
   5555             }
   5556         }
   5557 
   5558         internalSetPadding(
   5559                 mUserPaddingLeftInitial,
   5560                 topPadding >= 0 ? topPadding : mPaddingTop,
   5561                 mUserPaddingRightInitial,
   5562                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
   5563 
   5564         if (viewFlagMasks != 0) {
   5565             setFlags(viewFlagValues, viewFlagMasks);
   5566         }
   5567 
   5568         if (initializeScrollbars) {
   5569             initializeScrollbarsInternal(a);
   5570         }
   5571 
   5572         if (initializeScrollIndicators) {
   5573             initializeScrollIndicatorsInternal();
   5574         }
   5575 
   5576         a.recycle();
   5577 
   5578         // Needs to be called after mViewFlags is set
   5579         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   5580             recomputePadding();
   5581         }
   5582 
   5583         if (x != 0 || y != 0) {
   5584             scrollTo(x, y);
   5585         }
   5586 
   5587         if (transformSet) {
   5588             setTranslationX(tx);
   5589             setTranslationY(ty);
   5590             setTranslationZ(tz);
   5591             setElevation(elevation);
   5592             setRotation(rotation);
   5593             setRotationX(rotationX);
   5594             setRotationY(rotationY);
   5595             setScaleX(sx);
   5596             setScaleY(sy);
   5597         }
   5598 
   5599         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
   5600             setScrollContainer(true);
   5601         }
   5602 
   5603         computeOpaqueFlags();
   5604     }
   5605 
   5606     /**
   5607      * An implementation of OnClickListener that attempts to lazily load a
   5608      * named click handling method from a parent or ancestor context.
   5609      */
   5610     private static class DeclaredOnClickListener implements OnClickListener {
   5611         private final View mHostView;
   5612         private final String mMethodName;
   5613 
   5614         private Method mResolvedMethod;
   5615         private Context mResolvedContext;
   5616 
   5617         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
   5618             mHostView = hostView;
   5619             mMethodName = methodName;
   5620         }
   5621 
   5622         @Override
   5623         public void onClick(@NonNull View v) {
   5624             if (mResolvedMethod == null) {
   5625                 resolveMethod(mHostView.getContext(), mMethodName);
   5626             }
   5627 
   5628             try {
   5629                 mResolvedMethod.invoke(mResolvedContext, v);
   5630             } catch (IllegalAccessException e) {
   5631                 throw new IllegalStateException(
   5632                         "Could not execute non-public method for android:onClick", e);
   5633             } catch (InvocationTargetException e) {
   5634                 throw new IllegalStateException(
   5635                         "Could not execute method for android:onClick", e);
   5636             }
   5637         }
   5638 
   5639         @NonNull
   5640         private void resolveMethod(@Nullable Context context, @NonNull String name) {
   5641             while (context != null) {
   5642                 try {
   5643                     if (!context.isRestricted()) {
   5644                         final Method method = context.getClass().getMethod(mMethodName, View.class);
   5645                         if (method != null) {
   5646                             mResolvedMethod = method;
   5647                             mResolvedContext = context;
   5648                             return;
   5649                         }
   5650                     }
   5651                 } catch (NoSuchMethodException e) {
   5652                     // Failed to find method, keep searching up the hierarchy.
   5653                 }
   5654 
   5655                 if (context instanceof ContextWrapper) {
   5656                     context = ((ContextWrapper) context).getBaseContext();
   5657                 } else {
   5658                     // Can't search up the hierarchy, null out and fail.
   5659                     context = null;
   5660                 }
   5661             }
   5662 
   5663             final int id = mHostView.getId();
   5664             final String idText = id == NO_ID ? "" : " with id '"
   5665                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
   5666             throw new IllegalStateException("Could not find method " + mMethodName
   5667                     + "(View) in a parent or ancestor Context for android:onClick "
   5668                     + "attribute defined on view " + mHostView.getClass() + idText);
   5669         }
   5670     }
   5671 
   5672     /**
   5673      * Non-public constructor for use in testing
   5674      */
   5675     View() {
   5676         mResources = null;
   5677         mRenderNode = RenderNode.create(getClass().getName(), this);
   5678     }
   5679 
   5680     final boolean debugDraw() {
   5681         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
   5682     }
   5683 
   5684     private static SparseArray<String> getAttributeMap() {
   5685         if (mAttributeMap == null) {
   5686             mAttributeMap = new SparseArray<>();
   5687         }
   5688         return mAttributeMap;
   5689     }
   5690 
   5691     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
   5692         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
   5693         final int indexCount = t.getIndexCount();
   5694         final String[] attributes = new String[(attrsCount + indexCount) * 2];
   5695 
   5696         int i = 0;
   5697 
   5698         // Store raw XML attributes.
   5699         for (int j = 0; j < attrsCount; ++j) {
   5700             attributes[i] = attrs.getAttributeName(j);
   5701             attributes[i + 1] = attrs.getAttributeValue(j);
   5702             i += 2;
   5703         }
   5704 
   5705         // Store resolved styleable attributes.
   5706         final Resources res = t.getResources();
   5707         final SparseArray<String> attributeMap = getAttributeMap();
   5708         for (int j = 0; j < indexCount; ++j) {
   5709             final int index = t.getIndex(j);
   5710             if (!t.hasValueOrEmpty(index)) {
   5711                 // Value is undefined. Skip it.
   5712                 continue;
   5713             }
   5714 
   5715             final int resourceId = t.getResourceId(index, 0);
   5716             if (resourceId == 0) {
   5717                 // Value is not a reference. Skip it.
   5718                 continue;
   5719             }
   5720 
   5721             String resourceName = attributeMap.get(resourceId);
   5722             if (resourceName == null) {
   5723                 try {
   5724                     resourceName = res.getResourceName(resourceId);
   5725                 } catch (Resources.NotFoundException e) {
   5726                     resourceName = "0x" + Integer.toHexString(resourceId);
   5727                 }
   5728                 attributeMap.put(resourceId, resourceName);
   5729             }
   5730 
   5731             attributes[i] = resourceName;
   5732             attributes[i + 1] = t.getString(index);
   5733             i += 2;
   5734         }
   5735 
   5736         // Trim to fit contents.
   5737         final String[] trimmed = new String[i];
   5738         System.arraycopy(attributes, 0, trimmed, 0, i);
   5739         mAttributes = trimmed;
   5740     }
   5741 
   5742     public String toString() {
   5743         StringBuilder out = new StringBuilder(128);
   5744         out.append(getClass().getName());
   5745         out.append('{');
   5746         out.append(Integer.toHexString(System.identityHashCode(this)));
   5747         out.append(' ');
   5748         switch (mViewFlags&VISIBILITY_MASK) {
   5749             case VISIBLE: out.append('V'); break;
   5750             case INVISIBLE: out.append('I'); break;
   5751             case GONE: out.append('G'); break;
   5752             default: out.append('.'); break;
   5753         }
   5754         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
   5755         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
   5756         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
   5757         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
   5758         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
   5759         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
   5760         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
   5761         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
   5762         out.append(' ');
   5763         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
   5764         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
   5765         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
   5766         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
   5767             out.append('p');
   5768         } else {
   5769             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
   5770         }
   5771         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
   5772         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
   5773         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
   5774         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
   5775         out.append(' ');
   5776         out.append(mLeft);
   5777         out.append(',');
   5778         out.append(mTop);
   5779         out.append('-');
   5780         out.append(mRight);
   5781         out.append(',');
   5782         out.append(mBottom);
   5783         final int id = getId();
   5784         if (id != NO_ID) {
   5785             out.append(" #");
   5786             out.append(Integer.toHexString(id));
   5787             final Resources r = mResources;
   5788             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
   5789                 try {
   5790                     String pkgname;
   5791                     switch (id&0xff000000) {
   5792                         case 0x7f000000:
   5793                             pkgname="app";
   5794                             break;
   5795                         case 0x01000000:
   5796                             pkgname="android";
   5797                             break;
   5798                         default:
   5799                             pkgname = r.getResourcePackageName(id);
   5800                             break;
   5801                     }
   5802                     String typename = r.getResourceTypeName(id);
   5803                     String entryname = r.getResourceEntryName(id);
   5804                     out.append(" ");
   5805                     out.append(pkgname);
   5806                     out.append(":");
   5807                     out.append(typename);
   5808                     out.append("/");
   5809                     out.append(entryname);
   5810                 } catch (Resources.NotFoundException e) {
   5811                 }
   5812             }
   5813         }
   5814         out.append("}");
   5815         return out.toString();
   5816     }
   5817 
   5818     /**
   5819      * <p>
   5820      * Initializes the fading edges from a given set of styled attributes. This
   5821      * method should be called by subclasses that need fading edges and when an
   5822      * instance of these subclasses is created programmatically rather than
   5823      * being inflated from XML. This method is automatically called when the XML
   5824      * is inflated.
   5825      * </p>
   5826      *
   5827      * @param a the styled attributes set to initialize the fading edges from
   5828      *
   5829      * @removed
   5830      */
   5831     protected void initializeFadingEdge(TypedArray a) {
   5832         // This method probably shouldn't have been included in the SDK to begin with.
   5833         // It relies on 'a' having been initialized using an attribute filter array that is
   5834         // not publicly available to the SDK. The old method has been renamed
   5835         // to initializeFadingEdgeInternal and hidden for framework use only;
   5836         // this one initializes using defaults to make it safe to call for apps.
   5837 
   5838         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   5839 
   5840         initializeFadingEdgeInternal(arr);
   5841 
   5842         arr.recycle();
   5843     }
   5844 
   5845     /**
   5846      * <p>
   5847      * Initializes the fading edges from a given set of styled attributes. This
   5848      * method should be called by subclasses that need fading edges and when an
   5849      * instance of these subclasses is created programmatically rather than
   5850      * being inflated from XML. This method is automatically called when the XML
   5851      * is inflated.
   5852      * </p>
   5853      *
   5854      * @param a the styled attributes set to initialize the fading edges from
   5855      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
   5856      */
   5857     protected void initializeFadingEdgeInternal(TypedArray a) {
   5858         initScrollCache();
   5859 
   5860         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
   5861                 R.styleable.View_fadingEdgeLength,
   5862                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
   5863     }
   5864 
   5865     /**
   5866      * Returns the size of the vertical faded edges used to indicate that more
   5867      * content in this view is visible.
   5868      *
   5869      * @return The size in pixels of the vertical faded edge or 0 if vertical
   5870      *         faded edges are not enabled for this view.
   5871      * @attr ref android.R.styleable#View_fadingEdgeLength
   5872      */
   5873     public int getVerticalFadingEdgeLength() {
   5874         if (isVerticalFadingEdgeEnabled()) {
   5875             ScrollabilityCache cache = mScrollCache;
   5876             if (cache != null) {
   5877                 return cache.fadingEdgeLength;
   5878             }
   5879         }
   5880         return 0;
   5881     }
   5882 
   5883     /**
   5884      * Set the size of the faded edge used to indicate that more content in this
   5885      * view is available.  Will not change whether the fading edge is enabled; use
   5886      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
   5887      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
   5888      * for the vertical or horizontal fading edges.
   5889      *
   5890      * @param length The size in pixels of the faded edge used to indicate that more
   5891      *        content in this view is visible.
   5892      */
   5893     public void setFadingEdgeLength(int length) {
   5894         initScrollCache();
   5895         mScrollCache.fadingEdgeLength = length;
   5896     }
   5897 
   5898     /**
   5899      * Returns the size of the horizontal faded edges used to indicate that more
   5900      * content in this view is visible.
   5901      *
   5902      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
   5903      *         faded edges are not enabled for this view.
   5904      * @attr ref android.R.styleable#View_fadingEdgeLength
   5905      */
   5906     public int getHorizontalFadingEdgeLength() {
   5907         if (isHorizontalFadingEdgeEnabled()) {
   5908             ScrollabilityCache cache = mScrollCache;
   5909             if (cache != null) {
   5910                 return cache.fadingEdgeLength;
   5911             }
   5912         }
   5913         return 0;
   5914     }
   5915 
   5916     /**
   5917      * Returns the width of the vertical scrollbar.
   5918      *
   5919      * @return The width in pixels of the vertical scrollbar or 0 if there
   5920      *         is no vertical scrollbar.
   5921      */
   5922     public int getVerticalScrollbarWidth() {
   5923         ScrollabilityCache cache = mScrollCache;
   5924         if (cache != null) {
   5925             ScrollBarDrawable scrollBar = cache.scrollBar;
   5926             if (scrollBar != null) {
   5927                 int size = scrollBar.getSize(true);
   5928                 if (size <= 0) {
   5929                     size = cache.scrollBarSize;
   5930                 }
   5931                 return size;
   5932             }
   5933             return 0;
   5934         }
   5935         return 0;
   5936     }
   5937 
   5938     /**
   5939      * Returns the height of the horizontal scrollbar.
   5940      *
   5941      * @return The height in pixels of the horizontal scrollbar or 0 if
   5942      *         there is no horizontal scrollbar.
   5943      */
   5944     protected int getHorizontalScrollbarHeight() {
   5945         ScrollabilityCache cache = mScrollCache;
   5946         if (cache != null) {
   5947             ScrollBarDrawable scrollBar = cache.scrollBar;
   5948             if (scrollBar != null) {
   5949                 int size = scrollBar.getSize(false);
   5950                 if (size <= 0) {
   5951                     size = cache.scrollBarSize;
   5952                 }
   5953                 return size;
   5954             }
   5955             return 0;
   5956         }
   5957         return 0;
   5958     }
   5959 
   5960     /**
   5961      * <p>
   5962      * Initializes the scrollbars from a given set of styled attributes. This
   5963      * method should be called by subclasses that need scrollbars and when an
   5964      * instance of these subclasses is created programmatically rather than
   5965      * being inflated from XML. This method is automatically called when the XML
   5966      * is inflated.
   5967      * </p>
   5968      *
   5969      * @param a the styled attributes set to initialize the scrollbars from
   5970      *
   5971      * @removed
   5972      */
   5973     protected void initializeScrollbars(TypedArray a) {
   5974         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
   5975         // using the View filter array which is not available to the SDK. As such, internal
   5976         // framework usage now uses initializeScrollbarsInternal and we grab a default
   5977         // TypedArray with the right filter instead here.
   5978         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   5979 
   5980         initializeScrollbarsInternal(arr);
   5981 
   5982         // We ignored the method parameter. Recycle the one we actually did use.
   5983         arr.recycle();
   5984     }
   5985 
   5986     /**
   5987      * <p>
   5988      * Initializes the scrollbars from a given set of styled attributes. This
   5989      * method should be called by subclasses that need scrollbars and when an
   5990      * instance of these subclasses is created programmatically rather than
   5991      * being inflated from XML. This method is automatically called when the XML
   5992      * is inflated.
   5993      * </p>
   5994      *
   5995      * @param a the styled attributes set to initialize the scrollbars from
   5996      * @hide
   5997      */
   5998     protected void initializeScrollbarsInternal(TypedArray a) {
   5999         initScrollCache();
   6000 
   6001         final ScrollabilityCache scrollabilityCache = mScrollCache;
   6002 
   6003         if (scrollabilityCache.scrollBar == null) {
   6004             scrollabilityCache.scrollBar = new ScrollBarDrawable();
   6005             scrollabilityCache.scrollBar.setState(getDrawableState());
   6006             scrollabilityCache.scrollBar.setCallback(this);
   6007         }
   6008 
   6009         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
   6010 
   6011         if (!fadeScrollbars) {
   6012             scrollabilityCache.state = ScrollabilityCache.ON;
   6013         }
   6014         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   6015 
   6016 
   6017         scrollabilityCache.scrollBarFadeDuration = a.getInt(
   6018                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
   6019                         .getScrollBarFadeDuration());
   6020         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
   6021                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
   6022                 ViewConfiguration.getScrollDefaultDelay());
   6023 
   6024 
   6025         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
   6026                 com.android.internal.R.styleable.View_scrollbarSize,
   6027                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
   6028 
   6029         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
   6030         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
   6031 
   6032         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
   6033         if (thumb != null) {
   6034             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
   6035         }
   6036 
   6037         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
   6038                 false);
   6039         if (alwaysDraw) {
   6040             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
   6041         }
   6042 
   6043         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
   6044         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
   6045 
   6046         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
   6047         if (thumb != null) {
   6048             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
   6049         }
   6050 
   6051         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
   6052                 false);
   6053         if (alwaysDraw) {
   6054             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
   6055         }
   6056 
   6057         // Apply layout direction to the new Drawables if needed
   6058         final int layoutDirection = getLayoutDirection();
   6059         if (track != null) {
   6060             track.setLayoutDirection(layoutDirection);
   6061         }
   6062         if (thumb != null) {
   6063             thumb.setLayoutDirection(layoutDirection);
   6064         }
   6065 
   6066         // Re-apply user/background padding so that scrollbar(s) get added
   6067         resolvePadding();
   6068     }
   6069 
   6070     private void initializeScrollIndicatorsInternal() {
   6071         // Some day maybe we'll break this into top/left/start/etc. and let the
   6072         // client control it. Until then, you can have any scroll indicator you
   6073         // want as long as it's a 1dp foreground-colored rectangle.
   6074         if (mScrollIndicatorDrawable == null) {
   6075             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
   6076         }
   6077     }
   6078 
   6079     /**
   6080      * <p>
   6081      * Initalizes the scrollability cache if necessary.
   6082      * </p>
   6083      */
   6084     private void initScrollCache() {
   6085         if (mScrollCache == null) {
   6086             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
   6087         }
   6088     }
   6089 
   6090     private ScrollabilityCache getScrollCache() {
   6091         initScrollCache();
   6092         return mScrollCache;
   6093     }
   6094 
   6095     /**
   6096      * Set the position of the vertical scroll bar. Should be one of
   6097      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
   6098      * {@link #SCROLLBAR_POSITION_RIGHT}.
   6099      *
   6100      * @param position Where the vertical scroll bar should be positioned.
   6101      */
   6102     public void setVerticalScrollbarPosition(int position) {
   6103         if (mVerticalScrollbarPosition != position) {
   6104             mVerticalScrollbarPosition = position;
   6105             computeOpaqueFlags();
   6106             resolvePadding();
   6107         }
   6108     }
   6109 
   6110     /**
   6111      * @return The position where the vertical scroll bar will show, if applicable.
   6112      * @see #setVerticalScrollbarPosition(int)
   6113      */
   6114     public int getVerticalScrollbarPosition() {
   6115         return mVerticalScrollbarPosition;
   6116     }
   6117 
   6118     boolean isOnScrollbar(float x, float y) {
   6119         if (mScrollCache == null) {
   6120             return false;
   6121         }
   6122         x += getScrollX();
   6123         y += getScrollY();
   6124         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
   6125             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
   6126             getVerticalScrollBarBounds(null, touchBounds);
   6127             if (touchBounds.contains((int) x, (int) y)) {
   6128                 return true;
   6129             }
   6130         }
   6131         if (isHorizontalScrollBarEnabled()) {
   6132             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
   6133             getHorizontalScrollBarBounds(null, touchBounds);
   6134             if (touchBounds.contains((int) x, (int) y)) {
   6135                 return true;
   6136             }
   6137         }
   6138         return false;
   6139     }
   6140 
   6141     boolean isOnScrollbarThumb(float x, float y) {
   6142         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
   6143     }
   6144 
   6145     private boolean isOnVerticalScrollbarThumb(float x, float y) {
   6146         if (mScrollCache == null) {
   6147             return false;
   6148         }
   6149         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
   6150             x += getScrollX();
   6151             y += getScrollY();
   6152             final Rect bounds = mScrollCache.mScrollBarBounds;
   6153             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
   6154             getVerticalScrollBarBounds(bounds, touchBounds);
   6155             final int range = computeVerticalScrollRange();
   6156             final int offset = computeVerticalScrollOffset();
   6157             final int extent = computeVerticalScrollExtent();
   6158             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
   6159                     extent, range);
   6160             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
   6161                     extent, range, offset);
   6162             final int thumbTop = bounds.top + thumbOffset;
   6163             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
   6164             if (x >= touchBounds.left && x <= touchBounds.right
   6165                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
   6166                 return true;
   6167             }
   6168         }
   6169         return false;
   6170     }
   6171 
   6172     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
   6173         if (mScrollCache == null) {
   6174             return false;
   6175         }
   6176         if (isHorizontalScrollBarEnabled()) {
   6177             x += getScrollX();
   6178             y += getScrollY();
   6179             final Rect bounds = mScrollCache.mScrollBarBounds;
   6180             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
   6181             getHorizontalScrollBarBounds(bounds, touchBounds);
   6182             final int range = computeHorizontalScrollRange();
   6183             final int offset = computeHorizontalScrollOffset();
   6184             final int extent = computeHorizontalScrollExtent();
   6185             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
   6186                     extent, range);
   6187             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
   6188                     extent, range, offset);
   6189             final int thumbLeft = bounds.left + thumbOffset;
   6190             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
   6191             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
   6192                     && y >= touchBounds.top && y <= touchBounds.bottom) {
   6193                 return true;
   6194             }
   6195         }
   6196         return false;
   6197     }
   6198 
   6199     boolean isDraggingScrollBar() {
   6200         return mScrollCache != null
   6201                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
   6202     }
   6203 
   6204     /**
   6205      * Sets the state of all scroll indicators.
   6206      * <p>
   6207      * See {@link #setScrollIndicators(int, int)} for usage information.
   6208      *
   6209      * @param indicators a bitmask of indicators that should be enabled, or
   6210      *                   {@code 0} to disable all indicators
   6211      * @see #setScrollIndicators(int, int)
   6212      * @see #getScrollIndicators()
   6213      * @attr ref android.R.styleable#View_scrollIndicators
   6214      */
   6215     public void setScrollIndicators(@ScrollIndicators int indicators) {
   6216         setScrollIndicators(indicators,
   6217                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
   6218     }
   6219 
   6220     /**
   6221      * Sets the state of the scroll indicators specified by the mask. To change
   6222      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
   6223      * <p>
   6224      * When a scroll indicator is enabled, it will be displayed if the view
   6225      * can scroll in the direction of the indicator.
   6226      * <p>
   6227      * Multiple indicator types may be enabled or disabled by passing the
   6228      * logical OR of the desired types. If multiple types are specified, they
   6229      * will all be set to the same enabled state.
   6230      * <p>
   6231      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
   6232      *
   6233      * @param indicators the indicator direction, or the logical OR of multiple
   6234      *             indicator directions. One or more of:
   6235      *             <ul>
   6236      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
   6237      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
   6238      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
   6239      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
   6240      *               <li>{@link #SCROLL_INDICATOR_START}</li>
   6241      *               <li>{@link #SCROLL_INDICATOR_END}</li>
   6242      *             </ul>
   6243      * @see #setScrollIndicators(int)
   6244      * @see #getScrollIndicators()
   6245      * @attr ref android.R.styleable#View_scrollIndicators
   6246      */
   6247     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
   6248         // Shift and sanitize mask.
   6249         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   6250         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
   6251 
   6252         // Shift and mask indicators.
   6253         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   6254         indicators &= mask;
   6255 
   6256         // Merge with non-masked flags.
   6257         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
   6258 
   6259         if (mPrivateFlags3 != updatedFlags) {
   6260             mPrivateFlags3 = updatedFlags;
   6261 
   6262             if (indicators != 0) {
   6263                 initializeScrollIndicatorsInternal();
   6264             }
   6265             invalidate();
   6266         }
   6267     }
   6268 
   6269     /**
   6270      * Returns a bitmask representing the enabled scroll indicators.
   6271      * <p>
   6272      * For example, if the top and left scroll indicators are enabled and all
   6273      * other indicators are disabled, the return value will be
   6274      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
   6275      * <p>
   6276      * To check whether the bottom scroll indicator is enabled, use the value
   6277      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
   6278      *
   6279      * @return a bitmask representing the enabled scroll indicators
   6280      */
   6281     @ScrollIndicators
   6282     public int getScrollIndicators() {
   6283         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
   6284                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   6285     }
   6286 
   6287     ListenerInfo getListenerInfo() {
   6288         if (mListenerInfo != null) {
   6289             return mListenerInfo;
   6290         }
   6291         mListenerInfo = new ListenerInfo();
   6292         return mListenerInfo;
   6293     }
   6294 
   6295     /**
   6296      * Register a callback to be invoked when the scroll X or Y positions of
   6297      * this view change.
   6298      * <p>
   6299      * <b>Note:</b> Some views handle scrolling independently from View and may
   6300      * have their own separate listeners for scroll-type events. For example,
   6301      * {@link android.widget.ListView ListView} allows clients to register an
   6302      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   6303      * to listen for changes in list scroll position.
   6304      *
   6305      * @param l The listener to notify when the scroll X or Y position changes.
   6306      * @see android.view.View#getScrollX()
   6307      * @see android.view.View#getScrollY()
   6308      */
   6309     public void setOnScrollChangeListener(OnScrollChangeListener l) {
   6310         getListenerInfo().mOnScrollChangeListener = l;
   6311     }
   6312 
   6313     /**
   6314      * Register a callback to be invoked when focus of this view changed.
   6315      *
   6316      * @param l The callback that will run.
   6317      */
   6318     public void setOnFocusChangeListener(OnFocusChangeListener l) {
   6319         getListenerInfo().mOnFocusChangeListener = l;
   6320     }
   6321 
   6322     /**
   6323      * Add a listener that will be called when the bounds of the view change due to
   6324      * layout processing.
   6325      *
   6326      * @param listener The listener that will be called when layout bounds change.
   6327      */
   6328     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
   6329         ListenerInfo li = getListenerInfo();
   6330         if (li.mOnLayoutChangeListeners == null) {
   6331             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
   6332         }
   6333         if (!li.mOnLayoutChangeListeners.contains(listener)) {
   6334             li.mOnLayoutChangeListeners.add(listener);
   6335         }
   6336     }
   6337 
   6338     /**
   6339      * Remove a listener for layout changes.
   6340      *
   6341      * @param listener The listener for layout bounds change.
   6342      */
   6343     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
   6344         ListenerInfo li = mListenerInfo;
   6345         if (li == null || li.mOnLayoutChangeListeners == null) {
   6346             return;
   6347         }
   6348         li.mOnLayoutChangeListeners.remove(listener);
   6349     }
   6350 
   6351     /**
   6352      * Add a listener for attach state changes.
   6353      *
   6354      * This listener will be called whenever this view is attached or detached
   6355      * from a window. Remove the listener using
   6356      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
   6357      *
   6358      * @param listener Listener to attach
   6359      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
   6360      */
   6361     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   6362         ListenerInfo li = getListenerInfo();
   6363         if (li.mOnAttachStateChangeListeners == null) {
   6364             li.mOnAttachStateChangeListeners
   6365                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
   6366         }
   6367         li.mOnAttachStateChangeListeners.add(listener);
   6368     }
   6369 
   6370     /**
   6371      * Remove a listener for attach state changes. The listener will receive no further
   6372      * notification of window attach/detach events.
   6373      *
   6374      * @param listener Listener to remove
   6375      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
   6376      */
   6377     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   6378         ListenerInfo li = mListenerInfo;
   6379         if (li == null || li.mOnAttachStateChangeListeners == null) {
   6380             return;
   6381         }
   6382         li.mOnAttachStateChangeListeners.remove(listener);
   6383     }
   6384 
   6385     /**
   6386      * Returns the focus-change callback registered for this view.
   6387      *
   6388      * @return The callback, or null if one is not registered.
   6389      */
   6390     public OnFocusChangeListener getOnFocusChangeListener() {
   6391         ListenerInfo li = mListenerInfo;
   6392         return li != null ? li.mOnFocusChangeListener : null;
   6393     }
   6394 
   6395     /**
   6396      * Register a callback to be invoked when this view is clicked. If this view is not
   6397      * clickable, it becomes clickable.
   6398      *
   6399      * @param l The callback that will run
   6400      *
   6401      * @see #setClickable(boolean)
   6402      */
   6403     public void setOnClickListener(@Nullable OnClickListener l) {
   6404         if (!isClickable()) {
   6405             setClickable(true);
   6406         }
   6407         getListenerInfo().mOnClickListener = l;
   6408     }
   6409 
   6410     /**
   6411      * Return whether this view has an attached OnClickListener.  Returns
   6412      * true if there is a listener, false if there is none.
   6413      */
   6414     public boolean hasOnClickListeners() {
   6415         ListenerInfo li = mListenerInfo;
   6416         return (li != null && li.mOnClickListener != null);
   6417     }
   6418 
   6419     /**
   6420      * Register a callback to be invoked when this view is clicked and held. If this view is not
   6421      * long clickable, it becomes long clickable.
   6422      *
   6423      * @param l The callback that will run
   6424      *
   6425      * @see #setLongClickable(boolean)
   6426      */
   6427     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
   6428         if (!isLongClickable()) {
   6429             setLongClickable(true);
   6430         }
   6431         getListenerInfo().mOnLongClickListener = l;
   6432     }
   6433 
   6434     /**
   6435      * Register a callback to be invoked when this view is context clicked. If the view is not
   6436      * context clickable, it becomes context clickable.
   6437      *
   6438      * @param l The callback that will run
   6439      * @see #setContextClickable(boolean)
   6440      */
   6441     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
   6442         if (!isContextClickable()) {
   6443             setContextClickable(true);
   6444         }
   6445         getListenerInfo().mOnContextClickListener = l;
   6446     }
   6447 
   6448     /**
   6449      * Register a callback to be invoked when the context menu for this view is
   6450      * being built. If this view is not long clickable, it becomes long clickable.
   6451      *
   6452      * @param l The callback that will run
   6453      *
   6454      */
   6455     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
   6456         if (!isLongClickable()) {
   6457             setLongClickable(true);
   6458         }
   6459         getListenerInfo().mOnCreateContextMenuListener = l;
   6460     }
   6461 
   6462     /**
   6463      * Set an observer to collect stats for each frame rendered for this view.
   6464      *
   6465      * @hide
   6466      */
   6467     public void addFrameMetricsListener(Window window,
   6468             Window.OnFrameMetricsAvailableListener listener,
   6469             Handler handler) {
   6470         if (mAttachInfo != null) {
   6471             if (mAttachInfo.mThreadedRenderer != null) {
   6472                 if (mFrameMetricsObservers == null) {
   6473                     mFrameMetricsObservers = new ArrayList<>();
   6474                 }
   6475 
   6476                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
   6477                         handler.getLooper(), listener);
   6478                 mFrameMetricsObservers.add(fmo);
   6479                 mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
   6480             } else {
   6481                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
   6482             }
   6483         } else {
   6484             if (mFrameMetricsObservers == null) {
   6485                 mFrameMetricsObservers = new ArrayList<>();
   6486             }
   6487 
   6488             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
   6489                     handler.getLooper(), listener);
   6490             mFrameMetricsObservers.add(fmo);
   6491         }
   6492     }
   6493 
   6494     /**
   6495      * Remove observer configured to collect frame stats for this view.
   6496      *
   6497      * @hide
   6498      */
   6499     public void removeFrameMetricsListener(
   6500             Window.OnFrameMetricsAvailableListener listener) {
   6501         ThreadedRenderer renderer = getThreadedRenderer();
   6502         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
   6503         if (fmo == null) {
   6504             throw new IllegalArgumentException(
   6505                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
   6506         }
   6507 
   6508         if (mFrameMetricsObservers != null) {
   6509             mFrameMetricsObservers.remove(fmo);
   6510             if (renderer != null) {
   6511                 renderer.removeFrameMetricsObserver(fmo);
   6512             }
   6513         }
   6514     }
   6515 
   6516     private void registerPendingFrameMetricsObservers() {
   6517         if (mFrameMetricsObservers != null) {
   6518             ThreadedRenderer renderer = getThreadedRenderer();
   6519             if (renderer != null) {
   6520                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
   6521                     renderer.addFrameMetricsObserver(fmo);
   6522                 }
   6523             } else {
   6524                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
   6525             }
   6526         }
   6527     }
   6528 
   6529     private FrameMetricsObserver findFrameMetricsObserver(
   6530             Window.OnFrameMetricsAvailableListener listener) {
   6531         for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
   6532             FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
   6533             if (observer.mListener == listener) {
   6534                 return observer;
   6535             }
   6536         }
   6537 
   6538         return null;
   6539     }
   6540 
   6541     /** @hide */
   6542     public void setNotifyAutofillManagerOnClick(boolean notify) {
   6543         if (notify) {
   6544             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
   6545         } else {
   6546             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
   6547         }
   6548     }
   6549 
   6550     private void notifyAutofillManagerOnClick() {
   6551         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
   6552             try {
   6553                 getAutofillManager().notifyViewClicked(this);
   6554             } finally {
   6555                 // Set it to already called so it's not called twice when called by
   6556                 // performClickInternal()
   6557                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
   6558             }
   6559         }
   6560     }
   6561 
   6562     /**
   6563      * Entry point for {@link #performClick()} - other methods on View should call it instead of
   6564      * {@code performClick()} directly to make sure the autofill manager is notified when
   6565      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
   6566      * method).
   6567      */
   6568     private boolean performClickInternal() {
   6569         // Must notify autofill manager before performing the click actions to avoid scenarios where
   6570         // the app has a click listener that changes the state of views the autofill service might
   6571         // be interested on.
   6572         notifyAutofillManagerOnClick();
   6573 
   6574         return performClick();
   6575     }
   6576 
   6577     /**
   6578      * Call this view's OnClickListener, if it is defined.  Performs all normal
   6579      * actions associated with clicking: reporting accessibility event, playing
   6580      * a sound, etc.
   6581      *
   6582      * @return True there was an assigned OnClickListener that was called, false
   6583      *         otherwise is returned.
   6584      */
   6585     // NOTE: other methods on View should not call this method directly, but performClickInternal()
   6586     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
   6587     // could extend this method without calling super.performClick()).
   6588     public boolean performClick() {
   6589         // We still need to call this method to handle the cases where performClick() was called
   6590         // externally, instead of through performClickInternal()
   6591         notifyAutofillManagerOnClick();
   6592 
   6593         final boolean result;
   6594         final ListenerInfo li = mListenerInfo;
   6595         if (li != null && li.mOnClickListener != null) {
   6596             playSoundEffect(SoundEffectConstants.CLICK);
   6597             li.mOnClickListener.onClick(this);
   6598             result = true;
   6599         } else {
   6600             result = false;
   6601         }
   6602 
   6603         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
   6604 
   6605         notifyEnterOrExitForAutoFillIfNeeded(true);
   6606 
   6607         return result;
   6608     }
   6609 
   6610     /**
   6611      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
   6612      * this only calls the listener, and does not do any associated clicking
   6613      * actions like reporting an accessibility event.
   6614      *
   6615      * @return True there was an assigned OnClickListener that was called, false
   6616      *         otherwise is returned.
   6617      */
   6618     public boolean callOnClick() {
   6619         ListenerInfo li = mListenerInfo;
   6620         if (li != null && li.mOnClickListener != null) {
   6621             li.mOnClickListener.onClick(this);
   6622             return true;
   6623         }
   6624         return false;
   6625     }
   6626 
   6627     /**
   6628      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   6629      * context menu if the OnLongClickListener did not consume the event.
   6630      *
   6631      * @return {@code true} if one of the above receivers consumed the event,
   6632      *         {@code false} otherwise
   6633      */
   6634     public boolean performLongClick() {
   6635         return performLongClickInternal(mLongClickX, mLongClickY);
   6636     }
   6637 
   6638     /**
   6639      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   6640      * context menu if the OnLongClickListener did not consume the event,
   6641      * anchoring it to an (x,y) coordinate.
   6642      *
   6643      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
   6644      *          to disable anchoring
   6645      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
   6646      *          to disable anchoring
   6647      * @return {@code true} if one of the above receivers consumed the event,
   6648      *         {@code false} otherwise
   6649      */
   6650     public boolean performLongClick(float x, float y) {
   6651         mLongClickX = x;
   6652         mLongClickY = y;
   6653         final boolean handled = performLongClick();
   6654         mLongClickX = Float.NaN;
   6655         mLongClickY = Float.NaN;
   6656         return handled;
   6657     }
   6658 
   6659     /**
   6660      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   6661      * context menu if the OnLongClickListener did not consume the event,
   6662      * optionally anchoring it to an (x,y) coordinate.
   6663      *
   6664      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
   6665      *          to disable anchoring
   6666      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
   6667      *          to disable anchoring
   6668      * @return {@code true} if one of the above receivers consumed the event,
   6669      *         {@code false} otherwise
   6670      */
   6671     private boolean performLongClickInternal(float x, float y) {
   6672         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
   6673 
   6674         boolean handled = false;
   6675         final ListenerInfo li = mListenerInfo;
   6676         if (li != null && li.mOnLongClickListener != null) {
   6677             handled = li.mOnLongClickListener.onLongClick(View.this);
   6678         }
   6679         if (!handled) {
   6680             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
   6681             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
   6682         }
   6683         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
   6684             if (!handled) {
   6685                 handled = showLongClickTooltip((int) x, (int) y);
   6686             }
   6687         }
   6688         if (handled) {
   6689             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
   6690         }
   6691         return handled;
   6692     }
   6693 
   6694     /**
   6695      * Call this view's OnContextClickListener, if it is defined.
   6696      *
   6697      * @param x the x coordinate of the context click
   6698      * @param y the y coordinate of the context click
   6699      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   6700      *         otherwise.
   6701      */
   6702     public boolean performContextClick(float x, float y) {
   6703         return performContextClick();
   6704     }
   6705 
   6706     /**
   6707      * Call this view's OnContextClickListener, if it is defined.
   6708      *
   6709      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   6710      *         otherwise.
   6711      */
   6712     public boolean performContextClick() {
   6713         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
   6714 
   6715         boolean handled = false;
   6716         ListenerInfo li = mListenerInfo;
   6717         if (li != null && li.mOnContextClickListener != null) {
   6718             handled = li.mOnContextClickListener.onContextClick(View.this);
   6719         }
   6720         if (handled) {
   6721             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
   6722         }
   6723         return handled;
   6724     }
   6725 
   6726     /**
   6727      * Performs button-related actions during a touch down event.
   6728      *
   6729      * @param event The event.
   6730      * @return True if the down was consumed.
   6731      *
   6732      * @hide
   6733      */
   6734     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
   6735         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
   6736             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
   6737             showContextMenu(event.getX(), event.getY());
   6738             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   6739             return true;
   6740         }
   6741         return false;
   6742     }
   6743 
   6744     /**
   6745      * Shows the context menu for this view.
   6746      *
   6747      * @return {@code true} if the context menu was shown, {@code false}
   6748      *         otherwise
   6749      * @see #showContextMenu(float, float)
   6750      */
   6751     public boolean showContextMenu() {
   6752         return getParent().showContextMenuForChild(this);
   6753     }
   6754 
   6755     /**
   6756      * Shows the context menu for this view anchored to the specified
   6757      * view-relative coordinate.
   6758      *
   6759      * @param x the X coordinate in pixels relative to the view to which the
   6760      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
   6761      * @param y the Y coordinate in pixels relative to the view to which the
   6762      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
   6763      * @return {@code true} if the context menu was shown, {@code false}
   6764      *         otherwise
   6765      */
   6766     public boolean showContextMenu(float x, float y) {
   6767         return getParent().showContextMenuForChild(this, x, y);
   6768     }
   6769 
   6770     /**
   6771      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
   6772      *
   6773      * @param callback Callback that will control the lifecycle of the action mode
   6774      * @return The new action mode if it is started, null otherwise
   6775      *
   6776      * @see ActionMode
   6777      * @see #startActionMode(android.view.ActionMode.Callback, int)
   6778      */
   6779     public ActionMode startActionMode(ActionMode.Callback callback) {
   6780         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
   6781     }
   6782 
   6783     /**
   6784      * Start an action mode with the given type.
   6785      *
   6786      * @param callback Callback that will control the lifecycle of the action mode
   6787      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
   6788      * @return The new action mode if it is started, null otherwise
   6789      *
   6790      * @see ActionMode
   6791      */
   6792     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
   6793         ViewParent parent = getParent();
   6794         if (parent == null) return null;
   6795         try {
   6796             return parent.startActionModeForChild(this, callback, type);
   6797         } catch (AbstractMethodError ame) {
   6798             // Older implementations of custom views might not implement this.
   6799             return parent.startActionModeForChild(this, callback);
   6800         }
   6801     }
   6802 
   6803     /**
   6804      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
   6805      * Context, creating a unique View identifier to retrieve the result.
   6806      *
   6807      * @param intent The Intent to be started.
   6808      * @param requestCode The request code to use.
   6809      * @hide
   6810      */
   6811     public void startActivityForResult(Intent intent, int requestCode) {
   6812         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
   6813         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
   6814     }
   6815 
   6816     /**
   6817      * If this View corresponds to the calling who, dispatches the activity result.
   6818      * @param who The identifier for the targeted View to receive the result.
   6819      * @param requestCode The integer request code originally supplied to
   6820      *                    startActivityForResult(), allowing you to identify who this
   6821      *                    result came from.
   6822      * @param resultCode The integer result code returned by the child activity
   6823      *                   through its setResult().
   6824      * @param data An Intent, which can return result data to the caller
   6825      *               (various data can be attached to Intent "extras").
   6826      * @return {@code true} if the activity result was dispatched.
   6827      * @hide
   6828      */
   6829     public boolean dispatchActivityResult(
   6830             String who, int requestCode, int resultCode, Intent data) {
   6831         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
   6832             onActivityResult(requestCode, resultCode, data);
   6833             mStartActivityRequestWho = null;
   6834             return true;
   6835         }
   6836         return false;
   6837     }
   6838 
   6839     /**
   6840      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
   6841      *
   6842      * @param requestCode The integer request code originally supplied to
   6843      *                    startActivityForResult(), allowing you to identify who this
   6844      *                    result came from.
   6845      * @param resultCode The integer result code returned by the child activity
   6846      *                   through its setResult().
   6847      * @param data An Intent, which can return result data to the caller
   6848      *               (various data can be attached to Intent "extras").
   6849      * @hide
   6850      */
   6851     public void onActivityResult(int requestCode, int resultCode, Intent data) {
   6852         // Do nothing.
   6853     }
   6854 
   6855     /**
   6856      * Register a callback to be invoked when a hardware key is pressed in this view.
   6857      * Key presses in software input methods will generally not trigger the methods of
   6858      * this listener.
   6859      * @param l the key listener to attach to this view
   6860      */
   6861     public void setOnKeyListener(OnKeyListener l) {
   6862         getListenerInfo().mOnKeyListener = l;
   6863     }
   6864 
   6865     /**
   6866      * Register a callback to be invoked when a touch event is sent to this view.
   6867      * @param l the touch listener to attach to this view
   6868      */
   6869     public void setOnTouchListener(OnTouchListener l) {
   6870         getListenerInfo().mOnTouchListener = l;
   6871     }
   6872 
   6873     /**
   6874      * Register a callback to be invoked when a generic motion event is sent to this view.
   6875      * @param l the generic motion listener to attach to this view
   6876      */
   6877     public void setOnGenericMotionListener(OnGenericMotionListener l) {
   6878         getListenerInfo().mOnGenericMotionListener = l;
   6879     }
   6880 
   6881     /**
   6882      * Register a callback to be invoked when a hover event is sent to this view.
   6883      * @param l the hover listener to attach to this view
   6884      */
   6885     public void setOnHoverListener(OnHoverListener l) {
   6886         getListenerInfo().mOnHoverListener = l;
   6887     }
   6888 
   6889     /**
   6890      * Register a drag event listener callback object for this View. The parameter is
   6891      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
   6892      * View, the system calls the
   6893      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
   6894      * @param l An implementation of {@link android.view.View.OnDragListener}.
   6895      */
   6896     public void setOnDragListener(OnDragListener l) {
   6897         getListenerInfo().mOnDragListener = l;
   6898     }
   6899 
   6900     /**
   6901      * Give this view focus. This will cause
   6902      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
   6903      *
   6904      * Note: this does not check whether this {@link View} should get focus, it just
   6905      * gives it focus no matter what.  It should only be called internally by framework
   6906      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
   6907      *
   6908      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
   6909      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
   6910      *        focus moved when requestFocus() is called. It may not always
   6911      *        apply, in which case use the default View.FOCUS_DOWN.
   6912      * @param previouslyFocusedRect The rectangle of the view that had focus
   6913      *        prior in this View's coordinate system.
   6914      */
   6915     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
   6916         if (DBG) {
   6917             System.out.println(this + " requestFocus()");
   6918         }
   6919 
   6920         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
   6921             mPrivateFlags |= PFLAG_FOCUSED;
   6922 
   6923             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
   6924 
   6925             if (mParent != null) {
   6926                 mParent.requestChildFocus(this, this);
   6927                 updateFocusedInCluster(oldFocus, direction);
   6928             }
   6929 
   6930             if (mAttachInfo != null) {
   6931                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
   6932             }
   6933 
   6934             onFocusChanged(true, direction, previouslyFocusedRect);
   6935             refreshDrawableState();
   6936         }
   6937     }
   6938 
   6939     /**
   6940      * Sets this view's preference for reveal behavior when it gains focus.
   6941      *
   6942      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
   6943      * this view would prefer to be brought fully into view when it gains focus.
   6944      * For example, a text field that a user is meant to type into. Other views such
   6945      * as scrolling containers may prefer to opt-out of this behavior.</p>
   6946      *
   6947      * <p>The default value for views is true, though subclasses may change this
   6948      * based on their preferred behavior.</p>
   6949      *
   6950      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
   6951      *
   6952      * @see #getRevealOnFocusHint()
   6953      */
   6954     public final void setRevealOnFocusHint(boolean revealOnFocus) {
   6955         if (revealOnFocus) {
   6956             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
   6957         } else {
   6958             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
   6959         }
   6960     }
   6961 
   6962     /**
   6963      * Returns this view's preference for reveal behavior when it gains focus.
   6964      *
   6965      * <p>When this method returns true for a child view requesting focus, ancestor
   6966      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
   6967      * should make a best effort to make the newly focused child fully visible to the user.
   6968      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
   6969      * other properties affecting visibility to the user as part of the focus change.</p>
   6970      *
   6971      * @return true if this view would prefer to become fully visible when it gains focus,
   6972      *         false if it would prefer not to disrupt scroll positioning
   6973      *
   6974      * @see #setRevealOnFocusHint(boolean)
   6975      */
   6976     public final boolean getRevealOnFocusHint() {
   6977         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
   6978     }
   6979 
   6980     /**
   6981      * Populates <code>outRect</code> with the hotspot bounds. By default,
   6982      * the hotspot bounds are identical to the screen bounds.
   6983      *
   6984      * @param outRect rect to populate with hotspot bounds
   6985      * @hide Only for internal use by views and widgets.
   6986      */
   6987     public void getHotspotBounds(Rect outRect) {
   6988         final Drawable background = getBackground();
   6989         if (background != null) {
   6990             background.getHotspotBounds(outRect);
   6991         } else {
   6992             getBoundsOnScreen(outRect);
   6993         }
   6994     }
   6995 
   6996     /**
   6997      * Request that a rectangle of this view be visible on the screen,
   6998      * scrolling if necessary just enough.
   6999      *
   7000      * <p>A View should call this if it maintains some notion of which part
   7001      * of its content is interesting.  For example, a text editing view
   7002      * should call this when its cursor moves.
   7003      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
   7004      * It should not be affected by which part of the View is currently visible or its scroll
   7005      * position.
   7006      *
   7007      * @param rectangle The rectangle in the View's content coordinate space
   7008      * @return Whether any parent scrolled.
   7009      */
   7010     public boolean requestRectangleOnScreen(Rect rectangle) {
   7011         return requestRectangleOnScreen(rectangle, false);
   7012     }
   7013 
   7014     /**
   7015      * Request that a rectangle of this view be visible on the screen,
   7016      * scrolling if necessary just enough.
   7017      *
   7018      * <p>A View should call this if it maintains some notion of which part
   7019      * of its content is interesting.  For example, a text editing view
   7020      * should call this when its cursor moves.
   7021      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
   7022      * It should not be affected by which part of the View is currently visible or its scroll
   7023      * position.
   7024      * <p>When <code>immediate</code> is set to true, scrolling will not be
   7025      * animated.
   7026      *
   7027      * @param rectangle The rectangle in the View's content coordinate space
   7028      * @param immediate True to forbid animated scrolling, false otherwise
   7029      * @return Whether any parent scrolled.
   7030      */
   7031     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
   7032         if (mParent == null) {
   7033             return false;
   7034         }
   7035 
   7036         View child = this;
   7037 
   7038         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
   7039         position.set(rectangle);
   7040 
   7041         ViewParent parent = mParent;
   7042         boolean scrolled = false;
   7043         while (parent != null) {
   7044             rectangle.set((int) position.left, (int) position.top,
   7045                     (int) position.right, (int) position.bottom);
   7046 
   7047             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
   7048 
   7049             if (!(parent instanceof View)) {
   7050                 break;
   7051             }
   7052 
   7053             // move it from child's content coordinate space to parent's content coordinate space
   7054             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
   7055 
   7056             child = (View) parent;
   7057             parent = child.getParent();
   7058         }
   7059 
   7060         return scrolled;
   7061     }
   7062 
   7063     /**
   7064      * Called when this view wants to give up focus. If focus is cleared
   7065      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
   7066      * <p>
   7067      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
   7068      * to the first focusable View from the top after focus is cleared. Hence, if this
   7069      * View is the first from the top that can take focus, then all callbacks
   7070      * related to clearing focus will be invoked after which the framework will
   7071      * give focus to this view.
   7072      * </p>
   7073      */
   7074     public void clearFocus() {
   7075         if (DBG) {
   7076             System.out.println(this + " clearFocus()");
   7077         }
   7078 
   7079         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
   7080         clearFocusInternal(null, true, refocus);
   7081     }
   7082 
   7083     /**
   7084      * Clears focus from the view, optionally propagating the change up through
   7085      * the parent hierarchy and requesting that the root view place new focus.
   7086      *
   7087      * @param propagate whether to propagate the change up through the parent
   7088      *            hierarchy
   7089      * @param refocus when propagate is true, specifies whether to request the
   7090      *            root view place new focus
   7091      */
   7092     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
   7093         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   7094             mPrivateFlags &= ~PFLAG_FOCUSED;
   7095             clearParentsWantFocus();
   7096 
   7097             if (propagate && mParent != null) {
   7098                 mParent.clearChildFocus(this);
   7099             }
   7100 
   7101             onFocusChanged(false, 0, null);
   7102             refreshDrawableState();
   7103 
   7104             if (propagate && (!refocus || !rootViewRequestFocus())) {
   7105                 notifyGlobalFocusCleared(this);
   7106             }
   7107         }
   7108     }
   7109 
   7110     void notifyGlobalFocusCleared(View oldFocus) {
   7111         if (oldFocus != null && mAttachInfo != null) {
   7112             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
   7113         }
   7114     }
   7115 
   7116     boolean rootViewRequestFocus() {
   7117         final View root = getRootView();
   7118         return root != null && root.requestFocus();
   7119     }
   7120 
   7121     /**
   7122      * Called internally by the view system when a new view is getting focus.
   7123      * This is what clears the old focus.
   7124      * <p>
   7125      * <b>NOTE:</b> The parent view's focused child must be updated manually
   7126      * after calling this method. Otherwise, the view hierarchy may be left in
   7127      * an inconstent state.
   7128      */
   7129     void unFocus(View focused) {
   7130         if (DBG) {
   7131             System.out.println(this + " unFocus()");
   7132         }
   7133 
   7134         clearFocusInternal(focused, false, false);
   7135     }
   7136 
   7137     /**
   7138      * Returns true if this view has focus itself, or is the ancestor of the
   7139      * view that has focus.
   7140      *
   7141      * @return True if this view has or contains focus, false otherwise.
   7142      */
   7143     @ViewDebug.ExportedProperty(category = "focus")
   7144     public boolean hasFocus() {
   7145         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   7146     }
   7147 
   7148     /**
   7149      * Returns true if this view is focusable or if it contains a reachable View
   7150      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
   7151      * is a view whose parents do not block descendants focus.
   7152      * Only {@link #VISIBLE} views are considered focusable.
   7153      *
   7154      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
   7155      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
   7156      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
   7157      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
   7158      * {@code false} for views not explicitly marked as focusable.
   7159      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
   7160      * behavior.</p>
   7161      *
   7162      * @return {@code true} if the view is focusable or if the view contains a focusable
   7163      *         view, {@code false} otherwise
   7164      *
   7165      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
   7166      * @see ViewGroup#getTouchscreenBlocksFocus()
   7167      * @see #hasExplicitFocusable()
   7168      */
   7169     public boolean hasFocusable() {
   7170         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
   7171     }
   7172 
   7173     /**
   7174      * Returns true if this view is focusable or if it contains a reachable View
   7175      * for which {@link #hasExplicitFocusable()} returns {@code true}.
   7176      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
   7177      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
   7178      * {@link #FOCUSABLE} are considered focusable.
   7179      *
   7180      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
   7181      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
   7182      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
   7183      * to focusable will not.</p>
   7184      *
   7185      * @return {@code true} if the view is focusable or if the view contains a focusable
   7186      *         view, {@code false} otherwise
   7187      *
   7188      * @see #hasFocusable()
   7189      */
   7190     public boolean hasExplicitFocusable() {
   7191         return hasFocusable(false, true);
   7192     }
   7193 
   7194     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
   7195         if (!isFocusableInTouchMode()) {
   7196             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
   7197                 final ViewGroup g = (ViewGroup) p;
   7198                 if (g.shouldBlockFocusForTouchscreen()) {
   7199                     return false;
   7200                 }
   7201             }
   7202         }
   7203 
   7204         // Invisible, gone, or disabled views are never focusable.
   7205         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
   7206                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
   7207             return false;
   7208         }
   7209 
   7210         // Only use effective focusable value when allowed.
   7211         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
   7212             return true;
   7213         }
   7214 
   7215         return false;
   7216     }
   7217 
   7218     /**
   7219      * Called by the view system when the focus state of this view changes.
   7220      * When the focus change event is caused by directional navigation, direction
   7221      * and previouslyFocusedRect provide insight into where the focus is coming from.
   7222      * When overriding, be sure to call up through to the super class so that
   7223      * the standard focus handling will occur.
   7224      *
   7225      * @param gainFocus True if the View has focus; false otherwise.
   7226      * @param direction The direction focus has moved when requestFocus()
   7227      *                  is called to give this view focus. Values are
   7228      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
   7229      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
   7230      *                  It may not always apply, in which case use the default.
   7231      * @param previouslyFocusedRect The rectangle, in this view's coordinate
   7232      *        system, of the previously focused view.  If applicable, this will be
   7233      *        passed in as finer grained information about where the focus is coming
   7234      *        from (in addition to direction).  Will be <code>null</code> otherwise.
   7235      */
   7236     @CallSuper
   7237     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
   7238             @Nullable Rect previouslyFocusedRect) {
   7239         if (gainFocus) {
   7240             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
   7241         } else {
   7242             notifyViewAccessibilityStateChangedIfNeeded(
   7243                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   7244         }
   7245 
   7246         // Here we check whether we still need the default focus highlight, and switch it on/off.
   7247         switchDefaultFocusHighlight();
   7248 
   7249         InputMethodManager imm = InputMethodManager.peekInstance();
   7250         if (!gainFocus) {
   7251             if (isPressed()) {
   7252                 setPressed(false);
   7253             }
   7254             if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
   7255                 imm.focusOut(this);
   7256             }
   7257             onFocusLost();
   7258         } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
   7259             imm.focusIn(this);
   7260         }
   7261 
   7262         invalidate(true);
   7263         ListenerInfo li = mListenerInfo;
   7264         if (li != null && li.mOnFocusChangeListener != null) {
   7265             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
   7266         }
   7267 
   7268         if (mAttachInfo != null) {
   7269             mAttachInfo.mKeyDispatchState.reset(this);
   7270         }
   7271 
   7272         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
   7273     }
   7274 
   7275     /** @hide */
   7276     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
   7277         if (canNotifyAutofillEnterExitEvent()) {
   7278             AutofillManager afm = getAutofillManager();
   7279             if (afm != null) {
   7280                 if (enter && isFocused()) {
   7281                     // We have not been laid out yet, hence cannot evaluate
   7282                     // whether this view is visible to the user, we will do
   7283                     // the evaluation once layout is complete.
   7284                     if (!isLaidOut()) {
   7285                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
   7286                     } else if (isVisibleToUser()) {
   7287                         // TODO This is a potential problem that View gets focus before it's visible
   7288                         // to User. Ideally View should handle the event when isVisibleToUser()
   7289                         // becomes true where it should issue notifyViewEntered().
   7290                         afm.notifyViewEntered(this);
   7291                     }
   7292                 } else if (!enter && !isFocused()) {
   7293                     afm.notifyViewExited(this);
   7294                 }
   7295             }
   7296         }
   7297     }
   7298 
   7299     /**
   7300      * Visually distinct portion of a window with window-like semantics are considered panes for
   7301      * accessibility purposes. One example is the content view of a fragment that is replaced.
   7302      * In order for accessibility services to understand a pane's window-like behavior, panes
   7303      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
   7304      * when they appear, disappear, or change title.
   7305      *
   7306      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
   7307      *                               View is not a pane.
   7308      *
   7309      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
   7310      */
   7311     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
   7312         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
   7313             mAccessibilityPaneTitle = accessibilityPaneTitle;
   7314             notifyViewAccessibilityStateChangedIfNeeded(
   7315                     AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
   7316         }
   7317     }
   7318 
   7319     /**
   7320      * Get the title of the pane for purposes of accessibility.
   7321      *
   7322      * @return The current pane title.
   7323      *
   7324      * {@see #setAccessibilityPaneTitle}.
   7325      */
   7326     @Nullable public CharSequence getAccessibilityPaneTitle() {
   7327         return mAccessibilityPaneTitle;
   7328     }
   7329 
   7330     private boolean isAccessibilityPane() {
   7331         return mAccessibilityPaneTitle != null;
   7332     }
   7333 
   7334     /**
   7335      * Sends an accessibility event of the given type. If accessibility is
   7336      * not enabled this method has no effect. The default implementation calls
   7337      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
   7338      * to populate information about the event source (this View), then calls
   7339      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
   7340      * populate the text content of the event source including its descendants,
   7341      * and last calls
   7342      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
   7343      * on its parent to request sending of the event to interested parties.
   7344      * <p>
   7345      * If an {@link AccessibilityDelegate} has been specified via calling
   7346      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7347      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
   7348      * responsible for handling this call.
   7349      * </p>
   7350      *
   7351      * @param eventType The type of the event to send, as defined by several types from
   7352      * {@link android.view.accessibility.AccessibilityEvent}, such as
   7353      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
   7354      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
   7355      *
   7356      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   7357      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   7358      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
   7359      * @see AccessibilityDelegate
   7360      */
   7361     public void sendAccessibilityEvent(int eventType) {
   7362         if (mAccessibilityDelegate != null) {
   7363             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
   7364         } else {
   7365             sendAccessibilityEventInternal(eventType);
   7366         }
   7367     }
   7368 
   7369     /**
   7370      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
   7371      * {@link AccessibilityEvent} to make an announcement which is related to some
   7372      * sort of a context change for which none of the events representing UI transitions
   7373      * is a good fit. For example, announcing a new page in a book. If accessibility
   7374      * is not enabled this method does nothing.
   7375      *
   7376      * @param text The announcement text.
   7377      */
   7378     public void announceForAccessibility(CharSequence text) {
   7379         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
   7380             AccessibilityEvent event = AccessibilityEvent.obtain(
   7381                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
   7382             onInitializeAccessibilityEvent(event);
   7383             event.getText().add(text);
   7384             event.setContentDescription(null);
   7385             mParent.requestSendAccessibilityEvent(this, event);
   7386         }
   7387     }
   7388 
   7389     /**
   7390      * @see #sendAccessibilityEvent(int)
   7391      *
   7392      * Note: Called from the default {@link AccessibilityDelegate}.
   7393      *
   7394      * @hide
   7395      */
   7396     public void sendAccessibilityEventInternal(int eventType) {
   7397         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   7398             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
   7399         }
   7400     }
   7401 
   7402     /**
   7403      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
   7404      * takes as an argument an empty {@link AccessibilityEvent} and does not
   7405      * perform a check whether accessibility is enabled.
   7406      * <p>
   7407      * If an {@link AccessibilityDelegate} has been specified via calling
   7408      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7409      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
   7410      * is responsible for handling this call.
   7411      * </p>
   7412      *
   7413      * @param event The event to send.
   7414      *
   7415      * @see #sendAccessibilityEvent(int)
   7416      */
   7417     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
   7418         if (mAccessibilityDelegate != null) {
   7419             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   7420         } else {
   7421             sendAccessibilityEventUncheckedInternal(event);
   7422         }
   7423     }
   7424 
   7425     /**
   7426      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
   7427      *
   7428      * Note: Called from the default {@link AccessibilityDelegate}.
   7429      *
   7430      * @hide
   7431      */
   7432     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
   7433         // Panes disappearing are relevant even if though the view is no longer visible.
   7434         boolean isWindowStateChanged =
   7435                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
   7436         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
   7437                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
   7438         if (!isShown() && !isWindowDisappearedEvent) {
   7439             return;
   7440         }
   7441         onInitializeAccessibilityEvent(event);
   7442         // Only a subset of accessibility events populates text content.
   7443         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
   7444             dispatchPopulateAccessibilityEvent(event);
   7445         }
   7446         // In the beginning we called #isShown(), so we know that getParent() is not null.
   7447         ViewParent parent = getParent();
   7448         if (parent != null) {
   7449             getParent().requestSendAccessibilityEvent(this, event);
   7450         }
   7451     }
   7452 
   7453     /**
   7454      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
   7455      * to its children for adding their text content to the event. Note that the
   7456      * event text is populated in a separate dispatch path since we add to the
   7457      * event not only the text of the source but also the text of all its descendants.
   7458      * A typical implementation will call
   7459      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
   7460      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   7461      * on each child. Override this method if custom population of the event text
   7462      * content is required.
   7463      * <p>
   7464      * If an {@link AccessibilityDelegate} has been specified via calling
   7465      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7466      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
   7467      * is responsible for handling this call.
   7468      * </p>
   7469      * <p>
   7470      * <em>Note:</em> Accessibility events of certain types are not dispatched for
   7471      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
   7472      * </p>
   7473      *
   7474      * @param event The event.
   7475      *
   7476      * @return True if the event population was completed.
   7477      */
   7478     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
   7479         if (mAccessibilityDelegate != null) {
   7480             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
   7481         } else {
   7482             return dispatchPopulateAccessibilityEventInternal(event);
   7483         }
   7484     }
   7485 
   7486     /**
   7487      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   7488      *
   7489      * Note: Called from the default {@link AccessibilityDelegate}.
   7490      *
   7491      * @hide
   7492      */
   7493     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   7494         onPopulateAccessibilityEvent(event);
   7495         return false;
   7496     }
   7497 
   7498     /**
   7499      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   7500      * giving a chance to this View to populate the accessibility event with its
   7501      * text content. While this method is free to modify event
   7502      * attributes other than text content, doing so should normally be performed in
   7503      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
   7504      * <p>
   7505      * Example: Adding formatted date string to an accessibility event in addition
   7506      *          to the text added by the super implementation:
   7507      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   7508      *     super.onPopulateAccessibilityEvent(event);
   7509      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
   7510      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
   7511      *         mCurrentDate.getTimeInMillis(), flags);
   7512      *     event.getText().add(selectedDateUtterance);
   7513      * }</pre>
   7514      * <p>
   7515      * If an {@link AccessibilityDelegate} has been specified via calling
   7516      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7517      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
   7518      * is responsible for handling this call.
   7519      * </p>
   7520      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   7521      * information to the event, in case the default implementation has basic information to add.
   7522      * </p>
   7523      *
   7524      * @param event The accessibility event which to populate.
   7525      *
   7526      * @see #sendAccessibilityEvent(int)
   7527      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   7528      */
   7529     @CallSuper
   7530     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   7531         if (mAccessibilityDelegate != null) {
   7532             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
   7533         } else {
   7534             onPopulateAccessibilityEventInternal(event);
   7535         }
   7536     }
   7537 
   7538     /**
   7539      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
   7540      *
   7541      * Note: Called from the default {@link AccessibilityDelegate}.
   7542      *
   7543      * @hide
   7544      */
   7545     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   7546         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
   7547                 && !TextUtils.isEmpty(getAccessibilityPaneTitle())) {
   7548             event.getText().add(getAccessibilityPaneTitle());
   7549         }
   7550     }
   7551 
   7552     /**
   7553      * Initializes an {@link AccessibilityEvent} with information about
   7554      * this View which is the event source. In other words, the source of
   7555      * an accessibility event is the view whose state change triggered firing
   7556      * the event.
   7557      * <p>
   7558      * Example: Setting the password property of an event in addition
   7559      *          to properties set by the super implementation:
   7560      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   7561      *     super.onInitializeAccessibilityEvent(event);
   7562      *     event.setPassword(true);
   7563      * }</pre>
   7564      * <p>
   7565      * If an {@link AccessibilityDelegate} has been specified via calling
   7566      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7567      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
   7568      * is responsible for handling this call.
   7569      * </p>
   7570      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   7571      * information to the event, in case the default implementation has basic information to add.
   7572      * </p>
   7573      * @param event The event to initialize.
   7574      *
   7575      * @see #sendAccessibilityEvent(int)
   7576      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   7577      */
   7578     @CallSuper
   7579     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   7580         if (mAccessibilityDelegate != null) {
   7581             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
   7582         } else {
   7583             onInitializeAccessibilityEventInternal(event);
   7584         }
   7585     }
   7586 
   7587     /**
   7588      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   7589      *
   7590      * Note: Called from the default {@link AccessibilityDelegate}.
   7591      *
   7592      * @hide
   7593      */
   7594     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
   7595         event.setSource(this);
   7596         event.setClassName(getAccessibilityClassName());
   7597         event.setPackageName(getContext().getPackageName());
   7598         event.setEnabled(isEnabled());
   7599         event.setContentDescription(mContentDescription);
   7600 
   7601         switch (event.getEventType()) {
   7602             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
   7603                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
   7604                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
   7605                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
   7606                 event.setItemCount(focusablesTempList.size());
   7607                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
   7608                 if (mAttachInfo != null) {
   7609                     focusablesTempList.clear();
   7610                 }
   7611             } break;
   7612             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
   7613                 CharSequence text = getIterableTextForAccessibility();
   7614                 if (text != null && text.length() > 0) {
   7615                     event.setFromIndex(getAccessibilitySelectionStart());
   7616                     event.setToIndex(getAccessibilitySelectionEnd());
   7617                     event.setItemCount(text.length());
   7618                 }
   7619             } break;
   7620         }
   7621     }
   7622 
   7623     /**
   7624      * Returns an {@link AccessibilityNodeInfo} representing this view from the
   7625      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   7626      * This method is responsible for obtaining an accessibility node info from a
   7627      * pool of reusable instances and calling
   7628      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
   7629      * initialize the former.
   7630      * <p>
   7631      * Note: The client is responsible for recycling the obtained instance by calling
   7632      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
   7633      * </p>
   7634      *
   7635      * @return A populated {@link AccessibilityNodeInfo}.
   7636      *
   7637      * @see AccessibilityNodeInfo
   7638      */
   7639     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
   7640         if (mAccessibilityDelegate != null) {
   7641             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
   7642         } else {
   7643             return createAccessibilityNodeInfoInternal();
   7644         }
   7645     }
   7646 
   7647     /**
   7648      * @see #createAccessibilityNodeInfo()
   7649      *
   7650      * @hide
   7651      */
   7652     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
   7653         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   7654         if (provider != null) {
   7655             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
   7656         } else {
   7657             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
   7658             onInitializeAccessibilityNodeInfo(info);
   7659             return info;
   7660         }
   7661     }
   7662 
   7663     /**
   7664      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
   7665      * The base implementation sets:
   7666      * <ul>
   7667      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
   7668      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
   7669      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
   7670      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
   7671      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
   7672      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
   7673      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
   7674      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
   7675      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
   7676      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
   7677      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
   7678      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
   7679      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
   7680      * </ul>
   7681      * <p>
   7682      * Subclasses should override this method, call the super implementation,
   7683      * and set additional attributes.
   7684      * </p>
   7685      * <p>
   7686      * If an {@link AccessibilityDelegate} has been specified via calling
   7687      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7688      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
   7689      * is responsible for handling this call.
   7690      * </p>
   7691      *
   7692      * @param info The instance to initialize.
   7693      */
   7694     @CallSuper
   7695     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
   7696         if (mAccessibilityDelegate != null) {
   7697             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
   7698         } else {
   7699             onInitializeAccessibilityNodeInfoInternal(info);
   7700         }
   7701     }
   7702 
   7703     /**
   7704      * Gets the location of this view in screen coordinates.
   7705      *
   7706      * @param outRect The output location
   7707      * @hide
   7708      */
   7709     public void getBoundsOnScreen(Rect outRect) {
   7710         getBoundsOnScreen(outRect, false);
   7711     }
   7712 
   7713     /**
   7714      * Gets the location of this view in screen coordinates.
   7715      *
   7716      * @param outRect The output location
   7717      * @param clipToParent Whether to clip child bounds to the parent ones.
   7718      * @hide
   7719      */
   7720     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
   7721         if (mAttachInfo == null) {
   7722             return;
   7723         }
   7724 
   7725         RectF position = mAttachInfo.mTmpTransformRect;
   7726         position.set(0, 0, mRight - mLeft, mBottom - mTop);
   7727         mapRectFromViewToScreenCoords(position, clipToParent);
   7728         outRect.set(Math.round(position.left), Math.round(position.top),
   7729                 Math.round(position.right), Math.round(position.bottom));
   7730     }
   7731 
   7732     /**
   7733      * Map a rectangle from view-relative coordinates to screen-relative coordinates
   7734      *
   7735      * @param rect The rectangle to be mapped
   7736      * @param clipToParent Whether to clip child bounds to the parent ones.
   7737      * @hide
   7738      */
   7739     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
   7740         if (!hasIdentityMatrix()) {
   7741             getMatrix().mapRect(rect);
   7742         }
   7743 
   7744         rect.offset(mLeft, mTop);
   7745 
   7746         ViewParent parent = mParent;
   7747         while (parent instanceof View) {
   7748             View parentView = (View) parent;
   7749 
   7750             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
   7751 
   7752             if (clipToParent) {
   7753                 rect.left = Math.max(rect.left, 0);
   7754                 rect.top = Math.max(rect.top, 0);
   7755                 rect.right = Math.min(rect.right, parentView.getWidth());
   7756                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
   7757             }
   7758 
   7759             if (!parentView.hasIdentityMatrix()) {
   7760                 parentView.getMatrix().mapRect(rect);
   7761             }
   7762 
   7763             rect.offset(parentView.mLeft, parentView.mTop);
   7764 
   7765             parent = parentView.mParent;
   7766         }
   7767 
   7768         if (parent instanceof ViewRootImpl) {
   7769             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
   7770             rect.offset(0, -viewRootImpl.mCurScrollY);
   7771         }
   7772 
   7773         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
   7774     }
   7775 
   7776     /**
   7777      * Return the class name of this object to be used for accessibility purposes.
   7778      * Subclasses should only override this if they are implementing something that
   7779      * should be seen as a completely new class of view when used by accessibility,
   7780      * unrelated to the class it is deriving from.  This is used to fill in
   7781      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
   7782      */
   7783     public CharSequence getAccessibilityClassName() {
   7784         return View.class.getName();
   7785     }
   7786 
   7787     /**
   7788      * Called when assist structure is being retrieved from a view as part of
   7789      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
   7790      * @param structure Fill in with structured view data.  The default implementation
   7791      * fills in all data that can be inferred from the view itself.
   7792      */
   7793     public void onProvideStructure(ViewStructure structure) {
   7794         onProvideStructureForAssistOrAutofill(structure, false, 0);
   7795     }
   7796 
   7797     /**
   7798      * Populates a {@link ViewStructure} to fullfil an autofill request.
   7799      *
   7800      * <p>The structure should contain at least the following properties:
   7801      * <ul>
   7802      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
   7803      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
   7804      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
   7805      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
   7806      * </ul>
   7807      *
   7808      * <p>It's also recommended to set the following properties - the more properties the structure
   7809      * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
   7810      * using the structure:
   7811      *
   7812      * <ul>
   7813      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
   7814      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
   7815      *       view can only be filled with predefined values (typically used when the autofill type
   7816      *       is {@link #AUTOFILL_TYPE_LIST}).
   7817      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
   7818      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
   7819      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
   7820      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
   7821      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
   7822      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
   7823      *   <li>For views representing text fields, text properties such as the text itself
   7824      *       ({@link ViewStructure#setText(CharSequence)}), text hints
   7825      *       ({@link ViewStructure#setHint(CharSequence)}, input type
   7826      *       ({@link ViewStructure#setInputType(int)}),
   7827      *   <li>For views representing HTML nodes, its web domain
   7828      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
   7829      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
   7830      * </ul>
   7831      *
   7832      * <p>The default implementation of this method already sets most of these properties based on
   7833      * related {@link View} methods (for example, the autofill id is set using
   7834      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
   7835      * and views in the standard Android widgets library also override it to set their
   7836      * relevant properties (for example, {@link android.widget.TextView} already sets the text
   7837      * properties), so it's recommended to only override this method
   7838      * (and call {@code super.onProvideAutofillStructure()}) when:
   7839      *
   7840      * <ul>
   7841      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
   7842      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
   7843      *   <li>The view can only be autofilled with predefined options, so it can call
   7844      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
   7845      * </ul>
   7846      *
   7847      * <p><b>Note:</b> The {@code left} and {@code top} values set in
   7848      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
   7849      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
   7850      *
   7851      * <p>Views support the Autofill Framework mainly by:
   7852      * <ul>
   7853      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
   7854      *   <li>Notifying the Android System when the view value changed by calling
   7855      *       {@link AutofillManager#notifyValueChanged(View)}.
   7856      *   <li>Implementing the methods that autofill the view.
   7857      * </ul>
   7858      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
   7859      * for the latter.
   7860      *
   7861      * @param structure fill in with structured view data for autofill purposes.
   7862      * @param flags optional flags.
   7863      *
   7864      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   7865      */
   7866     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
   7867         onProvideStructureForAssistOrAutofill(structure, true, flags);
   7868     }
   7869 
   7870     private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
   7871             boolean forAutofill, @AutofillFlags int flags) {
   7872         final int id = mID;
   7873         if (id != NO_ID && !isViewIdGenerated(id)) {
   7874             String pkg, type, entry;
   7875             try {
   7876                 final Resources res = getResources();
   7877                 entry = res.getResourceEntryName(id);
   7878                 type = res.getResourceTypeName(id);
   7879                 pkg = res.getResourcePackageName(id);
   7880             } catch (Resources.NotFoundException e) {
   7881                 entry = type = pkg = null;
   7882             }
   7883             structure.setId(id, pkg, type, entry);
   7884         } else {
   7885             structure.setId(id, null, null, null);
   7886         }
   7887 
   7888         if (forAutofill) {
   7889             final @AutofillType int autofillType = getAutofillType();
   7890             // Don't need to fill autofill info if view does not support it.
   7891             // For example, only TextViews that are editable support autofill
   7892             if (autofillType != AUTOFILL_TYPE_NONE) {
   7893                 structure.setAutofillType(autofillType);
   7894                 structure.setAutofillHints(getAutofillHints());
   7895                 structure.setAutofillValue(getAutofillValue());
   7896             }
   7897             structure.setImportantForAutofill(getImportantForAutofill());
   7898         }
   7899 
   7900         int ignoredParentLeft = 0;
   7901         int ignoredParentTop = 0;
   7902         if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
   7903             View parentGroup = null;
   7904 
   7905             ViewParent viewParent = getParent();
   7906             if (viewParent instanceof View) {
   7907                 parentGroup = (View) viewParent;
   7908             }
   7909 
   7910             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
   7911                 ignoredParentLeft += parentGroup.mLeft;
   7912                 ignoredParentTop += parentGroup.mTop;
   7913 
   7914                 viewParent = parentGroup.getParent();
   7915                 if (viewParent instanceof View) {
   7916                     parentGroup = (View) viewParent;
   7917                 } else {
   7918                     break;
   7919                 }
   7920             }
   7921         }
   7922 
   7923         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
   7924                 mRight - mLeft, mBottom - mTop);
   7925         if (!forAutofill) {
   7926             if (!hasIdentityMatrix()) {
   7927                 structure.setTransformation(getMatrix());
   7928             }
   7929             structure.setElevation(getZ());
   7930         }
   7931         structure.setVisibility(getVisibility());
   7932         structure.setEnabled(isEnabled());
   7933         if (isClickable()) {
   7934             structure.setClickable(true);
   7935         }
   7936         if (isFocusable()) {
   7937             structure.setFocusable(true);
   7938         }
   7939         if (isFocused()) {
   7940             structure.setFocused(true);
   7941         }
   7942         if (isAccessibilityFocused()) {
   7943             structure.setAccessibilityFocused(true);
   7944         }
   7945         if (isSelected()) {
   7946             structure.setSelected(true);
   7947         }
   7948         if (isActivated()) {
   7949             structure.setActivated(true);
   7950         }
   7951         if (isLongClickable()) {
   7952             structure.setLongClickable(true);
   7953         }
   7954         if (this instanceof Checkable) {
   7955             structure.setCheckable(true);
   7956             if (((Checkable)this).isChecked()) {
   7957                 structure.setChecked(true);
   7958             }
   7959         }
   7960         if (isOpaque()) {
   7961             structure.setOpaque(true);
   7962         }
   7963         if (isContextClickable()) {
   7964             structure.setContextClickable(true);
   7965         }
   7966         structure.setClassName(getAccessibilityClassName().toString());
   7967         structure.setContentDescription(getContentDescription());
   7968     }
   7969 
   7970     /**
   7971      * Called when assist structure is being retrieved from a view as part of
   7972      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
   7973      * generate additional virtual structure under this view.  The defaullt implementation
   7974      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
   7975      * view's virtual accessibility nodes, if any.  You can override this for a more
   7976      * optimal implementation providing this data.
   7977      */
   7978     public void onProvideVirtualStructure(ViewStructure structure) {
   7979         onProvideVirtualStructureCompat(structure, false);
   7980     }
   7981 
   7982     /**
   7983      * Fallback implementation to populate a ViewStructure from accessibility state.
   7984      *
   7985      * @param structure The structure to populate.
   7986      * @param forAutofill Whether the structure is needed for autofill.
   7987      */
   7988     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
   7989         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   7990         if (provider != null) {
   7991             if (android.view.autofill.Helper.sVerbose && forAutofill) {
   7992                 Log.v(VIEW_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
   7993             }
   7994 
   7995             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
   7996             structure.setChildCount(1);
   7997             final ViewStructure root = structure.newChild(0);
   7998             populateVirtualStructure(root, provider, info, forAutofill);
   7999             info.recycle();
   8000         }
   8001     }
   8002 
   8003     /**
   8004      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
   8005      * request.
   8006      *
   8007      * <p>This method should be used when the view manages a virtual structure under this view. For
   8008      * example, a view that draws input fields using {@link #draw(Canvas)}.
   8009      *
   8010      * <p>When implementing this method, subclasses must follow the rules below:
   8011      *
   8012      * <ul>
   8013      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
   8014      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
   8015      *       identifying the children in the virtual structure.
   8016      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
   8017      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
   8018      *       autofill performance.
   8019      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
   8020      *       children.
   8021      *   <li>Set the autofill properties of the child structure as defined by
   8022      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
   8023      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
   8024      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
   8025      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
   8026      *       when the focused virtual child changed.
   8027      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
   8028      *       whether a given virtual view is visible to the user in order to support triggering
   8029      *       save when all views of interest go away.
   8030      *   <li>Call
   8031      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
   8032      *       when the value of a virtual child changed.
   8033      *   <li>Call {@link
   8034      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
   8035      *       when the visibility of a virtual child changed.
   8036      *   <li>Call
   8037      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
   8038      *       child is clicked.
   8039      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
   8040      *       changed and the current context should be committed (for example, when the user tapped
   8041      *       a {@code SUBMIT} button in an HTML page).
   8042      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
   8043      *       changed and the current context should be canceled (for example, when the user tapped
   8044      *       a {@code CANCEL} button in an HTML page).
   8045      *   <li>Provide ways for users to manually request autofill by calling
   8046      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
   8047      *   <li>The {@code left} and {@code top} values set in
   8048      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
   8049      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
   8050      *       structure.
   8051      * </ul>
   8052      *
   8053      * <p>Views with virtual children support the Autofill Framework mainly by:
   8054      * <ul>
   8055      *   <li>Providing the metadata defining what the virtual children mean and how they can be
   8056      *       autofilled.
   8057      *   <li>Implementing the methods that autofill the virtual children.
   8058      * </ul>
   8059      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
   8060      * for the latter.
   8061      *
   8062      * @param structure fill in with virtual children data for autofill purposes.
   8063      * @param flags optional flags.
   8064      *
   8065      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   8066      */
   8067     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
   8068         if (mContext.isAutofillCompatibilityEnabled()) {
   8069             onProvideVirtualStructureCompat(structure, true);
   8070         }
   8071     }
   8072 
   8073     /**
   8074      * Automatically fills the content of this view with the {@code value}.
   8075      *
   8076      * <p>Views support the Autofill Framework mainly by:
   8077      * <ul>
   8078      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
   8079      *   <li>Implementing the methods that autofill the view.
   8080      * </ul>
   8081      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
   8082      * this method is responsible for latter.
   8083      *
   8084      * <p>This method does nothing by default, but when overridden it typically:
   8085      * <ol>
   8086      *   <li>Checks if the provided value matches the expected type (which is defined by
   8087      *       {@link #getAutofillType()}).
   8088      *   <li>Checks if the view is editable - if it isn't, it should return right away.
   8089      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
   8090      *   <li>Pass the actual value to the equivalent setter in the view.
   8091      * </ol>
   8092      *
   8093      * <p>For example, a text-field view could implement the method this way:
   8094      *
   8095      * <pre class="prettyprint">
   8096      * &#64;Override
   8097      * public void autofill(AutofillValue value) {
   8098      *   if (!value.isText() || !this.isEditable()) {
   8099      *      return;
   8100      *   }
   8101      *   CharSequence text = value.getTextValue();
   8102      *   if (text != null) {
   8103      *     this.setText(text);
   8104      *   }
   8105      * }
   8106      * </pre>
   8107      *
   8108      * <p>If the value is updated asynchronously, the next call to
   8109      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
   8110      * changed to the autofilled value. If not, the view will not be considered autofilled.
   8111      *
   8112      * <p><b>Note:</b> After this method is called, the value returned by
   8113      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
   8114      * view will not be highlighted as autofilled.
   8115      *
   8116      * @param value value to be autofilled.
   8117      */
   8118     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
   8119     }
   8120 
   8121     /**
   8122      * Automatically fills the content of the virtual children within this view.
   8123      *
   8124      * <p>Views with virtual children support the Autofill Framework mainly by:
   8125      * <ul>
   8126      *   <li>Providing the metadata defining what the virtual children mean and how they can be
   8127      *       autofilled.
   8128      *   <li>Implementing the methods that autofill the virtual children.
   8129      * </ul>
   8130      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
   8131      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
   8132      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
   8133      *
   8134      * <p>If a child value is updated asynchronously, the next call to
   8135      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
   8136      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
   8137      * considered autofilled.
   8138      *
   8139      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
   8140      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
   8141      * changes.
   8142      *
   8143      * @param values map of values to be autofilled, keyed by virtual child id.
   8144      *
   8145      * @attr ref android.R.styleable#Theme_autofilledHighlight
   8146      */
   8147     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
   8148         if (!mContext.isAutofillCompatibilityEnabled()) {
   8149             return;
   8150         }
   8151         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   8152         if (provider == null) {
   8153             return;
   8154         }
   8155         final int valueCount = values.size();
   8156         for (int i = 0; i < valueCount; i++) {
   8157             final AutofillValue value = values.valueAt(i);
   8158             if (value.isText()) {
   8159                 final int virtualId = values.keyAt(i);
   8160                 final CharSequence text = value.getTextValue();
   8161                 final Bundle arguments = new Bundle();
   8162                 arguments.putCharSequence(
   8163                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
   8164                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
   8165             }
   8166         }
   8167     }
   8168 
   8169     /**
   8170      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
   8171      *
   8172      * <p>The autofill id is created on demand, unless it is explicitly set by
   8173      * {@link #setAutofillId(AutofillId)}.
   8174      *
   8175      * <p>See {@link #setAutofillId(AutofillId)} for more info.
   8176      *
   8177      * @return The View's autofill id.
   8178      */
   8179     public final AutofillId getAutofillId() {
   8180         if (mAutofillId == null) {
   8181             // The autofill id needs to be unique, but its value doesn't matter,
   8182             // so it's better to reuse the accessibility id to save space.
   8183             mAutofillId = new AutofillId(getAutofillViewId());
   8184         }
   8185         return mAutofillId;
   8186     }
   8187 
   8188     /**
   8189      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
   8190      *
   8191      * <p>The autofill id is created on demand, and this method should only be called when a view is
   8192      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
   8193      * that method creates a snapshot of the view that is passed along to the autofill service.
   8194      *
   8195      * <p>This method is typically used when view subtrees are recycled to represent different
   8196      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
   8197      * out, and restored later when it's swapped back in. For example:
   8198      *
   8199      * <pre>
   8200      * EditText reusableView = ...;
   8201      * ViewGroup parentView = ...;
   8202      * AutofillManager afm = ...;
   8203      *
   8204      * // Swap out the view and change its contents
   8205      * AutofillId oldId = reusableView.getAutofillId();
   8206      * CharSequence oldText = reusableView.getText();
   8207      * parentView.removeView(reusableView);
   8208      * AutofillId newId = afm.getNextAutofillId();
   8209      * reusableView.setText("New I am");
   8210      * reusableView.setAutofillId(newId);
   8211      * parentView.addView(reusableView);
   8212      *
   8213      * // Later, swap the old content back in
   8214      * parentView.removeView(reusableView);
   8215      * reusableView.setAutofillId(oldId);
   8216      * reusableView.setText(oldText);
   8217      * parentView.addView(reusableView);
   8218      * </pre>
   8219      *
   8220      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
   8221      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
   8222      * obtained through {@link #getAutofillId()}), or a new value obtained through
   8223      * {@link AutofillManager#getNextAutofillId()}.
   8224      *
   8225      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
   8226      * a window}.
   8227      *
   8228      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
   8229      */
   8230     public void setAutofillId(@Nullable AutofillId id) {
   8231         // TODO(b/37566627): add unit / CTS test for all possible combinations below
   8232         if (android.view.autofill.Helper.sVerbose) {
   8233             Log.v(VIEW_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
   8234         }
   8235         if (isAttachedToWindow()) {
   8236             throw new IllegalStateException("Cannot set autofill id when view is attached");
   8237         }
   8238         if (id != null && id.isVirtual()) {
   8239             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
   8240         }
   8241         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
   8242             // Ignore reset because it was never explicitly set before.
   8243             return;
   8244         }
   8245         mAutofillId = id;
   8246         if (id != null) {
   8247             mAutofillViewId = id.getViewId();
   8248             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
   8249         } else {
   8250             mAutofillViewId = NO_ID;
   8251             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
   8252         }
   8253     }
   8254 
   8255     /**
   8256      * Describes the autofill type of this view, so an
   8257      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
   8258      * when autofilling the view.
   8259      *
   8260      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
   8261      * support the Autofill Framework.
   8262      *
   8263      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
   8264      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
   8265      *
   8266      * @see #onProvideAutofillStructure(ViewStructure, int)
   8267      * @see #autofill(AutofillValue)
   8268      */
   8269     public @AutofillType int getAutofillType() {
   8270         return AUTOFILL_TYPE_NONE;
   8271     }
   8272 
   8273     /**
   8274      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
   8275      * to autofill the view with the user's data.
   8276      *
   8277      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
   8278      *
   8279      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
   8280      * {@code null} if no hints were set.
   8281      *
   8282      * @attr ref android.R.styleable#View_autofillHints
   8283      */
   8284     @ViewDebug.ExportedProperty()
   8285     @Nullable public String[] getAutofillHints() {
   8286         return mAutofillHints;
   8287     }
   8288 
   8289     /**
   8290      * @hide
   8291      */
   8292     public boolean isAutofilled() {
   8293         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
   8294     }
   8295 
   8296     /**
   8297      * Gets the {@link View}'s current autofill value.
   8298      *
   8299      * <p>By default returns {@code null}, but subclasses should override it and return an
   8300      * appropriate value to properly support the Autofill Framework.
   8301      *
   8302      * @see #onProvideAutofillStructure(ViewStructure, int)
   8303      * @see #autofill(AutofillValue)
   8304      */
   8305     @Nullable
   8306     public AutofillValue getAutofillValue() {
   8307         return null;
   8308     }
   8309 
   8310     /**
   8311      * Gets the mode for determining whether this view is important for autofill.
   8312      *
   8313      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
   8314      * info about this mode.
   8315      *
   8316      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
   8317      * {@link #setImportantForAutofill(int)}.
   8318      *
   8319      * @attr ref android.R.styleable#View_importantForAutofill
   8320      */
   8321     @ViewDebug.ExportedProperty(mapping = {
   8322             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
   8323             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
   8324             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
   8325             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
   8326                 to = "yesExcludeDescendants"),
   8327             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
   8328                 to = "noExcludeDescendants")})
   8329     public @AutofillImportance int getImportantForAutofill() {
   8330         return (mPrivateFlags3
   8331                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
   8332     }
   8333 
   8334     /**
   8335      * Sets the mode for determining whether this view is considered important for autofill.
   8336      *
   8337      * <p>The platform determines the importance for autofill automatically but you
   8338      * can use this method to customize the behavior. For example:
   8339      *
   8340      * <ol>
   8341      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
   8342      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
   8343      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
   8344      *       view of an activity containing a spreadhseet editor), it should be
   8345      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
   8346      *   <li>When the view content is relevant for autofill but its children aren't (for example,
   8347      *       a credit card expiration date represented by a custom view that overrides the proper
   8348      *       autofill methods and has 2 children representing the month and year), it should
   8349      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
   8350      * </ol>
   8351      *
   8352      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
   8353      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
   8354      * children) will be always be considered not important; for example, when the user explicitly
   8355      * makes an autofill request, all views are considered important. See
   8356      * {@link #isImportantForAutofill()} for more details about how the View's importance for
   8357      * autofill is used.
   8358      *
   8359      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
   8360      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
   8361      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
   8362      *
   8363      * @attr ref android.R.styleable#View_importantForAutofill
   8364      */
   8365     public void setImportantForAutofill(@AutofillImportance int mode) {
   8366         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
   8367         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
   8368                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
   8369     }
   8370 
   8371     /**
   8372      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
   8373      * associated with this view is considered important for autofill purposes.
   8374      *
   8375      * <p>Generally speaking, a view is important for autofill if:
   8376      * <ol>
   8377      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
   8378      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
   8379      *     determine how other views can be autofilled.
   8380      * <ol>
   8381      *
   8382      * <p>For example, view containers should typically return {@code false} for performance reasons
   8383      * (since the important info is provided by their children), but if its properties have relevant
   8384      * information (for example, a resource id called {@code credentials}, it should return
   8385      * {@code true}. On the other hand, views representing labels or editable fields should
   8386      * typically return {@code true}, but in some cases they could return {@code false}
   8387      * (for example, if they're part of a "Captcha" mechanism).
   8388      *
   8389      * <p>The value returned by this method depends on the value returned by
   8390      * {@link #getImportantForAutofill()}:
   8391      *
   8392      * <ol>
   8393      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
   8394      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
   8395      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
   8396      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
   8397      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
   8398      *       that can return {@code true} in some cases (like a container with a resource id),
   8399      *       but {@code false} in most.
   8400      *   <li>otherwise, it returns {@code false}.
   8401      * </ol>
   8402      *
   8403      * <p>When a view is considered important for autofill:
   8404      * <ul>
   8405      *   <li>The view might automatically trigger an autofill request when focused on.
   8406      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
   8407      *       request.
   8408      * </ul>
   8409      *
   8410      * <p>On the other hand, when a view is considered not important for autofill:
   8411      * <ul>
   8412      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
   8413      *       request through {@link AutofillManager#requestAutofill(View)}.
   8414      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
   8415      *       autofill request, unless the request has the
   8416      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
   8417      * </ul>
   8418      *
   8419      * @return whether the view is considered important for autofill.
   8420      *
   8421      * @see #setImportantForAutofill(int)
   8422      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
   8423      * @see #IMPORTANT_FOR_AUTOFILL_YES
   8424      * @see #IMPORTANT_FOR_AUTOFILL_NO
   8425      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
   8426      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
   8427      * @see AutofillManager#requestAutofill(View)
   8428      */
   8429     public final boolean isImportantForAutofill() {
   8430         // Check parent mode to ensure we're not hidden.
   8431         ViewParent parent = mParent;
   8432         while (parent instanceof View) {
   8433             final int parentImportance = ((View) parent).getImportantForAutofill();
   8434             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
   8435                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
   8436                 return false;
   8437             }
   8438             parent = parent.getParent();
   8439         }
   8440 
   8441         final int importance = getImportantForAutofill();
   8442 
   8443         // First, check the explicit states.
   8444         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
   8445                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
   8446             return true;
   8447         }
   8448         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
   8449                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
   8450             return false;
   8451         }
   8452 
   8453         // Then use some heuristics to handle AUTO.
   8454 
   8455         // Always include views that have an explicit resource id.
   8456         final int id = mID;
   8457         if (id != NO_ID && !isViewIdGenerated(id)) {
   8458             final Resources res = getResources();
   8459             String entry = null;
   8460             String pkg = null;
   8461             try {
   8462                 entry = res.getResourceEntryName(id);
   8463                 pkg = res.getResourcePackageName(id);
   8464             } catch (Resources.NotFoundException e) {
   8465                 // ignore
   8466             }
   8467             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
   8468                 return true;
   8469             }
   8470         }
   8471 
   8472         // If the app developer explicitly set hints for it, it's important.
   8473         if (getAutofillHints() != null) {
   8474             return true;
   8475         }
   8476 
   8477         // Otherwise, assume it's not important...
   8478         return false;
   8479     }
   8480 
   8481     @Nullable
   8482     private AutofillManager getAutofillManager() {
   8483         return mContext.getSystemService(AutofillManager.class);
   8484     }
   8485 
   8486     private boolean isAutofillable() {
   8487         return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
   8488                 && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
   8489     }
   8490 
   8491     /** @hide */
   8492     public boolean canNotifyAutofillEnterExitEvent() {
   8493         return isAutofillable() && isAttachedToWindow();
   8494     }
   8495 
   8496     private void populateVirtualStructure(ViewStructure structure,
   8497             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
   8498             boolean forAutofill) {
   8499         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
   8500                 null, null, info.getViewIdResourceName());
   8501         Rect rect = structure.getTempRect();
   8502         info.getBoundsInParent(rect);
   8503         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
   8504         structure.setVisibility(VISIBLE);
   8505         structure.setEnabled(info.isEnabled());
   8506         if (info.isClickable()) {
   8507             structure.setClickable(true);
   8508         }
   8509         if (info.isFocusable()) {
   8510             structure.setFocusable(true);
   8511         }
   8512         if (info.isFocused()) {
   8513             structure.setFocused(true);
   8514         }
   8515         if (info.isAccessibilityFocused()) {
   8516             structure.setAccessibilityFocused(true);
   8517         }
   8518         if (info.isSelected()) {
   8519             structure.setSelected(true);
   8520         }
   8521         if (info.isLongClickable()) {
   8522             structure.setLongClickable(true);
   8523         }
   8524         if (info.isCheckable()) {
   8525             structure.setCheckable(true);
   8526             if (info.isChecked()) {
   8527                 structure.setChecked(true);
   8528             }
   8529         }
   8530         if (info.isContextClickable()) {
   8531             structure.setContextClickable(true);
   8532         }
   8533         if (forAutofill) {
   8534             structure.setAutofillId(new AutofillId(getAutofillId(),
   8535                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
   8536         }
   8537         CharSequence cname = info.getClassName();
   8538         structure.setClassName(cname != null ? cname.toString() : null);
   8539         structure.setContentDescription(info.getContentDescription());
   8540         if (forAutofill) {
   8541             final int maxTextLength = info.getMaxTextLength();
   8542             if (maxTextLength != -1) {
   8543                 structure.setMaxTextLength(maxTextLength);
   8544             }
   8545             structure.setHint(info.getHintText());
   8546         }
   8547         CharSequence text = info.getText();
   8548         boolean hasText = text != null || info.getError() != null;
   8549         if (hasText) {
   8550             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
   8551         }
   8552         if (forAutofill) {
   8553             if (info.isEditable()) {
   8554                 structure.setDataIsSensitive(true);
   8555                 if (hasText) {
   8556                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
   8557                     structure.setAutofillValue(AutofillValue.forText(text));
   8558                 }
   8559                 int inputType = info.getInputType();
   8560                 if (inputType == 0 && info.isPassword()) {
   8561                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
   8562                 }
   8563                 structure.setInputType(inputType);
   8564             } else {
   8565                 structure.setDataIsSensitive(false);
   8566             }
   8567         }
   8568         final int NCHILDREN = info.getChildCount();
   8569         if (NCHILDREN > 0) {
   8570             structure.setChildCount(NCHILDREN);
   8571             for (int i=0; i<NCHILDREN; i++) {
   8572                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
   8573                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
   8574                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
   8575                     continue;
   8576                 }
   8577                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
   8578                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
   8579                 ViewStructure child = structure.newChild(i);
   8580                 populateVirtualStructure(child, provider, cinfo, forAutofill);
   8581                 cinfo.recycle();
   8582             }
   8583         }
   8584     }
   8585 
   8586     /**
   8587      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
   8588      * implementation calls {@link #onProvideStructure} and
   8589      * {@link #onProvideVirtualStructure}.
   8590      */
   8591     public void dispatchProvideStructure(ViewStructure structure) {
   8592         dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
   8593     }
   8594 
   8595     /**
   8596      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
   8597      * when an Assist structure is being created as part of an autofill request.
   8598      *
   8599      * <p>The default implementation does the following:
   8600      * <ul>
   8601      *   <li>Sets the {@link AutofillId} in the structure.
   8602      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
   8603      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
   8604      * </ul>
   8605      *
   8606      * <p>Typically, this method should only be overridden by subclasses that provide a view
   8607      * hierarchy (such as {@link ViewGroup}) - other classes should override
   8608      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
   8609      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
   8610      *
   8611      * <p>When overridden, it must:
   8612      *
   8613      * <ul>
   8614      *   <li>Either call
   8615      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
   8616      *       set the {@link AutofillId} in the structure (for example, by calling
   8617      *       {@code structure.setAutofillId(getAutofillId())}).
   8618      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
   8619      *       set, all views in the structure should be considered important for autofill,
   8620      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
   8621      *       respect this flag to provide a better user experience - this flag is typically used
   8622      *       when an user explicitly requested autofill. If the flag is not set,
   8623      *       then only views marked as important for autofill should be included in the
   8624      *       structure - skipping non-important views optimizes the overall autofill performance.
   8625      * </ul>
   8626      *
   8627      * @param structure fill in with structured view data for autofill purposes.
   8628      * @param flags optional flags.
   8629      *
   8630      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   8631      */
   8632     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
   8633             @AutofillFlags int flags) {
   8634         dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
   8635     }
   8636 
   8637     private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
   8638             boolean forAutofill, @AutofillFlags int flags) {
   8639         if (forAutofill) {
   8640             structure.setAutofillId(getAutofillId());
   8641             onProvideAutofillStructure(structure, flags);
   8642             onProvideAutofillVirtualStructure(structure, flags);
   8643         } else if (!isAssistBlocked()) {
   8644             onProvideStructure(structure);
   8645             onProvideVirtualStructure(structure);
   8646         } else {
   8647             structure.setClassName(getAccessibilityClassName().toString());
   8648             structure.setAssistBlocked(true);
   8649         }
   8650     }
   8651 
   8652     /**
   8653      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   8654      *
   8655      * Note: Called from the default {@link AccessibilityDelegate}.
   8656      *
   8657      * @hide
   8658      */
   8659     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
   8660         if (mAttachInfo == null) {
   8661             return;
   8662         }
   8663 
   8664         Rect bounds = mAttachInfo.mTmpInvalRect;
   8665 
   8666         getDrawingRect(bounds);
   8667         info.setBoundsInParent(bounds);
   8668 
   8669         getBoundsOnScreen(bounds, true);
   8670         info.setBoundsInScreen(bounds);
   8671 
   8672         ViewParent parent = getParentForAccessibility();
   8673         if (parent instanceof View) {
   8674             info.setParent((View) parent);
   8675         }
   8676 
   8677         if (mID != View.NO_ID) {
   8678             View rootView = getRootView();
   8679             if (rootView == null) {
   8680                 rootView = this;
   8681             }
   8682 
   8683             View label = rootView.findLabelForView(this, mID);
   8684             if (label != null) {
   8685                 info.setLabeledBy(label);
   8686             }
   8687 
   8688             if ((mAttachInfo.mAccessibilityFetchFlags
   8689                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
   8690                     && Resources.resourceHasPackage(mID)) {
   8691                 try {
   8692                     String viewId = getResources().getResourceName(mID);
   8693                     info.setViewIdResourceName(viewId);
   8694                 } catch (Resources.NotFoundException nfe) {
   8695                     /* ignore */
   8696                 }
   8697             }
   8698         }
   8699 
   8700         if (mLabelForId != View.NO_ID) {
   8701             View rootView = getRootView();
   8702             if (rootView == null) {
   8703                 rootView = this;
   8704             }
   8705             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
   8706             if (labeled != null) {
   8707                 info.setLabelFor(labeled);
   8708             }
   8709         }
   8710 
   8711         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
   8712             View rootView = getRootView();
   8713             if (rootView == null) {
   8714                 rootView = this;
   8715             }
   8716             View next = rootView.findViewInsideOutShouldExist(this,
   8717                     mAccessibilityTraversalBeforeId);
   8718             if (next != null && next.includeForAccessibility()) {
   8719                 info.setTraversalBefore(next);
   8720             }
   8721         }
   8722 
   8723         if (mAccessibilityTraversalAfterId != View.NO_ID) {
   8724             View rootView = getRootView();
   8725             if (rootView == null) {
   8726                 rootView = this;
   8727             }
   8728             View next = rootView.findViewInsideOutShouldExist(this,
   8729                     mAccessibilityTraversalAfterId);
   8730             if (next != null && next.includeForAccessibility()) {
   8731                 info.setTraversalAfter(next);
   8732             }
   8733         }
   8734 
   8735         info.setVisibleToUser(isVisibleToUser());
   8736 
   8737         info.setImportantForAccessibility(isImportantForAccessibility());
   8738         info.setPackageName(mContext.getPackageName());
   8739         info.setClassName(getAccessibilityClassName());
   8740         info.setContentDescription(getContentDescription());
   8741 
   8742         info.setEnabled(isEnabled());
   8743         info.setClickable(isClickable());
   8744         info.setFocusable(isFocusable());
   8745         info.setScreenReaderFocusable(isScreenReaderFocusable());
   8746         info.setFocused(isFocused());
   8747         info.setAccessibilityFocused(isAccessibilityFocused());
   8748         info.setSelected(isSelected());
   8749         info.setLongClickable(isLongClickable());
   8750         info.setContextClickable(isContextClickable());
   8751         info.setLiveRegion(getAccessibilityLiveRegion());
   8752         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
   8753             info.setTooltipText(mTooltipInfo.mTooltipText);
   8754             info.addAction((mTooltipInfo.mTooltipPopup == null)
   8755                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
   8756                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
   8757         }
   8758 
   8759         // TODO: These make sense only if we are in an AdapterView but all
   8760         // views can be selected. Maybe from accessibility perspective
   8761         // we should report as selectable view in an AdapterView.
   8762         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
   8763         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
   8764 
   8765         if (isFocusable()) {
   8766             if (isFocused()) {
   8767                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
   8768             } else {
   8769                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
   8770             }
   8771         }
   8772 
   8773         if (!isAccessibilityFocused()) {
   8774             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
   8775         } else {
   8776             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
   8777         }
   8778 
   8779         if (isClickable() && isEnabled()) {
   8780             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
   8781         }
   8782 
   8783         if (isLongClickable() && isEnabled()) {
   8784             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
   8785         }
   8786 
   8787         if (isContextClickable() && isEnabled()) {
   8788             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
   8789         }
   8790 
   8791         CharSequence text = getIterableTextForAccessibility();
   8792         if (text != null && text.length() > 0) {
   8793             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
   8794 
   8795             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
   8796             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
   8797             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
   8798             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
   8799                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
   8800                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
   8801         }
   8802 
   8803         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
   8804         populateAccessibilityNodeInfoDrawingOrderInParent(info);
   8805         info.setPaneTitle(mAccessibilityPaneTitle);
   8806         info.setHeading(isAccessibilityHeading());
   8807     }
   8808 
   8809     /**
   8810      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
   8811      * additional data.
   8812      * <p>
   8813      * This method only needs overloading if the node is marked as having extra data available.
   8814      * </p>
   8815      *
   8816      * @param info The info to which to add the extra data. Never {@code null}.
   8817      * @param extraDataKey A key specifying the type of extra data to add to the info. The
   8818      *                     extra data should be added to the {@link Bundle} returned by
   8819      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
   8820      *                     {@code null}.
   8821      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
   8822      *                  {@code null} if the service provided no arguments.
   8823      *
   8824      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
   8825      */
   8826     public void addExtraDataToAccessibilityNodeInfo(
   8827             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
   8828             @Nullable Bundle arguments) {
   8829     }
   8830 
   8831     /**
   8832      * Determine the order in which this view will be drawn relative to its siblings for a11y
   8833      *
   8834      * @param info The info whose drawing order should be populated
   8835      */
   8836     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
   8837         /*
   8838          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
   8839          * drawing order may not be well-defined, and some Views with custom drawing order may
   8840          * not be initialized sufficiently to respond properly getChildDrawingOrder.
   8841          */
   8842         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
   8843             info.setDrawingOrder(0);
   8844             return;
   8845         }
   8846         int drawingOrderInParent = 1;
   8847         // Iterate up the hierarchy if parents are not important for a11y
   8848         View viewAtDrawingLevel = this;
   8849         final ViewParent parent = getParentForAccessibility();
   8850         while (viewAtDrawingLevel != parent) {
   8851             final ViewParent currentParent = viewAtDrawingLevel.getParent();
   8852             if (!(currentParent instanceof ViewGroup)) {
   8853                 // Should only happen for the Decor
   8854                 drawingOrderInParent = 0;
   8855                 break;
   8856             } else {
   8857                 final ViewGroup parentGroup = (ViewGroup) currentParent;
   8858                 final int childCount = parentGroup.getChildCount();
   8859                 if (childCount > 1) {
   8860                     List<View> preorderedList = parentGroup.buildOrderedChildList();
   8861                     if (preorderedList != null) {
   8862                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
   8863                         for (int i = 0; i < childDrawIndex; i++) {
   8864                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
   8865                         }
   8866                     } else {
   8867                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
   8868                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
   8869                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
   8870                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
   8871                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
   8872                         if (childDrawIndex != 0) {
   8873                             for (int i = 0; i < numChildrenToIterate; i++) {
   8874                                 final int otherDrawIndex = (customOrder ?
   8875                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
   8876                                 if (otherDrawIndex < childDrawIndex) {
   8877                                     drawingOrderInParent +=
   8878                                             numViewsForAccessibility(parentGroup.getChildAt(i));
   8879                                 }
   8880                             }
   8881                         }
   8882                     }
   8883                 }
   8884             }
   8885             viewAtDrawingLevel = (View) currentParent;
   8886         }
   8887         info.setDrawingOrder(drawingOrderInParent);
   8888     }
   8889 
   8890     private static int numViewsForAccessibility(View view) {
   8891         if (view != null) {
   8892             if (view.includeForAccessibility()) {
   8893                 return 1;
   8894             } else if (view instanceof ViewGroup) {
   8895                 return ((ViewGroup) view).getNumChildrenForAccessibility();
   8896             }
   8897         }
   8898         return 0;
   8899     }
   8900 
   8901     private View findLabelForView(View view, int labeledId) {
   8902         if (mMatchLabelForPredicate == null) {
   8903             mMatchLabelForPredicate = new MatchLabelForPredicate();
   8904         }
   8905         mMatchLabelForPredicate.mLabeledId = labeledId;
   8906         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
   8907     }
   8908 
   8909     /**
   8910      * Computes whether this virtual autofill view is visible to the user.
   8911      *
   8912      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
   8913      * view must override it.
   8914      *
   8915      * @return Whether the view is visible on the screen.
   8916      */
   8917     public boolean isVisibleToUserForAutofill(int virtualId) {
   8918         if (mContext.isAutofillCompatibilityEnabled()) {
   8919             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   8920             if (provider != null) {
   8921                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
   8922                 if (node != null) {
   8923                     return node.isVisibleToUser();
   8924                 }
   8925                 // if node is null, assume it's not visible anymore
   8926             } else {
   8927                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
   8928             }
   8929             return false;
   8930         }
   8931         return true;
   8932     }
   8933 
   8934     /**
   8935      * Computes whether this view is visible to the user. Such a view is
   8936      * attached, visible, all its predecessors are visible, it is not clipped
   8937      * entirely by its predecessors, and has an alpha greater than zero.
   8938      *
   8939      * @return Whether the view is visible on the screen.
   8940      *
   8941      * @hide
   8942      */
   8943     public boolean isVisibleToUser() {
   8944         return isVisibleToUser(null);
   8945     }
   8946 
   8947     /**
   8948      * Computes whether the given portion of this view is visible to the user.
   8949      * Such a view is attached, visible, all its predecessors are visible,
   8950      * has an alpha greater than zero, and the specified portion is not
   8951      * clipped entirely by its predecessors.
   8952      *
   8953      * @param boundInView the portion of the view to test; coordinates should be relative; may be
   8954      *                    <code>null</code>, and the entire view will be tested in this case.
   8955      *                    When <code>true</code> is returned by the function, the actual visible
   8956      *                    region will be stored in this parameter; that is, if boundInView is fully
   8957      *                    contained within the view, no modification will be made, otherwise regions
   8958      *                    outside of the visible area of the view will be clipped.
   8959      *
   8960      * @return Whether the specified portion of the view is visible on the screen.
   8961      *
   8962      * @hide
   8963      */
   8964     protected boolean isVisibleToUser(Rect boundInView) {
   8965         if (mAttachInfo != null) {
   8966             // Attached to invisible window means this view is not visible.
   8967             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
   8968                 return false;
   8969             }
   8970             // An invisible predecessor or one with alpha zero means
   8971             // that this view is not visible to the user.
   8972             Object current = this;
   8973             while (current instanceof View) {
   8974                 View view = (View) current;
   8975                 // We have attach info so this view is attached and there is no
   8976                 // need to check whether we reach to ViewRootImpl on the way up.
   8977                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
   8978                         view.getVisibility() != VISIBLE) {
   8979                     return false;
   8980                 }
   8981                 current = view.mParent;
   8982             }
   8983             // Check if the view is entirely covered by its predecessors.
   8984             Rect visibleRect = mAttachInfo.mTmpInvalRect;
   8985             Point offset = mAttachInfo.mPoint;
   8986             if (!getGlobalVisibleRect(visibleRect, offset)) {
   8987                 return false;
   8988             }
   8989             // Check if the visible portion intersects the rectangle of interest.
   8990             if (boundInView != null) {
   8991                 visibleRect.offset(-offset.x, -offset.y);
   8992                 return boundInView.intersect(visibleRect);
   8993             }
   8994             return true;
   8995         }
   8996         return false;
   8997     }
   8998 
   8999     /**
   9000      * Returns the delegate for implementing accessibility support via
   9001      * composition. For more details see {@link AccessibilityDelegate}.
   9002      *
   9003      * @return The delegate, or null if none set.
   9004      *
   9005      * @hide
   9006      */
   9007     public AccessibilityDelegate getAccessibilityDelegate() {
   9008         return mAccessibilityDelegate;
   9009     }
   9010 
   9011     /**
   9012      * Sets a delegate for implementing accessibility support via composition
   9013      * (as opposed to inheritance). For more details, see
   9014      * {@link AccessibilityDelegate}.
   9015      * <p>
   9016      * <strong>Note:</strong> On platform versions prior to
   9017      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
   9018      * views in the {@code android.widget.*} package are called <i>before</i>
   9019      * host methods. This prevents certain properties such as class name from
   9020      * being modified by overriding
   9021      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
   9022      * as any changes will be overwritten by the host class.
   9023      * <p>
   9024      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
   9025      * methods are called <i>after</i> host methods, which all properties to be
   9026      * modified without being overwritten by the host class.
   9027      *
   9028      * @param delegate the object to which accessibility method calls should be
   9029      *                 delegated
   9030      * @see AccessibilityDelegate
   9031      */
   9032     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
   9033         mAccessibilityDelegate = delegate;
   9034     }
   9035 
   9036     /**
   9037      * Gets the provider for managing a virtual view hierarchy rooted at this View
   9038      * and reported to {@link android.accessibilityservice.AccessibilityService}s
   9039      * that explore the window content.
   9040      * <p>
   9041      * If this method returns an instance, this instance is responsible for managing
   9042      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
   9043      * View including the one representing the View itself. Similarly the returned
   9044      * instance is responsible for performing accessibility actions on any virtual
   9045      * view or the root view itself.
   9046      * </p>
   9047      * <p>
   9048      * If an {@link AccessibilityDelegate} has been specified via calling
   9049      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   9050      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
   9051      * is responsible for handling this call.
   9052      * </p>
   9053      *
   9054      * @return The provider.
   9055      *
   9056      * @see AccessibilityNodeProvider
   9057      */
   9058     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
   9059         if (mAccessibilityDelegate != null) {
   9060             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
   9061         } else {
   9062             return null;
   9063         }
   9064     }
   9065 
   9066     /**
   9067      * Gets the unique identifier of this view on the screen for accessibility purposes.
   9068      *
   9069      * @return The view accessibility id.
   9070      *
   9071      * @hide
   9072      */
   9073     public int getAccessibilityViewId() {
   9074         if (mAccessibilityViewId == NO_ID) {
   9075             mAccessibilityViewId = sNextAccessibilityViewId++;
   9076         }
   9077         return mAccessibilityViewId;
   9078     }
   9079 
   9080     /**
   9081      * Gets the unique identifier of this view on the screen for autofill purposes.
   9082      *
   9083      * @return The view autofill id.
   9084      *
   9085      * @hide
   9086      */
   9087     public int getAutofillViewId() {
   9088         if (mAutofillViewId == NO_ID) {
   9089             mAutofillViewId = mContext.getNextAutofillId();
   9090         }
   9091         return mAutofillViewId;
   9092     }
   9093 
   9094     /**
   9095      * Gets the unique identifier of the window in which this View reseides.
   9096      *
   9097      * @return The window accessibility id.
   9098      *
   9099      * @hide
   9100      */
   9101     public int getAccessibilityWindowId() {
   9102         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
   9103                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
   9104     }
   9105 
   9106     /**
   9107      * Returns the {@link View}'s content description.
   9108      * <p>
   9109      * <strong>Note:</strong> Do not override this method, as it will have no
   9110      * effect on the content description presented to accessibility services.
   9111      * You must call {@link #setContentDescription(CharSequence)} to modify the
   9112      * content description.
   9113      *
   9114      * @return the content description
   9115      * @see #setContentDescription(CharSequence)
   9116      * @attr ref android.R.styleable#View_contentDescription
   9117      */
   9118     @ViewDebug.ExportedProperty(category = "accessibility")
   9119     public CharSequence getContentDescription() {
   9120         return mContentDescription;
   9121     }
   9122 
   9123     /**
   9124      * Sets the {@link View}'s content description.
   9125      * <p>
   9126      * A content description briefly describes the view and is primarily used
   9127      * for accessibility support to determine how a view should be presented to
   9128      * the user. In the case of a view with no textual representation, such as
   9129      * {@link android.widget.ImageButton}, a useful content description
   9130      * explains what the view does. For example, an image button with a phone
   9131      * icon that is used to place a call may use "Call" as its content
   9132      * description. An image of a floppy disk that is used to save a file may
   9133      * use "Save".
   9134      *
   9135      * @param contentDescription The content description.
   9136      * @see #getContentDescription()
   9137      * @attr ref android.R.styleable#View_contentDescription
   9138      */
   9139     @RemotableViewMethod
   9140     public void setContentDescription(CharSequence contentDescription) {
   9141         if (mContentDescription == null) {
   9142             if (contentDescription == null) {
   9143                 return;
   9144             }
   9145         } else if (mContentDescription.equals(contentDescription)) {
   9146             return;
   9147         }
   9148         mContentDescription = contentDescription;
   9149         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
   9150         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
   9151             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
   9152             notifySubtreeAccessibilityStateChangedIfNeeded();
   9153         } else {
   9154             notifyViewAccessibilityStateChangedIfNeeded(
   9155                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
   9156         }
   9157     }
   9158 
   9159     /**
   9160      * Sets the id of a view before which this one is visited in accessibility traversal.
   9161      * A screen-reader must visit the content of this view before the content of the one
   9162      * it precedes. For example, if view B is set to be before view A, then a screen-reader
   9163      * will traverse the entire content of B before traversing the entire content of A,
   9164      * regardles of what traversal strategy it is using.
   9165      * <p>
   9166      * Views that do not have specified before/after relationships are traversed in order
   9167      * determined by the screen-reader.
   9168      * </p>
   9169      * <p>
   9170      * Setting that this view is before a view that is not important for accessibility
   9171      * or if this view is not important for accessibility will have no effect as the
   9172      * screen-reader is not aware of unimportant views.
   9173      * </p>
   9174      *
   9175      * @param beforeId The id of a view this one precedes in accessibility traversal.
   9176      *
   9177      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
   9178      *
   9179      * @see #setImportantForAccessibility(int)
   9180      */
   9181     @RemotableViewMethod
   9182     public void setAccessibilityTraversalBefore(int beforeId) {
   9183         if (mAccessibilityTraversalBeforeId == beforeId) {
   9184             return;
   9185         }
   9186         mAccessibilityTraversalBeforeId = beforeId;
   9187         notifyViewAccessibilityStateChangedIfNeeded(
   9188                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9189     }
   9190 
   9191     /**
   9192      * Gets the id of a view before which this one is visited in accessibility traversal.
   9193      *
   9194      * @return The id of a view this one precedes in accessibility traversal if
   9195      *         specified, otherwise {@link #NO_ID}.
   9196      *
   9197      * @see #setAccessibilityTraversalBefore(int)
   9198      */
   9199     public int getAccessibilityTraversalBefore() {
   9200         return mAccessibilityTraversalBeforeId;
   9201     }
   9202 
   9203     /**
   9204      * Sets the id of a view after which this one is visited in accessibility traversal.
   9205      * A screen-reader must visit the content of the other view before the content of this
   9206      * one. For example, if view B is set to be after view A, then a screen-reader
   9207      * will traverse the entire content of A before traversing the entire content of B,
   9208      * regardles of what traversal strategy it is using.
   9209      * <p>
   9210      * Views that do not have specified before/after relationships are traversed in order
   9211      * determined by the screen-reader.
   9212      * </p>
   9213      * <p>
   9214      * Setting that this view is after a view that is not important for accessibility
   9215      * or if this view is not important for accessibility will have no effect as the
   9216      * screen-reader is not aware of unimportant views.
   9217      * </p>
   9218      *
   9219      * @param afterId The id of a view this one succedees in accessibility traversal.
   9220      *
   9221      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
   9222      *
   9223      * @see #setImportantForAccessibility(int)
   9224      */
   9225     @RemotableViewMethod
   9226     public void setAccessibilityTraversalAfter(int afterId) {
   9227         if (mAccessibilityTraversalAfterId == afterId) {
   9228             return;
   9229         }
   9230         mAccessibilityTraversalAfterId = afterId;
   9231         notifyViewAccessibilityStateChangedIfNeeded(
   9232                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9233     }
   9234 
   9235     /**
   9236      * Gets the id of a view after which this one is visited in accessibility traversal.
   9237      *
   9238      * @return The id of a view this one succeedes in accessibility traversal if
   9239      *         specified, otherwise {@link #NO_ID}.
   9240      *
   9241      * @see #setAccessibilityTraversalAfter(int)
   9242      */
   9243     public int getAccessibilityTraversalAfter() {
   9244         return mAccessibilityTraversalAfterId;
   9245     }
   9246 
   9247     /**
   9248      * Gets the id of a view for which this view serves as a label for
   9249      * accessibility purposes.
   9250      *
   9251      * @return The labeled view id.
   9252      */
   9253     @ViewDebug.ExportedProperty(category = "accessibility")
   9254     public int getLabelFor() {
   9255         return mLabelForId;
   9256     }
   9257 
   9258     /**
   9259      * Sets the id of a view for which this view serves as a label for
   9260      * accessibility purposes.
   9261      *
   9262      * @param id The labeled view id.
   9263      */
   9264     @RemotableViewMethod
   9265     public void setLabelFor(@IdRes int id) {
   9266         if (mLabelForId == id) {
   9267             return;
   9268         }
   9269         mLabelForId = id;
   9270         if (mLabelForId != View.NO_ID
   9271                 && mID == View.NO_ID) {
   9272             mID = generateViewId();
   9273         }
   9274         notifyViewAccessibilityStateChangedIfNeeded(
   9275                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9276     }
   9277 
   9278     /**
   9279      * Invoked whenever this view loses focus, either by losing window focus or by losing
   9280      * focus within its window. This method can be used to clear any state tied to the
   9281      * focus. For instance, if a button is held pressed with the trackball and the window
   9282      * loses focus, this method can be used to cancel the press.
   9283      *
   9284      * Subclasses of View overriding this method should always call super.onFocusLost().
   9285      *
   9286      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
   9287      * @see #onWindowFocusChanged(boolean)
   9288      *
   9289      * @hide pending API council approval
   9290      */
   9291     @CallSuper
   9292     protected void onFocusLost() {
   9293         resetPressedState();
   9294     }
   9295 
   9296     private void resetPressedState() {
   9297         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   9298             return;
   9299         }
   9300 
   9301         if (isPressed()) {
   9302             setPressed(false);
   9303 
   9304             if (!mHasPerformedLongPress) {
   9305                 removeLongPressCallback();
   9306             }
   9307         }
   9308     }
   9309 
   9310     /**
   9311      * Returns true if this view has focus
   9312      *
   9313      * @return True if this view has focus, false otherwise.
   9314      */
   9315     @ViewDebug.ExportedProperty(category = "focus")
   9316     public boolean isFocused() {
   9317         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   9318     }
   9319 
   9320     /**
   9321      * Find the view in the hierarchy rooted at this view that currently has
   9322      * focus.
   9323      *
   9324      * @return The view that currently has focus, or null if no focused view can
   9325      *         be found.
   9326      */
   9327     public View findFocus() {
   9328         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
   9329     }
   9330 
   9331     /**
   9332      * Indicates whether this view is one of the set of scrollable containers in
   9333      * its window.
   9334      *
   9335      * @return whether this view is one of the set of scrollable containers in
   9336      * its window
   9337      *
   9338      * @attr ref android.R.styleable#View_isScrollContainer
   9339      */
   9340     public boolean isScrollContainer() {
   9341         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
   9342     }
   9343 
   9344     /**
   9345      * Change whether this view is one of the set of scrollable containers in
   9346      * its window.  This will be used to determine whether the window can
   9347      * resize or must pan when a soft input area is open -- scrollable
   9348      * containers allow the window to use resize mode since the container
   9349      * will appropriately shrink.
   9350      *
   9351      * @attr ref android.R.styleable#View_isScrollContainer
   9352      */
   9353     public void setScrollContainer(boolean isScrollContainer) {
   9354         if (isScrollContainer) {
   9355             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
   9356                 mAttachInfo.mScrollContainers.add(this);
   9357                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   9358             }
   9359             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
   9360         } else {
   9361             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   9362                 mAttachInfo.mScrollContainers.remove(this);
   9363             }
   9364             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
   9365         }
   9366     }
   9367 
   9368     /**
   9369      * Returns the quality of the drawing cache.
   9370      *
   9371      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   9372      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   9373      *
   9374      * @see #setDrawingCacheQuality(int)
   9375      * @see #setDrawingCacheEnabled(boolean)
   9376      * @see #isDrawingCacheEnabled()
   9377      *
   9378      * @attr ref android.R.styleable#View_drawingCacheQuality
   9379      *
   9380      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   9381      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   9382      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   9383      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   9384      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   9385      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   9386      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   9387      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   9388      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   9389      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   9390      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   9391      * reports or unit testing the {@link PixelCopy} API is recommended.
   9392      */
   9393     @Deprecated
   9394     @DrawingCacheQuality
   9395     public int getDrawingCacheQuality() {
   9396         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
   9397     }
   9398 
   9399     /**
   9400      * Set the drawing cache quality of this view. This value is used only when the
   9401      * drawing cache is enabled
   9402      *
   9403      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   9404      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   9405      *
   9406      * @see #getDrawingCacheQuality()
   9407      * @see #setDrawingCacheEnabled(boolean)
   9408      * @see #isDrawingCacheEnabled()
   9409      *
   9410      * @attr ref android.R.styleable#View_drawingCacheQuality
   9411      *
   9412      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   9413      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   9414      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   9415      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   9416      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   9417      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   9418      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   9419      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   9420      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   9421      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   9422      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   9423      * reports or unit testing the {@link PixelCopy} API is recommended.
   9424      */
   9425     @Deprecated
   9426     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
   9427         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
   9428     }
   9429 
   9430     /**
   9431      * Returns whether the screen should remain on, corresponding to the current
   9432      * value of {@link #KEEP_SCREEN_ON}.
   9433      *
   9434      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
   9435      *
   9436      * @see #setKeepScreenOn(boolean)
   9437      *
   9438      * @attr ref android.R.styleable#View_keepScreenOn
   9439      */
   9440     public boolean getKeepScreenOn() {
   9441         return (mViewFlags & KEEP_SCREEN_ON) != 0;
   9442     }
   9443 
   9444     /**
   9445      * Controls whether the screen should remain on, modifying the
   9446      * value of {@link #KEEP_SCREEN_ON}.
   9447      *
   9448      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
   9449      *
   9450      * @see #getKeepScreenOn()
   9451      *
   9452      * @attr ref android.R.styleable#View_keepScreenOn
   9453      */
   9454     public void setKeepScreenOn(boolean keepScreenOn) {
   9455         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
   9456     }
   9457 
   9458     /**
   9459      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   9460      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   9461      *
   9462      * @attr ref android.R.styleable#View_nextFocusLeft
   9463      */
   9464     public int getNextFocusLeftId() {
   9465         return mNextFocusLeftId;
   9466     }
   9467 
   9468     /**
   9469      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   9470      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
   9471      * decide automatically.
   9472      *
   9473      * @attr ref android.R.styleable#View_nextFocusLeft
   9474      */
   9475     public void setNextFocusLeftId(int nextFocusLeftId) {
   9476         mNextFocusLeftId = nextFocusLeftId;
   9477     }
   9478 
   9479     /**
   9480      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   9481      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   9482      *
   9483      * @attr ref android.R.styleable#View_nextFocusRight
   9484      */
   9485     public int getNextFocusRightId() {
   9486         return mNextFocusRightId;
   9487     }
   9488 
   9489     /**
   9490      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   9491      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
   9492      * decide automatically.
   9493      *
   9494      * @attr ref android.R.styleable#View_nextFocusRight
   9495      */
   9496     public void setNextFocusRightId(int nextFocusRightId) {
   9497         mNextFocusRightId = nextFocusRightId;
   9498     }
   9499 
   9500     /**
   9501      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   9502      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   9503      *
   9504      * @attr ref android.R.styleable#View_nextFocusUp
   9505      */
   9506     public int getNextFocusUpId() {
   9507         return mNextFocusUpId;
   9508     }
   9509 
   9510     /**
   9511      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   9512      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
   9513      * decide automatically.
   9514      *
   9515      * @attr ref android.R.styleable#View_nextFocusUp
   9516      */
   9517     public void setNextFocusUpId(int nextFocusUpId) {
   9518         mNextFocusUpId = nextFocusUpId;
   9519     }
   9520 
   9521     /**
   9522      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   9523      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   9524      *
   9525      * @attr ref android.R.styleable#View_nextFocusDown
   9526      */
   9527     public int getNextFocusDownId() {
   9528         return mNextFocusDownId;
   9529     }
   9530 
   9531     /**
   9532      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   9533      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
   9534      * decide automatically.
   9535      *
   9536      * @attr ref android.R.styleable#View_nextFocusDown
   9537      */
   9538     public void setNextFocusDownId(int nextFocusDownId) {
   9539         mNextFocusDownId = nextFocusDownId;
   9540     }
   9541 
   9542     /**
   9543      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   9544      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   9545      *
   9546      * @attr ref android.R.styleable#View_nextFocusForward
   9547      */
   9548     public int getNextFocusForwardId() {
   9549         return mNextFocusForwardId;
   9550     }
   9551 
   9552     /**
   9553      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   9554      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
   9555      * decide automatically.
   9556      *
   9557      * @attr ref android.R.styleable#View_nextFocusForward
   9558      */
   9559     public void setNextFocusForwardId(int nextFocusForwardId) {
   9560         mNextFocusForwardId = nextFocusForwardId;
   9561     }
   9562 
   9563     /**
   9564      * Gets the id of the root of the next keyboard navigation cluster.
   9565      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
   9566      * decide automatically.
   9567      *
   9568      * @attr ref android.R.styleable#View_nextClusterForward
   9569      */
   9570     public int getNextClusterForwardId() {
   9571         return mNextClusterForwardId;
   9572     }
   9573 
   9574     /**
   9575      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
   9576      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
   9577      * decide automatically.
   9578      *
   9579      * @attr ref android.R.styleable#View_nextClusterForward
   9580      */
   9581     public void setNextClusterForwardId(int nextClusterForwardId) {
   9582         mNextClusterForwardId = nextClusterForwardId;
   9583     }
   9584 
   9585     /**
   9586      * Returns the visibility of this view and all of its ancestors
   9587      *
   9588      * @return True if this view and all of its ancestors are {@link #VISIBLE}
   9589      */
   9590     public boolean isShown() {
   9591         View current = this;
   9592         //noinspection ConstantConditions
   9593         do {
   9594             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   9595                 return false;
   9596             }
   9597             ViewParent parent = current.mParent;
   9598             if (parent == null) {
   9599                 return false; // We are not attached to the view root
   9600             }
   9601             if (!(parent instanceof View)) {
   9602                 return true;
   9603             }
   9604             current = (View) parent;
   9605         } while (current != null);
   9606 
   9607         return false;
   9608     }
   9609 
   9610     /**
   9611      * Called by the view hierarchy when the content insets for a window have
   9612      * changed, to allow it to adjust its content to fit within those windows.
   9613      * The content insets tell you the space that the status bar, input method,
   9614      * and other system windows infringe on the application's window.
   9615      *
   9616      * <p>You do not normally need to deal with this function, since the default
   9617      * window decoration given to applications takes care of applying it to the
   9618      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   9619      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
   9620      * and your content can be placed under those system elements.  You can then
   9621      * use this method within your view hierarchy if you have parts of your UI
   9622      * which you would like to ensure are not being covered.
   9623      *
   9624      * <p>The default implementation of this method simply applies the content
   9625      * insets to the view's padding, consuming that content (modifying the
   9626      * insets to be 0), and returning true.  This behavior is off by default, but can
   9627      * be enabled through {@link #setFitsSystemWindows(boolean)}.
   9628      *
   9629      * <p>This function's traversal down the hierarchy is depth-first.  The same content
   9630      * insets object is propagated down the hierarchy, so any changes made to it will
   9631      * be seen by all following views (including potentially ones above in
   9632      * the hierarchy since this is a depth-first traversal).  The first view
   9633      * that returns true will abort the entire traversal.
   9634      *
   9635      * <p>The default implementation works well for a situation where it is
   9636      * used with a container that covers the entire window, allowing it to
   9637      * apply the appropriate insets to its content on all edges.  If you need
   9638      * a more complicated layout (such as two different views fitting system
   9639      * windows, one on the top of the window, and one on the bottom),
   9640      * you can override the method and handle the insets however you would like.
   9641      * Note that the insets provided by the framework are always relative to the
   9642      * far edges of the window, not accounting for the location of the called view
   9643      * within that window.  (In fact when this method is called you do not yet know
   9644      * where the layout will place the view, as it is done before layout happens.)
   9645      *
   9646      * <p>Note: unlike many View methods, there is no dispatch phase to this
   9647      * call.  If you are overriding it in a ViewGroup and want to allow the
   9648      * call to continue to your children, you must be sure to call the super
   9649      * implementation.
   9650      *
   9651      * <p>Here is a sample layout that makes use of fitting system windows
   9652      * to have controls for a video view placed inside of the window decorations
   9653      * that it hides and shows.  This can be used with code like the second
   9654      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
   9655      *
   9656      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
   9657      *
   9658      * @param insets Current content insets of the window.  Prior to
   9659      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
   9660      * the insets or else you and Android will be unhappy.
   9661      *
   9662      * @return {@code true} if this view applied the insets and it should not
   9663      * continue propagating further down the hierarchy, {@code false} otherwise.
   9664      * @see #getFitsSystemWindows()
   9665      * @see #setFitsSystemWindows(boolean)
   9666      * @see #setSystemUiVisibility(int)
   9667      *
   9668      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
   9669      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
   9670      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
   9671      * to implement handling their own insets.
   9672      */
   9673     @Deprecated
   9674     protected boolean fitSystemWindows(Rect insets) {
   9675         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
   9676             if (insets == null) {
   9677                 // Null insets by definition have already been consumed.
   9678                 // This call cannot apply insets since there are none to apply,
   9679                 // so return false.
   9680                 return false;
   9681             }
   9682             // If we're not in the process of dispatching the newer apply insets call,
   9683             // that means we're not in the compatibility path. Dispatch into the newer
   9684             // apply insets path and take things from there.
   9685             try {
   9686                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
   9687                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
   9688             } finally {
   9689                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
   9690             }
   9691         } else {
   9692             // We're being called from the newer apply insets path.
   9693             // Perform the standard fallback behavior.
   9694             return fitSystemWindowsInt(insets);
   9695         }
   9696     }
   9697 
   9698     private boolean fitSystemWindowsInt(Rect insets) {
   9699         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
   9700             mUserPaddingStart = UNDEFINED_PADDING;
   9701             mUserPaddingEnd = UNDEFINED_PADDING;
   9702             Rect localInsets = sThreadLocal.get();
   9703             if (localInsets == null) {
   9704                 localInsets = new Rect();
   9705                 sThreadLocal.set(localInsets);
   9706             }
   9707             boolean res = computeFitSystemWindows(insets, localInsets);
   9708             mUserPaddingLeftInitial = localInsets.left;
   9709             mUserPaddingRightInitial = localInsets.right;
   9710             internalSetPadding(localInsets.left, localInsets.top,
   9711                     localInsets.right, localInsets.bottom);
   9712             return res;
   9713         }
   9714         return false;
   9715     }
   9716 
   9717     /**
   9718      * Called when the view should apply {@link WindowInsets} according to its internal policy.
   9719      *
   9720      * <p>This method should be overridden by views that wish to apply a policy different from or
   9721      * in addition to the default behavior. Clients that wish to force a view subtree
   9722      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
   9723      *
   9724      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
   9725      * it will be called during dispatch instead of this method. The listener may optionally
   9726      * call this method from its own implementation if it wishes to apply the view's default
   9727      * insets policy in addition to its own.</p>
   9728      *
   9729      * <p>Implementations of this method should either return the insets parameter unchanged
   9730      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
   9731      * that this view applied itself. This allows new inset types added in future platform
   9732      * versions to pass through existing implementations unchanged without being erroneously
   9733      * consumed.</p>
   9734      *
   9735      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
   9736      * property is set then the view will consume the system window insets and apply them
   9737      * as padding for the view.</p>
   9738      *
   9739      * @param insets Insets to apply
   9740      * @return The supplied insets with any applied insets consumed
   9741      */
   9742     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
   9743         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
   9744             // We weren't called from within a direct call to fitSystemWindows,
   9745             // call into it as a fallback in case we're in a class that overrides it
   9746             // and has logic to perform.
   9747             if (fitSystemWindows(insets.getSystemWindowInsets())) {
   9748                 return insets.consumeSystemWindowInsets();
   9749             }
   9750         } else {
   9751             // We were called from within a direct call to fitSystemWindows.
   9752             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
   9753                 return insets.consumeSystemWindowInsets();
   9754             }
   9755         }
   9756         return insets;
   9757     }
   9758 
   9759     /**
   9760      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
   9761      * window insets to this view. The listener's
   9762      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   9763      * method will be called instead of the view's
   9764      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   9765      *
   9766      * @param listener Listener to set
   9767      *
   9768      * @see #onApplyWindowInsets(WindowInsets)
   9769      */
   9770     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
   9771         getListenerInfo().mOnApplyWindowInsetsListener = listener;
   9772     }
   9773 
   9774     /**
   9775      * Request to apply the given window insets to this view or another view in its subtree.
   9776      *
   9777      * <p>This method should be called by clients wishing to apply insets corresponding to areas
   9778      * obscured by window decorations or overlays. This can include the status and navigation bars,
   9779      * action bars, input methods and more. New inset categories may be added in the future.
   9780      * The method returns the insets provided minus any that were applied by this view or its
   9781      * children.</p>
   9782      *
   9783      * <p>Clients wishing to provide custom behavior should override the
   9784      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
   9785      * {@link OnApplyWindowInsetsListener} via the
   9786      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
   9787      * method.</p>
   9788      *
   9789      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
   9790      * </p>
   9791      *
   9792      * @param insets Insets to apply
   9793      * @return The provided insets minus the insets that were consumed
   9794      */
   9795     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
   9796         try {
   9797             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
   9798             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
   9799                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
   9800             } else {
   9801                 return onApplyWindowInsets(insets);
   9802             }
   9803         } finally {
   9804             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
   9805         }
   9806     }
   9807 
   9808     /**
   9809      * Compute the view's coordinate within the surface.
   9810      *
   9811      * <p>Computes the coordinates of this view in its surface. The argument
   9812      * must be an array of two integers. After the method returns, the array
   9813      * contains the x and y location in that order.</p>
   9814      * @hide
   9815      * @param location an array of two integers in which to hold the coordinates
   9816      */
   9817     public void getLocationInSurface(@Size(2) int[] location) {
   9818         getLocationInWindow(location);
   9819         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
   9820             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
   9821             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
   9822         }
   9823     }
   9824 
   9825     /**
   9826      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
   9827      * only available if the view is attached.
   9828      *
   9829      * @return WindowInsets from the top of the view hierarchy or null if View is detached
   9830      */
   9831     public WindowInsets getRootWindowInsets() {
   9832         if (mAttachInfo != null) {
   9833             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
   9834         }
   9835         return null;
   9836     }
   9837 
   9838     /**
   9839      * @hide Compute the insets that should be consumed by this view and the ones
   9840      * that should propagate to those under it.
   9841      *
   9842      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
   9843      *
   9844      * @param inoutInsets the insets given to this view
   9845      * @param outLocalInsets the insets that should be applied to this view
   9846      * @deprecated use {@link #computeSystemWindowInsets}
   9847      * @return
   9848      */
   9849     @Deprecated
   9850     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
   9851         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
   9852                 outLocalInsets);
   9853         inoutInsets.set(innerInsets.getSystemWindowInsets());
   9854         return innerInsets.isSystemWindowInsetsConsumed();
   9855     }
   9856 
   9857     /**
   9858      * Compute insets that should be consumed by this view and the ones that should propagate
   9859      * to those under it.
   9860      *
   9861      * @param in Insets currently being processed by this View, likely received as a parameter
   9862      *           to {@link #onApplyWindowInsets(WindowInsets)}.
   9863      * @param outLocalInsets A Rect that will receive the insets that should be consumed
   9864      *                       by this view
   9865      * @return Insets that should be passed along to views under this one
   9866      */
   9867     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
   9868         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
   9869                 || mAttachInfo == null
   9870                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
   9871                 && !mAttachInfo.mOverscanRequested)) {
   9872             outLocalInsets.set(in.getSystemWindowInsets());
   9873             return in.consumeSystemWindowInsets().inset(outLocalInsets);
   9874         } else {
   9875             // The application wants to take care of fitting system window for
   9876             // the content...  however we still need to take care of any overscan here.
   9877             final Rect overscan = mAttachInfo.mOverscanInsets;
   9878             outLocalInsets.set(overscan);
   9879             return in.inset(outLocalInsets);
   9880         }
   9881     }
   9882 
   9883     /**
   9884      * Sets whether or not this view should account for system screen decorations
   9885      * such as the status bar and inset its content; that is, controlling whether
   9886      * the default implementation of {@link #fitSystemWindows(Rect)} will be
   9887      * executed.  See that method for more details.
   9888      *
   9889      * <p>Note that if you are providing your own implementation of
   9890      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
   9891      * flag to true -- your implementation will be overriding the default
   9892      * implementation that checks this flag.
   9893      *
   9894      * @param fitSystemWindows If true, then the default implementation of
   9895      * {@link #fitSystemWindows(Rect)} will be executed.
   9896      *
   9897      * @attr ref android.R.styleable#View_fitsSystemWindows
   9898      * @see #getFitsSystemWindows()
   9899      * @see #fitSystemWindows(Rect)
   9900      * @see #setSystemUiVisibility(int)
   9901      */
   9902     public void setFitsSystemWindows(boolean fitSystemWindows) {
   9903         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
   9904     }
   9905 
   9906     /**
   9907      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
   9908      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
   9909      * will be executed.
   9910      *
   9911      * @return {@code true} if the default implementation of
   9912      * {@link #fitSystemWindows(Rect)} will be executed.
   9913      *
   9914      * @attr ref android.R.styleable#View_fitsSystemWindows
   9915      * @see #setFitsSystemWindows(boolean)
   9916      * @see #fitSystemWindows(Rect)
   9917      * @see #setSystemUiVisibility(int)
   9918      */
   9919     @ViewDebug.ExportedProperty
   9920     public boolean getFitsSystemWindows() {
   9921         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
   9922     }
   9923 
   9924     /** @hide */
   9925     public boolean fitsSystemWindows() {
   9926         return getFitsSystemWindows();
   9927     }
   9928 
   9929     /**
   9930      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
   9931      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
   9932      */
   9933     @Deprecated
   9934     public void requestFitSystemWindows() {
   9935         if (mParent != null) {
   9936             mParent.requestFitSystemWindows();
   9937         }
   9938     }
   9939 
   9940     /**
   9941      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
   9942      */
   9943     public void requestApplyInsets() {
   9944         requestFitSystemWindows();
   9945     }
   9946 
   9947     /**
   9948      * For use by PhoneWindow to make its own system window fitting optional.
   9949      * @hide
   9950      */
   9951     public void makeOptionalFitsSystemWindows() {
   9952         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
   9953     }
   9954 
   9955     /**
   9956      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
   9957      * treat them as such.
   9958      * @hide
   9959      */
   9960     public void getOutsets(Rect outOutsetRect) {
   9961         if (mAttachInfo != null) {
   9962             outOutsetRect.set(mAttachInfo.mOutsets);
   9963         } else {
   9964             outOutsetRect.setEmpty();
   9965         }
   9966     }
   9967 
   9968     /**
   9969      * Returns the visibility status for this view.
   9970      *
   9971      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   9972      * @attr ref android.R.styleable#View_visibility
   9973      */
   9974     @ViewDebug.ExportedProperty(mapping = {
   9975         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
   9976         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
   9977         @ViewDebug.IntToString(from = GONE,      to = "GONE")
   9978     })
   9979     @Visibility
   9980     public int getVisibility() {
   9981         return mViewFlags & VISIBILITY_MASK;
   9982     }
   9983 
   9984     /**
   9985      * Set the visibility state of this view.
   9986      *
   9987      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   9988      * @attr ref android.R.styleable#View_visibility
   9989      */
   9990     @RemotableViewMethod
   9991     public void setVisibility(@Visibility int visibility) {
   9992         setFlags(visibility, VISIBILITY_MASK);
   9993     }
   9994 
   9995     /**
   9996      * Returns the enabled status for this view. The interpretation of the
   9997      * enabled state varies by subclass.
   9998      *
   9999      * @return True if this view is enabled, false otherwise.
   10000      */
   10001     @ViewDebug.ExportedProperty
   10002     public boolean isEnabled() {
   10003         return (mViewFlags & ENABLED_MASK) == ENABLED;
   10004     }
   10005 
   10006     /**
   10007      * Set the enabled state of this view. The interpretation of the enabled
   10008      * state varies by subclass.
   10009      *
   10010      * @param enabled True if this view is enabled, false otherwise.
   10011      */
   10012     @RemotableViewMethod
   10013     public void setEnabled(boolean enabled) {
   10014         if (enabled == isEnabled()) return;
   10015 
   10016         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
   10017 
   10018         /*
   10019          * The View most likely has to change its appearance, so refresh
   10020          * the drawable state.
   10021          */
   10022         refreshDrawableState();
   10023 
   10024         // Invalidate too, since the default behavior for views is to be
   10025         // be drawn at 50% alpha rather than to change the drawable.
   10026         invalidate(true);
   10027 
   10028         if (!enabled) {
   10029             cancelPendingInputEvents();
   10030         }
   10031     }
   10032 
   10033     /**
   10034      * Set whether this view can receive the focus.
   10035      * <p>
   10036      * Setting this to false will also ensure that this view is not focusable
   10037      * in touch mode.
   10038      *
   10039      * @param focusable If true, this view can receive the focus.
   10040      *
   10041      * @see #setFocusableInTouchMode(boolean)
   10042      * @see #setFocusable(int)
   10043      * @attr ref android.R.styleable#View_focusable
   10044      */
   10045     public void setFocusable(boolean focusable) {
   10046         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
   10047     }
   10048 
   10049     /**
   10050      * Sets whether this view can receive focus.
   10051      * <p>
   10052      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
   10053      * automatically based on the view's interactivity. This is the default.
   10054      * <p>
   10055      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
   10056      * in touch mode.
   10057      *
   10058      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
   10059      *                  or {@link #FOCUSABLE_AUTO}.
   10060      * @see #setFocusableInTouchMode(boolean)
   10061      * @attr ref android.R.styleable#View_focusable
   10062      */
   10063     public void setFocusable(@Focusable int focusable) {
   10064         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
   10065             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
   10066         }
   10067         setFlags(focusable, FOCUSABLE_MASK);
   10068     }
   10069 
   10070     /**
   10071      * Set whether this view can receive focus while in touch mode.
   10072      *
   10073      * Setting this to true will also ensure that this view is focusable.
   10074      *
   10075      * @param focusableInTouchMode If true, this view can receive the focus while
   10076      *   in touch mode.
   10077      *
   10078      * @see #setFocusable(boolean)
   10079      * @attr ref android.R.styleable#View_focusableInTouchMode
   10080      */
   10081     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
   10082         // Focusable in touch mode should always be set before the focusable flag
   10083         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
   10084         // which, in touch mode, will not successfully request focus on this view
   10085         // because the focusable in touch mode flag is not set
   10086         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
   10087 
   10088         // Clear FOCUSABLE_AUTO if set.
   10089         if (focusableInTouchMode) {
   10090             // Clears FOCUSABLE_AUTO if set.
   10091             setFlags(FOCUSABLE, FOCUSABLE_MASK);
   10092         }
   10093     }
   10094 
   10095     /**
   10096      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
   10097      * to autofill the view with the user's data.
   10098      *
   10099      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
   10100      * For example, if the application accepts either an username or email address to identify
   10101      * an user.
   10102      *
   10103      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
   10104      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
   10105      * constants such as:
   10106      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
   10107      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
   10108      * {@link #AUTOFILL_HINT_NAME},
   10109      * {@link #AUTOFILL_HINT_PHONE},
   10110      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
   10111      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
   10112      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
   10113      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
   10114      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
   10115      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
   10116      *
   10117      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
   10118      * @attr ref android.R.styleable#View_autofillHints
   10119      */
   10120     public void setAutofillHints(@Nullable String... autofillHints) {
   10121         if (autofillHints == null || autofillHints.length == 0) {
   10122             mAutofillHints = null;
   10123         } else {
   10124             mAutofillHints = autofillHints;
   10125         }
   10126     }
   10127 
   10128     /**
   10129      * @hide
   10130      */
   10131     @TestApi
   10132     public void setAutofilled(boolean isAutofilled) {
   10133         boolean wasChanged = isAutofilled != isAutofilled();
   10134 
   10135         if (wasChanged) {
   10136             if (isAutofilled) {
   10137                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
   10138             } else {
   10139                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
   10140             }
   10141 
   10142             invalidate();
   10143         }
   10144     }
   10145 
   10146     /**
   10147      * Set whether this view should have sound effects enabled for events such as
   10148      * clicking and touching.
   10149      *
   10150      * <p>You may wish to disable sound effects for a view if you already play sounds,
   10151      * for instance, a dial key that plays dtmf tones.
   10152      *
   10153      * @param soundEffectsEnabled whether sound effects are enabled for this view.
   10154      * @see #isSoundEffectsEnabled()
   10155      * @see #playSoundEffect(int)
   10156      * @attr ref android.R.styleable#View_soundEffectsEnabled
   10157      */
   10158     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
   10159         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
   10160     }
   10161 
   10162     /**
   10163      * @return whether this view should have sound effects enabled for events such as
   10164      *     clicking and touching.
   10165      *
   10166      * @see #setSoundEffectsEnabled(boolean)
   10167      * @see #playSoundEffect(int)
   10168      * @attr ref android.R.styleable#View_soundEffectsEnabled
   10169      */
   10170     @ViewDebug.ExportedProperty
   10171     public boolean isSoundEffectsEnabled() {
   10172         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
   10173     }
   10174 
   10175     /**
   10176      * Set whether this view should have haptic feedback for events such as
   10177      * long presses.
   10178      *
   10179      * <p>You may wish to disable haptic feedback if your view already controls
   10180      * its own haptic feedback.
   10181      *
   10182      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
   10183      * @see #isHapticFeedbackEnabled()
   10184      * @see #performHapticFeedback(int)
   10185      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   10186      */
   10187     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
   10188         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
   10189     }
   10190 
   10191     /**
   10192      * @return whether this view should have haptic feedback enabled for events
   10193      * long presses.
   10194      *
   10195      * @see #setHapticFeedbackEnabled(boolean)
   10196      * @see #performHapticFeedback(int)
   10197      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   10198      */
   10199     @ViewDebug.ExportedProperty
   10200     public boolean isHapticFeedbackEnabled() {
   10201         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
   10202     }
   10203 
   10204     /**
   10205      * Returns the layout direction for this view.
   10206      *
   10207      * @return One of {@link #LAYOUT_DIRECTION_LTR},
   10208      *   {@link #LAYOUT_DIRECTION_RTL},
   10209      *   {@link #LAYOUT_DIRECTION_INHERIT} or
   10210      *   {@link #LAYOUT_DIRECTION_LOCALE}.
   10211      *
   10212      * @attr ref android.R.styleable#View_layoutDirection
   10213      *
   10214      * @hide
   10215      */
   10216     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   10217         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
   10218         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
   10219         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
   10220         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
   10221     })
   10222     @LayoutDir
   10223     public int getRawLayoutDirection() {
   10224         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   10225     }
   10226 
   10227     /**
   10228      * Set the layout direction for this view. This will propagate a reset of layout direction
   10229      * resolution to the view's children and resolve layout direction for this view.
   10230      *
   10231      * @param layoutDirection the layout direction to set. Should be one of:
   10232      *
   10233      * {@link #LAYOUT_DIRECTION_LTR},
   10234      * {@link #LAYOUT_DIRECTION_RTL},
   10235      * {@link #LAYOUT_DIRECTION_INHERIT},
   10236      * {@link #LAYOUT_DIRECTION_LOCALE}.
   10237      *
   10238      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
   10239      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   10240      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
   10241      *
   10242      * @attr ref android.R.styleable#View_layoutDirection
   10243      */
   10244     @RemotableViewMethod
   10245     public void setLayoutDirection(@LayoutDir int layoutDirection) {
   10246         if (getRawLayoutDirection() != layoutDirection) {
   10247             // Reset the current layout direction and the resolved one
   10248             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
   10249             resetRtlProperties();
   10250             // Set the new layout direction (filtered)
   10251             mPrivateFlags2 |=
   10252                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
   10253             // We need to resolve all RTL properties as they all depend on layout direction
   10254             resolveRtlPropertiesIfNeeded();
   10255             requestLayout();
   10256             invalidate(true);
   10257         }
   10258     }
   10259 
   10260     /**
   10261      * Returns the resolved layout direction for this view.
   10262      *
   10263      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
   10264      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
   10265      *
   10266      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
   10267      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
   10268      *
   10269      * @attr ref android.R.styleable#View_layoutDirection
   10270      */
   10271     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   10272         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
   10273         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
   10274     })
   10275     @ResolvedLayoutDir
   10276     public int getLayoutDirection() {
   10277         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   10278         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
   10279             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   10280             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
   10281         }
   10282         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
   10283                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
   10284     }
   10285 
   10286     /**
   10287      * Indicates whether or not this view's layout is right-to-left. This is resolved from
   10288      * layout attribute and/or the inherited value from the parent
   10289      *
   10290      * @return true if the layout is right-to-left.
   10291      *
   10292      * @hide
   10293      */
   10294     @ViewDebug.ExportedProperty(category = "layout")
   10295     public boolean isLayoutRtl() {
   10296         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
   10297     }
   10298 
   10299     /**
   10300      * Indicates whether the view is currently tracking transient state that the
   10301      * app should not need to concern itself with saving and restoring, but that
   10302      * the framework should take special note to preserve when possible.
   10303      *
   10304      * <p>A view with transient state cannot be trivially rebound from an external
   10305      * data source, such as an adapter binding item views in a list. This may be
   10306      * because the view is performing an animation, tracking user selection
   10307      * of content, or similar.</p>
   10308      *
   10309      * @return true if the view has transient state
   10310      */
   10311     @ViewDebug.ExportedProperty(category = "layout")
   10312     public boolean hasTransientState() {
   10313         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
   10314     }
   10315 
   10316     /**
   10317      * Set whether this view is currently tracking transient state that the
   10318      * framework should attempt to preserve when possible. This flag is reference counted,
   10319      * so every call to setHasTransientState(true) should be paired with a later call
   10320      * to setHasTransientState(false).
   10321      *
   10322      * <p>A view with transient state cannot be trivially rebound from an external
   10323      * data source, such as an adapter binding item views in a list. This may be
   10324      * because the view is performing an animation, tracking user selection
   10325      * of content, or similar.</p>
   10326      *
   10327      * @param hasTransientState true if this view has transient state
   10328      */
   10329     public void setHasTransientState(boolean hasTransientState) {
   10330         final boolean oldHasTransientState = hasTransientState();
   10331         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
   10332                 mTransientStateCount - 1;
   10333         if (mTransientStateCount < 0) {
   10334             mTransientStateCount = 0;
   10335             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
   10336                     "unmatched pair of setHasTransientState calls");
   10337         } else if ((hasTransientState && mTransientStateCount == 1) ||
   10338                 (!hasTransientState && mTransientStateCount == 0)) {
   10339             // update flag if we've just incremented up from 0 or decremented down to 0
   10340             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
   10341                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
   10342             final boolean newHasTransientState = hasTransientState();
   10343             if (mParent != null && newHasTransientState != oldHasTransientState) {
   10344                 try {
   10345                     mParent.childHasTransientStateChanged(this, newHasTransientState);
   10346                 } catch (AbstractMethodError e) {
   10347                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   10348                             " does not fully implement ViewParent", e);
   10349                 }
   10350             }
   10351         }
   10352     }
   10353 
   10354     /**
   10355      * Returns true if this view is currently attached to a window.
   10356      */
   10357     public boolean isAttachedToWindow() {
   10358         return mAttachInfo != null;
   10359     }
   10360 
   10361     /**
   10362      * Returns true if this view has been through at least one layout since it
   10363      * was last attached to or detached from a window.
   10364      */
   10365     public boolean isLaidOut() {
   10366         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
   10367     }
   10368 
   10369     /**
   10370      * @return {@code true} if laid-out and not about to do another layout.
   10371      */
   10372     boolean isLayoutValid() {
   10373         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
   10374     }
   10375 
   10376     /**
   10377      * If this view doesn't do any drawing on its own, set this flag to
   10378      * allow further optimizations. By default, this flag is not set on
   10379      * View, but could be set on some View subclasses such as ViewGroup.
   10380      *
   10381      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
   10382      * you should clear this flag.
   10383      *
   10384      * @param willNotDraw whether or not this View draw on its own
   10385      */
   10386     public void setWillNotDraw(boolean willNotDraw) {
   10387         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
   10388     }
   10389 
   10390     /**
   10391      * Returns whether or not this View draws on its own.
   10392      *
   10393      * @return true if this view has nothing to draw, false otherwise
   10394      */
   10395     @ViewDebug.ExportedProperty(category = "drawing")
   10396     public boolean willNotDraw() {
   10397         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
   10398     }
   10399 
   10400     /**
   10401      * When a View's drawing cache is enabled, drawing is redirected to an
   10402      * offscreen bitmap. Some views, like an ImageView, must be able to
   10403      * bypass this mechanism if they already draw a single bitmap, to avoid
   10404      * unnecessary usage of the memory.
   10405      *
   10406      * @param willNotCacheDrawing true if this view does not cache its
   10407      *        drawing, false otherwise
   10408      *
   10409      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   10410      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   10411      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   10412      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   10413      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   10414      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   10415      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   10416      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   10417      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   10418      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   10419      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   10420      * reports or unit testing the {@link PixelCopy} API is recommended.
   10421      */
   10422     @Deprecated
   10423     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
   10424         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
   10425     }
   10426 
   10427     /**
   10428      * Returns whether or not this View can cache its drawing or not.
   10429      *
   10430      * @return true if this view does not cache its drawing, false otherwise
   10431      *
   10432      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   10433      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   10434      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   10435      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   10436      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   10437      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   10438      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   10439      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   10440      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   10441      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   10442      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   10443      * reports or unit testing the {@link PixelCopy} API is recommended.
   10444      */
   10445     @ViewDebug.ExportedProperty(category = "drawing")
   10446     @Deprecated
   10447     public boolean willNotCacheDrawing() {
   10448         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
   10449     }
   10450 
   10451     /**
   10452      * Indicates whether this view reacts to click events or not.
   10453      *
   10454      * @return true if the view is clickable, false otherwise
   10455      *
   10456      * @see #setClickable(boolean)
   10457      * @attr ref android.R.styleable#View_clickable
   10458      */
   10459     @ViewDebug.ExportedProperty
   10460     public boolean isClickable() {
   10461         return (mViewFlags & CLICKABLE) == CLICKABLE;
   10462     }
   10463 
   10464     /**
   10465      * Enables or disables click events for this view. When a view
   10466      * is clickable it will change its state to "pressed" on every click.
   10467      * Subclasses should set the view clickable to visually react to
   10468      * user's clicks.
   10469      *
   10470      * @param clickable true to make the view clickable, false otherwise
   10471      *
   10472      * @see #isClickable()
   10473      * @attr ref android.R.styleable#View_clickable
   10474      */
   10475     public void setClickable(boolean clickable) {
   10476         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
   10477     }
   10478 
   10479     /**
   10480      * Indicates whether this view reacts to long click events or not.
   10481      *
   10482      * @return true if the view is long clickable, false otherwise
   10483      *
   10484      * @see #setLongClickable(boolean)
   10485      * @attr ref android.R.styleable#View_longClickable
   10486      */
   10487     public boolean isLongClickable() {
   10488         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   10489     }
   10490 
   10491     /**
   10492      * Enables or disables long click events for this view. When a view is long
   10493      * clickable it reacts to the user holding down the button for a longer
   10494      * duration than a tap. This event can either launch the listener or a
   10495      * context menu.
   10496      *
   10497      * @param longClickable true to make the view long clickable, false otherwise
   10498      * @see #isLongClickable()
   10499      * @attr ref android.R.styleable#View_longClickable
   10500      */
   10501     public void setLongClickable(boolean longClickable) {
   10502         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
   10503     }
   10504 
   10505     /**
   10506      * Indicates whether this view reacts to context clicks or not.
   10507      *
   10508      * @return true if the view is context clickable, false otherwise
   10509      * @see #setContextClickable(boolean)
   10510      * @attr ref android.R.styleable#View_contextClickable
   10511      */
   10512     public boolean isContextClickable() {
   10513         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   10514     }
   10515 
   10516     /**
   10517      * Enables or disables context clicking for this view. This event can launch the listener.
   10518      *
   10519      * @param contextClickable true to make the view react to a context click, false otherwise
   10520      * @see #isContextClickable()
   10521      * @attr ref android.R.styleable#View_contextClickable
   10522      */
   10523     public void setContextClickable(boolean contextClickable) {
   10524         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
   10525     }
   10526 
   10527     /**
   10528      * Sets the pressed state for this view and provides a touch coordinate for
   10529      * animation hinting.
   10530      *
   10531      * @param pressed Pass true to set the View's internal state to "pressed",
   10532      *            or false to reverts the View's internal state from a
   10533      *            previously set "pressed" state.
   10534      * @param x The x coordinate of the touch that caused the press
   10535      * @param y The y coordinate of the touch that caused the press
   10536      */
   10537     private void setPressed(boolean pressed, float x, float y) {
   10538         if (pressed) {
   10539             drawableHotspotChanged(x, y);
   10540         }
   10541 
   10542         setPressed(pressed);
   10543     }
   10544 
   10545     /**
   10546      * Sets the pressed state for this view.
   10547      *
   10548      * @see #isClickable()
   10549      * @see #setClickable(boolean)
   10550      *
   10551      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
   10552      *        the View's internal state from a previously set "pressed" state.
   10553      */
   10554     public void setPressed(boolean pressed) {
   10555         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
   10556 
   10557         if (pressed) {
   10558             mPrivateFlags |= PFLAG_PRESSED;
   10559         } else {
   10560             mPrivateFlags &= ~PFLAG_PRESSED;
   10561         }
   10562 
   10563         if (needsRefresh) {
   10564             refreshDrawableState();
   10565         }
   10566         dispatchSetPressed(pressed);
   10567     }
   10568 
   10569     /**
   10570      * Dispatch setPressed to all of this View's children.
   10571      *
   10572      * @see #setPressed(boolean)
   10573      *
   10574      * @param pressed The new pressed state
   10575      */
   10576     protected void dispatchSetPressed(boolean pressed) {
   10577     }
   10578 
   10579     /**
   10580      * Indicates whether the view is currently in pressed state. Unless
   10581      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
   10582      * the pressed state.
   10583      *
   10584      * @see #setPressed(boolean)
   10585      * @see #isClickable()
   10586      * @see #setClickable(boolean)
   10587      *
   10588      * @return true if the view is currently pressed, false otherwise
   10589      */
   10590     @ViewDebug.ExportedProperty
   10591     public boolean isPressed() {
   10592         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
   10593     }
   10594 
   10595     /**
   10596      * @hide
   10597      * Indicates whether this view will participate in data collection through
   10598      * {@link ViewStructure}.  If true, it will not provide any data
   10599      * for itself or its children.  If false, the normal data collection will be allowed.
   10600      *
   10601      * @return Returns false if assist data collection is not blocked, else true.
   10602      *
   10603      * @see #setAssistBlocked(boolean)
   10604      * @attr ref android.R.styleable#View_assistBlocked
   10605      */
   10606     public boolean isAssistBlocked() {
   10607         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
   10608     }
   10609 
   10610     /**
   10611      * @hide
   10612      * Controls whether assist data collection from this view and its children is enabled
   10613      * (that is, whether {@link #onProvideStructure} and
   10614      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
   10615      * allowing normal assist collection.  Setting this to false will disable assist collection.
   10616      *
   10617      * @param enabled Set to true to <em>disable</em> assist data collection, or false
   10618      * (the default) to allow it.
   10619      *
   10620      * @see #isAssistBlocked()
   10621      * @see #onProvideStructure
   10622      * @see #onProvideVirtualStructure
   10623      * @attr ref android.R.styleable#View_assistBlocked
   10624      */
   10625     public void setAssistBlocked(boolean enabled) {
   10626         if (enabled) {
   10627             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
   10628         } else {
   10629             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
   10630         }
   10631     }
   10632 
   10633     /**
   10634      * Indicates whether this view will save its state (that is,
   10635      * whether its {@link #onSaveInstanceState} method will be called).
   10636      *
   10637      * @return Returns true if the view state saving is enabled, else false.
   10638      *
   10639      * @see #setSaveEnabled(boolean)
   10640      * @attr ref android.R.styleable#View_saveEnabled
   10641      */
   10642     public boolean isSaveEnabled() {
   10643         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
   10644     }
   10645 
   10646     /**
   10647      * Controls whether the saving of this view's state is
   10648      * enabled (that is, whether its {@link #onSaveInstanceState} method
   10649      * will be called).  Note that even if freezing is enabled, the
   10650      * view still must have an id assigned to it (via {@link #setId(int)})
   10651      * for its state to be saved.  This flag can only disable the
   10652      * saving of this view; any child views may still have their state saved.
   10653      *
   10654      * @param enabled Set to false to <em>disable</em> state saving, or true
   10655      * (the default) to allow it.
   10656      *
   10657      * @see #isSaveEnabled()
   10658      * @see #setId(int)
   10659      * @see #onSaveInstanceState()
   10660      * @attr ref android.R.styleable#View_saveEnabled
   10661      */
   10662     public void setSaveEnabled(boolean enabled) {
   10663         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
   10664     }
   10665 
   10666     /**
   10667      * Gets whether the framework should discard touches when the view's
   10668      * window is obscured by another visible window.
   10669      * Refer to the {@link View} security documentation for more details.
   10670      *
   10671      * @return True if touch filtering is enabled.
   10672      *
   10673      * @see #setFilterTouchesWhenObscured(boolean)
   10674      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   10675      */
   10676     @ViewDebug.ExportedProperty
   10677     public boolean getFilterTouchesWhenObscured() {
   10678         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
   10679     }
   10680 
   10681     /**
   10682      * Sets whether the framework should discard touches when the view's
   10683      * window is obscured by another visible window.
   10684      * Refer to the {@link View} security documentation for more details.
   10685      *
   10686      * @param enabled True if touch filtering should be enabled.
   10687      *
   10688      * @see #getFilterTouchesWhenObscured
   10689      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   10690      */
   10691     public void setFilterTouchesWhenObscured(boolean enabled) {
   10692         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
   10693                 FILTER_TOUCHES_WHEN_OBSCURED);
   10694     }
   10695 
   10696     /**
   10697      * Indicates whether the entire hierarchy under this view will save its
   10698      * state when a state saving traversal occurs from its parent.  The default
   10699      * is true; if false, these views will not be saved unless
   10700      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   10701      *
   10702      * @return Returns true if the view state saving from parent is enabled, else false.
   10703      *
   10704      * @see #setSaveFromParentEnabled(boolean)
   10705      */
   10706     public boolean isSaveFromParentEnabled() {
   10707         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
   10708     }
   10709 
   10710     /**
   10711      * Controls whether the entire hierarchy under this view will save its
   10712      * state when a state saving traversal occurs from its parent.  The default
   10713      * is true; if false, these views will not be saved unless
   10714      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   10715      *
   10716      * @param enabled Set to false to <em>disable</em> state saving, or true
   10717      * (the default) to allow it.
   10718      *
   10719      * @see #isSaveFromParentEnabled()
   10720      * @see #setId(int)
   10721      * @see #onSaveInstanceState()
   10722      */
   10723     public void setSaveFromParentEnabled(boolean enabled) {
   10724         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
   10725     }
   10726 
   10727 
   10728     /**
   10729      * Returns whether this View is currently able to take focus.
   10730      *
   10731      * @return True if this view can take focus, or false otherwise.
   10732      */
   10733     @ViewDebug.ExportedProperty(category = "focus")
   10734     public final boolean isFocusable() {
   10735         return FOCUSABLE == (mViewFlags & FOCUSABLE);
   10736     }
   10737 
   10738     /**
   10739      * Returns the focusable setting for this view.
   10740      *
   10741      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
   10742      * @attr ref android.R.styleable#View_focusable
   10743      */
   10744     @ViewDebug.ExportedProperty(mapping = {
   10745             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
   10746             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
   10747             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
   10748             }, category = "focus")
   10749     @Focusable
   10750     public int getFocusable() {
   10751         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
   10752     }
   10753 
   10754     /**
   10755      * When a view is focusable, it may not want to take focus when in touch mode.
   10756      * For example, a button would like focus when the user is navigating via a D-pad
   10757      * so that the user can click on it, but once the user starts touching the screen,
   10758      * the button shouldn't take focus
   10759      * @return Whether the view is focusable in touch mode.
   10760      * @attr ref android.R.styleable#View_focusableInTouchMode
   10761      */
   10762     @ViewDebug.ExportedProperty(category = "focus")
   10763     public final boolean isFocusableInTouchMode() {
   10764         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
   10765     }
   10766 
   10767     /**
   10768      * Returns whether the view should be treated as a focusable unit by screen reader
   10769      * accessibility tools.
   10770      * @see #setScreenReaderFocusable(boolean)
   10771      *
   10772      * @return Whether the view should be treated as a focusable unit by screen reader.
   10773      */
   10774     public boolean isScreenReaderFocusable() {
   10775         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
   10776     }
   10777 
   10778     /**
   10779      * When screen readers (one type of accessibility tool) decide what should be read to the
   10780      * user, they typically look for input focusable ({@link #isFocusable()}) parents of
   10781      * non-focusable text items, and read those focusable parents and their non-focusable children
   10782      * as a unit. In some situations, this behavior is desirable for views that should not take
   10783      * input focus. Setting an item to be screen reader focusable requests that the view be
   10784      * treated as a unit by screen readers without any effect on input focusability. The default
   10785      * value of {@code false} lets screen readers use other signals, like focusable, to determine
   10786      * how to group items.
   10787      *
   10788      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
   10789      *                              accessibility tools.
   10790      */
   10791     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
   10792         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
   10793     }
   10794 
   10795     /**
   10796      * Gets whether this view is a heading for accessibility purposes.
   10797      *
   10798      * @return {@code true} if the view is a heading, {@code false} otherwise.
   10799      *
   10800      * @attr ref android.R.styleable#View_accessibilityHeading
   10801      */
   10802     public boolean isAccessibilityHeading() {
   10803         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
   10804     }
   10805 
   10806     /**
   10807      * Set if view is a heading for a section of content for accessibility purposes.
   10808      *
   10809      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
   10810      *
   10811      * @attr ref android.R.styleable#View_accessibilityHeading
   10812      */
   10813     public void setAccessibilityHeading(boolean isHeading) {
   10814         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
   10815     }
   10816 
   10817     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
   10818         int pflags3 = mPrivateFlags3;
   10819         if (newValue) {
   10820             pflags3 |= mask;
   10821         } else {
   10822             pflags3 &= ~mask;
   10823         }
   10824 
   10825         if (pflags3 != mPrivateFlags3) {
   10826             mPrivateFlags3 = pflags3;
   10827             notifyViewAccessibilityStateChangedIfNeeded(
   10828                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   10829         }
   10830     }
   10831 
   10832     /**
   10833      * Find the nearest view in the specified direction that can take focus.
   10834      * This does not actually give focus to that view.
   10835      *
   10836      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   10837      *
   10838      * @return The nearest focusable in the specified direction, or null if none
   10839      *         can be found.
   10840      */
   10841     public View focusSearch(@FocusRealDirection int direction) {
   10842         if (mParent != null) {
   10843             return mParent.focusSearch(this, direction);
   10844         } else {
   10845             return null;
   10846         }
   10847     }
   10848 
   10849     /**
   10850      * Returns whether this View is a root of a keyboard navigation cluster.
   10851      *
   10852      * @return True if this view is a root of a cluster, or false otherwise.
   10853      * @attr ref android.R.styleable#View_keyboardNavigationCluster
   10854      */
   10855     @ViewDebug.ExportedProperty(category = "focus")
   10856     public final boolean isKeyboardNavigationCluster() {
   10857         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
   10858     }
   10859 
   10860     /**
   10861      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
   10862      * will be ignored.
   10863      *
   10864      * @return the keyboard navigation cluster that this view is in (can be this view)
   10865      *         or {@code null} if not in one
   10866      */
   10867     View findKeyboardNavigationCluster() {
   10868         if (mParent instanceof View) {
   10869             View cluster = ((View) mParent).findKeyboardNavigationCluster();
   10870             if (cluster != null) {
   10871                 return cluster;
   10872             } else if (isKeyboardNavigationCluster()) {
   10873                 return this;
   10874             }
   10875         }
   10876         return null;
   10877     }
   10878 
   10879     /**
   10880      * Set whether this view is a root of a keyboard navigation cluster.
   10881      *
   10882      * @param isCluster If true, this view is a root of a cluster.
   10883      *
   10884      * @attr ref android.R.styleable#View_keyboardNavigationCluster
   10885      */
   10886     public void setKeyboardNavigationCluster(boolean isCluster) {
   10887         if (isCluster) {
   10888             mPrivateFlags3 |= PFLAG3_CLUSTER;
   10889         } else {
   10890             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
   10891         }
   10892     }
   10893 
   10894     /**
   10895      * Sets this View as the one which receives focus the next time cluster navigation jumps
   10896      * to the cluster containing this View. This does NOT change focus even if the cluster
   10897      * containing this view is current.
   10898      *
   10899      * @hide
   10900      */
   10901     @TestApi
   10902     public final void setFocusedInCluster() {
   10903         setFocusedInCluster(findKeyboardNavigationCluster());
   10904     }
   10905 
   10906     private void setFocusedInCluster(View cluster) {
   10907         if (this instanceof ViewGroup) {
   10908             ((ViewGroup) this).mFocusedInCluster = null;
   10909         }
   10910         if (cluster == this) {
   10911             return;
   10912         }
   10913         ViewParent parent = mParent;
   10914         View child = this;
   10915         while (parent instanceof ViewGroup) {
   10916             ((ViewGroup) parent).mFocusedInCluster = child;
   10917             if (parent == cluster) {
   10918                 break;
   10919             }
   10920             child = (View) parent;
   10921             parent = parent.getParent();
   10922         }
   10923     }
   10924 
   10925     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
   10926         if (oldFocus != null) {
   10927             View oldCluster = oldFocus.findKeyboardNavigationCluster();
   10928             View cluster = findKeyboardNavigationCluster();
   10929             if (oldCluster != cluster) {
   10930                 // Going from one cluster to another, so save last-focused.
   10931                 // This covers cluster jumps because they are always FOCUS_DOWN
   10932                 oldFocus.setFocusedInCluster(oldCluster);
   10933                 if (!(oldFocus.mParent instanceof ViewGroup)) {
   10934                     return;
   10935                 }
   10936                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
   10937                     // This is a result of ordered navigation so consider navigation through
   10938                     // the previous cluster "complete" and clear its last-focused memory.
   10939                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
   10940                 } else if (oldFocus instanceof ViewGroup
   10941                         && ((ViewGroup) oldFocus).getDescendantFocusability()
   10942                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
   10943                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
   10944                     // This means oldFocus is not focusable since it obviously has a focusable
   10945                     // child (this). Don't restore focus to it in the future.
   10946                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
   10947                 }
   10948             }
   10949         }
   10950     }
   10951 
   10952     /**
   10953      * Returns whether this View should receive focus when the focus is restored for the view
   10954      * hierarchy containing this view.
   10955      * <p>
   10956      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
   10957      * window or serves as a target of cluster navigation.
   10958      *
   10959      * @see #restoreDefaultFocus()
   10960      *
   10961      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
   10962      * @attr ref android.R.styleable#View_focusedByDefault
   10963      */
   10964     @ViewDebug.ExportedProperty(category = "focus")
   10965     public final boolean isFocusedByDefault() {
   10966         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
   10967     }
   10968 
   10969     /**
   10970      * Sets whether this View should receive focus when the focus is restored for the view
   10971      * hierarchy containing this view.
   10972      * <p>
   10973      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
   10974      * window or serves as a target of cluster navigation.
   10975      *
   10976      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
   10977      *                           {@code false} otherwise.
   10978      *
   10979      * @see #restoreDefaultFocus()
   10980      *
   10981      * @attr ref android.R.styleable#View_focusedByDefault
   10982      */
   10983     public void setFocusedByDefault(boolean isFocusedByDefault) {
   10984         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
   10985             return;
   10986         }
   10987 
   10988         if (isFocusedByDefault) {
   10989             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
   10990         } else {
   10991             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
   10992         }
   10993 
   10994         if (mParent instanceof ViewGroup) {
   10995             if (isFocusedByDefault) {
   10996                 ((ViewGroup) mParent).setDefaultFocus(this);
   10997             } else {
   10998                 ((ViewGroup) mParent).clearDefaultFocus(this);
   10999             }
   11000         }
   11001     }
   11002 
   11003     /**
   11004      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
   11005      *
   11006      * @return {@code true} if this view has default focus, {@code false} otherwise
   11007      */
   11008     boolean hasDefaultFocus() {
   11009         return isFocusedByDefault();
   11010     }
   11011 
   11012     /**
   11013      * Find the nearest keyboard navigation cluster in the specified direction.
   11014      * This does not actually give focus to that cluster.
   11015      *
   11016      * @param currentCluster The starting point of the search. Null means the current cluster is not
   11017      *                       found yet
   11018      * @param direction Direction to look
   11019      *
   11020      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
   11021      *         can be found
   11022      */
   11023     public View keyboardNavigationClusterSearch(View currentCluster,
   11024             @FocusDirection int direction) {
   11025         if (isKeyboardNavigationCluster()) {
   11026             currentCluster = this;
   11027         }
   11028         if (isRootNamespace()) {
   11029             // Root namespace means we should consider ourselves the top of the
   11030             // tree for group searching; otherwise we could be group searching
   11031             // into other tabs.  see LocalActivityManager and TabHost for more info.
   11032             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
   11033                     this, currentCluster, direction);
   11034         } else if (mParent != null) {
   11035             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
   11036         }
   11037         return null;
   11038     }
   11039 
   11040     /**
   11041      * This method is the last chance for the focused view and its ancestors to
   11042      * respond to an arrow key. This is called when the focused view did not
   11043      * consume the key internally, nor could the view system find a new view in
   11044      * the requested direction to give focus to.
   11045      *
   11046      * @param focused The currently focused view.
   11047      * @param direction The direction focus wants to move. One of FOCUS_UP,
   11048      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
   11049      * @return True if the this view consumed this unhandled move.
   11050      */
   11051     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
   11052         return false;
   11053     }
   11054 
   11055     /**
   11056      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
   11057      * have {@link android.R.attr#state_focused} defined in its background.
   11058      *
   11059      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
   11060      *                                      highlight, {@code false} otherwise.
   11061      *
   11062      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
   11063      */
   11064     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
   11065         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
   11066     }
   11067 
   11068     /**
   11069 
   11070     /**
   11071      * Returns whether this View should use a default focus highlight when it gets focused but
   11072      * doesn't have {@link android.R.attr#state_focused} defined in its background.
   11073      *
   11074      * @return True if this View should use a default focus highlight.
   11075      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
   11076      */
   11077     @ViewDebug.ExportedProperty(category = "focus")
   11078     public final boolean getDefaultFocusHighlightEnabled() {
   11079         return mDefaultFocusHighlightEnabled;
   11080     }
   11081 
   11082     /**
   11083      * If a user manually specified the next view id for a particular direction,
   11084      * use the root to look up the view.
   11085      * @param root The root view of the hierarchy containing this view.
   11086      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
   11087      * or FOCUS_BACKWARD.
   11088      * @return The user specified next view, or null if there is none.
   11089      */
   11090     View findUserSetNextFocus(View root, @FocusDirection int direction) {
   11091         switch (direction) {
   11092             case FOCUS_LEFT:
   11093                 if (mNextFocusLeftId == View.NO_ID) return null;
   11094                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
   11095             case FOCUS_RIGHT:
   11096                 if (mNextFocusRightId == View.NO_ID) return null;
   11097                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
   11098             case FOCUS_UP:
   11099                 if (mNextFocusUpId == View.NO_ID) return null;
   11100                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
   11101             case FOCUS_DOWN:
   11102                 if (mNextFocusDownId == View.NO_ID) return null;
   11103                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
   11104             case FOCUS_FORWARD:
   11105                 if (mNextFocusForwardId == View.NO_ID) return null;
   11106                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
   11107             case FOCUS_BACKWARD: {
   11108                 if (mID == View.NO_ID) return null;
   11109                 final int id = mID;
   11110                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
   11111                     @Override
   11112                     public boolean test(View t) {
   11113                         return t.mNextFocusForwardId == id;
   11114                     }
   11115                 });
   11116             }
   11117         }
   11118         return null;
   11119     }
   11120 
   11121     /**
   11122      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
   11123      * use the root to look up the view.
   11124      *
   11125      * @param root the root view of the hierarchy containing this view
   11126      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
   11127      * @return the user-specified next cluster, or {@code null} if there is none
   11128      */
   11129     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
   11130         switch (direction) {
   11131             case FOCUS_FORWARD:
   11132                 if (mNextClusterForwardId == View.NO_ID) return null;
   11133                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
   11134             case FOCUS_BACKWARD: {
   11135                 if (mID == View.NO_ID) return null;
   11136                 final int id = mID;
   11137                 return root.findViewByPredicateInsideOut(this,
   11138                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
   11139             }
   11140         }
   11141         return null;
   11142     }
   11143 
   11144     private View findViewInsideOutShouldExist(View root, int id) {
   11145         if (mMatchIdPredicate == null) {
   11146             mMatchIdPredicate = new MatchIdPredicate();
   11147         }
   11148         mMatchIdPredicate.mId = id;
   11149         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
   11150         if (result == null) {
   11151             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
   11152         }
   11153         return result;
   11154     }
   11155 
   11156     /**
   11157      * Find and return all focusable views that are descendants of this view,
   11158      * possibly including this view if it is focusable itself.
   11159      *
   11160      * @param direction The direction of the focus
   11161      * @return A list of focusable views
   11162      */
   11163     public ArrayList<View> getFocusables(@FocusDirection int direction) {
   11164         ArrayList<View> result = new ArrayList<View>(24);
   11165         addFocusables(result, direction);
   11166         return result;
   11167     }
   11168 
   11169     /**
   11170      * Add any focusable views that are descendants of this view (possibly
   11171      * including this view if it is focusable itself) to views.  If we are in touch mode,
   11172      * only add views that are also focusable in touch mode.
   11173      *
   11174      * @param views Focusable views found so far
   11175      * @param direction The direction of the focus
   11176      */
   11177     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
   11178         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
   11179     }
   11180 
   11181     /**
   11182      * Adds any focusable views that are descendants of this view (possibly
   11183      * including this view if it is focusable itself) to views. This method
   11184      * adds all focusable views regardless if we are in touch mode or
   11185      * only views focusable in touch mode if we are in touch mode or
   11186      * only views that can take accessibility focus if accessibility is enabled
   11187      * depending on the focusable mode parameter.
   11188      *
   11189      * @param views Focusable views found so far or null if all we are interested is
   11190      *        the number of focusables.
   11191      * @param direction The direction of the focus.
   11192      * @param focusableMode The type of focusables to be added.
   11193      *
   11194      * @see #FOCUSABLES_ALL
   11195      * @see #FOCUSABLES_TOUCH_MODE
   11196      */
   11197     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
   11198             @FocusableMode int focusableMode) {
   11199         if (views == null) {
   11200             return;
   11201         }
   11202         if (!canTakeFocus()) {
   11203             return;
   11204         }
   11205         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
   11206                 && !isFocusableInTouchMode()) {
   11207             return;
   11208         }
   11209         views.add(this);
   11210     }
   11211 
   11212     /**
   11213      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
   11214      * including this view if it is a cluster root itself) to views.
   11215      *
   11216      * @param views Keyboard navigation cluster roots found so far
   11217      * @param direction Direction to look
   11218      */
   11219     public void addKeyboardNavigationClusters(
   11220             @NonNull Collection<View> views,
   11221             int direction) {
   11222         if (!isKeyboardNavigationCluster()) {
   11223             return;
   11224         }
   11225         if (!hasFocusable()) {
   11226             return;
   11227         }
   11228         views.add(this);
   11229     }
   11230 
   11231     /**
   11232      * Finds the Views that contain given text. The containment is case insensitive.
   11233      * The search is performed by either the text that the View renders or the content
   11234      * description that describes the view for accessibility purposes and the view does
   11235      * not render or both. Clients can specify how the search is to be performed via
   11236      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
   11237      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
   11238      *
   11239      * @param outViews The output list of matching Views.
   11240      * @param searched The text to match against.
   11241      *
   11242      * @see #FIND_VIEWS_WITH_TEXT
   11243      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
   11244      * @see #setContentDescription(CharSequence)
   11245      */
   11246     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
   11247             @FindViewFlags int flags) {
   11248         if (getAccessibilityNodeProvider() != null) {
   11249             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
   11250                 outViews.add(this);
   11251             }
   11252         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
   11253                 && (searched != null && searched.length() > 0)
   11254                 && (mContentDescription != null && mContentDescription.length() > 0)) {
   11255             String searchedLowerCase = searched.toString().toLowerCase();
   11256             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
   11257             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
   11258                 outViews.add(this);
   11259             }
   11260         }
   11261     }
   11262 
   11263     /**
   11264      * Find and return all touchable views that are descendants of this view,
   11265      * possibly including this view if it is touchable itself.
   11266      *
   11267      * @return A list of touchable views
   11268      */
   11269     public ArrayList<View> getTouchables() {
   11270         ArrayList<View> result = new ArrayList<View>();
   11271         addTouchables(result);
   11272         return result;
   11273     }
   11274 
   11275     /**
   11276      * Add any touchable views that are descendants of this view (possibly
   11277      * including this view if it is touchable itself) to views.
   11278      *
   11279      * @param views Touchable views found so far
   11280      */
   11281     public void addTouchables(ArrayList<View> views) {
   11282         final int viewFlags = mViewFlags;
   11283 
   11284         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   11285                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
   11286                 && (viewFlags & ENABLED_MASK) == ENABLED) {
   11287             views.add(this);
   11288         }
   11289     }
   11290 
   11291     /**
   11292      * Returns whether this View is accessibility focused.
   11293      *
   11294      * @return True if this View is accessibility focused.
   11295      */
   11296     public boolean isAccessibilityFocused() {
   11297         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
   11298     }
   11299 
   11300     /**
   11301      * Call this to try to give accessibility focus to this view.
   11302      *
   11303      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
   11304      * returns false or the view is no visible or the view already has accessibility
   11305      * focus.
   11306      *
   11307      * See also {@link #focusSearch(int)}, which is what you call to say that you
   11308      * have focus, and you want your parent to look for the next one.
   11309      *
   11310      * @return Whether this view actually took accessibility focus.
   11311      *
   11312      * @hide
   11313      */
   11314     public boolean requestAccessibilityFocus() {
   11315         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
   11316         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
   11317             return false;
   11318         }
   11319         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   11320             return false;
   11321         }
   11322         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
   11323             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
   11324             ViewRootImpl viewRootImpl = getViewRootImpl();
   11325             if (viewRootImpl != null) {
   11326                 viewRootImpl.setAccessibilityFocus(this, null);
   11327             }
   11328             invalidate();
   11329             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
   11330             return true;
   11331         }
   11332         return false;
   11333     }
   11334 
   11335     /**
   11336      * Call this to try to clear accessibility focus of this view.
   11337      *
   11338      * See also {@link #focusSearch(int)}, which is what you call to say that you
   11339      * have focus, and you want your parent to look for the next one.
   11340      *
   11341      * @hide
   11342      */
   11343     public void clearAccessibilityFocus() {
   11344         clearAccessibilityFocusNoCallbacks(0);
   11345 
   11346         // Clear the global reference of accessibility focus if this view or
   11347         // any of its descendants had accessibility focus. This will NOT send
   11348         // an event or update internal state if focus is cleared from a
   11349         // descendant view, which may leave views in inconsistent states.
   11350         final ViewRootImpl viewRootImpl = getViewRootImpl();
   11351         if (viewRootImpl != null) {
   11352             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
   11353             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   11354                 viewRootImpl.setAccessibilityFocus(null, null);
   11355             }
   11356         }
   11357     }
   11358 
   11359     private void sendAccessibilityHoverEvent(int eventType) {
   11360         // Since we are not delivering to a client accessibility events from not
   11361         // important views (unless the clinet request that) we need to fire the
   11362         // event from the deepest view exposed to the client. As a consequence if
   11363         // the user crosses a not exposed view the client will see enter and exit
   11364         // of the exposed predecessor followed by and enter and exit of that same
   11365         // predecessor when entering and exiting the not exposed descendant. This
   11366         // is fine since the client has a clear idea which view is hovered at the
   11367         // price of a couple more events being sent. This is a simple and
   11368         // working solution.
   11369         View source = this;
   11370         while (true) {
   11371             if (source.includeForAccessibility()) {
   11372                 source.sendAccessibilityEvent(eventType);
   11373                 return;
   11374             }
   11375             ViewParent parent = source.getParent();
   11376             if (parent instanceof View) {
   11377                 source = (View) parent;
   11378             } else {
   11379                 return;
   11380             }
   11381         }
   11382     }
   11383 
   11384     /**
   11385      * Clears accessibility focus without calling any callback methods
   11386      * normally invoked in {@link #clearAccessibilityFocus()}. This method
   11387      * is used separately from that one for clearing accessibility focus when
   11388      * giving this focus to another view.
   11389      *
   11390      * @param action The action, if any, that led to focus being cleared. Set to
   11391      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
   11392      * the window.
   11393      */
   11394     void clearAccessibilityFocusNoCallbacks(int action) {
   11395         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
   11396             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
   11397             invalidate();
   11398             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   11399                 AccessibilityEvent event = AccessibilityEvent.obtain(
   11400                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
   11401                 event.setAction(action);
   11402                 if (mAccessibilityDelegate != null) {
   11403                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   11404                 } else {
   11405                     sendAccessibilityEventUnchecked(event);
   11406                 }
   11407             }
   11408         }
   11409     }
   11410 
   11411     /**
   11412      * Call this to try to give focus to a specific view or to one of its
   11413      * descendants.
   11414      *
   11415      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   11416      * false), or if it can't be focused due to other conditions (not focusable in touch mode
   11417      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
   11418      * enabled, or has no size).
   11419      *
   11420      * See also {@link #focusSearch(int)}, which is what you call to say that you
   11421      * have focus, and you want your parent to look for the next one.
   11422      *
   11423      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
   11424      * {@link #FOCUS_DOWN} and <code>null</code>.
   11425      *
   11426      * @return Whether this view or one of its descendants actually took focus.
   11427      */
   11428     public final boolean requestFocus() {
   11429         return requestFocus(View.FOCUS_DOWN);
   11430     }
   11431 
   11432     /**
   11433      * This will request focus for whichever View was last focused within this
   11434      * cluster before a focus-jump out of it.
   11435      *
   11436      * @hide
   11437      */
   11438     @TestApi
   11439     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
   11440         // Prioritize focusableByDefault over algorithmic focus selection.
   11441         if (restoreDefaultFocus()) {
   11442             return true;
   11443         }
   11444         return requestFocus(direction);
   11445     }
   11446 
   11447     /**
   11448      * This will request focus for whichever View not in a cluster was last focused before a
   11449      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
   11450      * the "first" focusable view it finds.
   11451      *
   11452      * @hide
   11453      */
   11454     @TestApi
   11455     public boolean restoreFocusNotInCluster() {
   11456         return requestFocus(View.FOCUS_DOWN);
   11457     }
   11458 
   11459     /**
   11460      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
   11461      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
   11462      *
   11463      * @return Whether this view or one of its descendants actually took focus
   11464      */
   11465     public boolean restoreDefaultFocus() {
   11466         return requestFocus(View.FOCUS_DOWN);
   11467     }
   11468 
   11469     /**
   11470      * Call this to try to give focus to a specific view or to one of its
   11471      * descendants and give it a hint about what direction focus is heading.
   11472      *
   11473      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   11474      * false), or if it is focusable and it is not focusable in touch mode
   11475      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   11476      *
   11477      * See also {@link #focusSearch(int)}, which is what you call to say that you
   11478      * have focus, and you want your parent to look for the next one.
   11479      *
   11480      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
   11481      * <code>null</code> set for the previously focused rectangle.
   11482      *
   11483      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   11484      * @return Whether this view or one of its descendants actually took focus.
   11485      */
   11486     public final boolean requestFocus(int direction) {
   11487         return requestFocus(direction, null);
   11488     }
   11489 
   11490     /**
   11491      * Call this to try to give focus to a specific view or to one of its descendants
   11492      * and give it hints about the direction and a specific rectangle that the focus
   11493      * is coming from.  The rectangle can help give larger views a finer grained hint
   11494      * about where focus is coming from, and therefore, where to show selection, or
   11495      * forward focus change internally.
   11496      *
   11497      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   11498      * false), or if it is focusable and it is not focusable in touch mode
   11499      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   11500      *
   11501      * A View will not take focus if it is not visible.
   11502      *
   11503      * A View will not take focus if one of its parents has
   11504      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
   11505      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
   11506      *
   11507      * See also {@link #focusSearch(int)}, which is what you call to say that you
   11508      * have focus, and you want your parent to look for the next one.
   11509      *
   11510      * You may wish to override this method if your custom {@link View} has an internal
   11511      * {@link View} that it wishes to forward the request to.
   11512      *
   11513      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   11514      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
   11515      *        to give a finer grained hint about where focus is coming from.  May be null
   11516      *        if there is no hint.
   11517      * @return Whether this view or one of its descendants actually took focus.
   11518      */
   11519     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
   11520         return requestFocusNoSearch(direction, previouslyFocusedRect);
   11521     }
   11522 
   11523     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
   11524         // need to be focusable
   11525         if (!canTakeFocus()) {
   11526             return false;
   11527         }
   11528 
   11529         // need to be focusable in touch mode if in touch mode
   11530         if (isInTouchMode() &&
   11531             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
   11532                return false;
   11533         }
   11534 
   11535         // need to not have any parents blocking us
   11536         if (hasAncestorThatBlocksDescendantFocus()) {
   11537             return false;
   11538         }
   11539 
   11540         if (!isLayoutValid()) {
   11541             mPrivateFlags |= PFLAG_WANTS_FOCUS;
   11542         } else {
   11543             clearParentsWantFocus();
   11544         }
   11545 
   11546         handleFocusGainInternal(direction, previouslyFocusedRect);
   11547         return true;
   11548     }
   11549 
   11550     void clearParentsWantFocus() {
   11551         if (mParent instanceof View) {
   11552             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
   11553             ((View) mParent).clearParentsWantFocus();
   11554         }
   11555     }
   11556 
   11557     /**
   11558      * Call this to try to give focus to a specific view or to one of its descendants. This is a
   11559      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
   11560      * touch mode to request focus when they are touched.
   11561      *
   11562      * @return Whether this view or one of its descendants actually took focus.
   11563      *
   11564      * @see #isInTouchMode()
   11565      *
   11566      */
   11567     public final boolean requestFocusFromTouch() {
   11568         // Leave touch mode if we need to
   11569         if (isInTouchMode()) {
   11570             ViewRootImpl viewRoot = getViewRootImpl();
   11571             if (viewRoot != null) {
   11572                 viewRoot.ensureTouchMode(false);
   11573             }
   11574         }
   11575         return requestFocus(View.FOCUS_DOWN);
   11576     }
   11577 
   11578     /**
   11579      * @return Whether any ancestor of this view blocks descendant focus.
   11580      */
   11581     private boolean hasAncestorThatBlocksDescendantFocus() {
   11582         final boolean focusableInTouchMode = isFocusableInTouchMode();
   11583         ViewParent ancestor = mParent;
   11584         while (ancestor instanceof ViewGroup) {
   11585             final ViewGroup vgAncestor = (ViewGroup) ancestor;
   11586             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
   11587                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
   11588                 return true;
   11589             } else {
   11590                 ancestor = vgAncestor.getParent();
   11591             }
   11592         }
   11593         return false;
   11594     }
   11595 
   11596     /**
   11597      * Gets the mode for determining whether this View is important for accessibility.
   11598      * A view is important for accessibility if it fires accessibility events and if it
   11599      * is reported to accessibility services that query the screen.
   11600      *
   11601      * @return The mode for determining whether a view is important for accessibility, one
   11602      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
   11603      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
   11604      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
   11605      *
   11606      * @attr ref android.R.styleable#View_importantForAccessibility
   11607      *
   11608      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   11609      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   11610      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   11611      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   11612      */
   11613     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
   11614             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
   11615             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
   11616             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
   11617             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
   11618                     to = "noHideDescendants")
   11619         })
   11620     public int getImportantForAccessibility() {
   11621         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   11622                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   11623     }
   11624 
   11625     /**
   11626      * Sets the live region mode for this view. This indicates to accessibility
   11627      * services whether they should automatically notify the user about changes
   11628      * to the view's content description or text, or to the content descriptions
   11629      * or text of the view's children (where applicable).
   11630      * <p>
   11631      * For example, in a login screen with a TextView that displays an "incorrect
   11632      * password" notification, that view should be marked as a live region with
   11633      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   11634      * <p>
   11635      * To disable change notifications for this view, use
   11636      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
   11637      * mode for most views.
   11638      * <p>
   11639      * To indicate that the user should be notified of changes, use
   11640      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   11641      * <p>
   11642      * If the view's changes should interrupt ongoing speech and notify the user
   11643      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
   11644      *
   11645      * @param mode The live region mode for this view, one of:
   11646      *        <ul>
   11647      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
   11648      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
   11649      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
   11650      *        </ul>
   11651      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   11652      */
   11653     public void setAccessibilityLiveRegion(int mode) {
   11654         if (mode != getAccessibilityLiveRegion()) {
   11655             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   11656             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
   11657                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   11658             notifyViewAccessibilityStateChangedIfNeeded(
   11659                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   11660         }
   11661     }
   11662 
   11663     /**
   11664      * Gets the live region mode for this View.
   11665      *
   11666      * @return The live region mode for the view.
   11667      *
   11668      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   11669      *
   11670      * @see #setAccessibilityLiveRegion(int)
   11671      */
   11672     public int getAccessibilityLiveRegion() {
   11673         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
   11674                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   11675     }
   11676 
   11677     /**
   11678      * Sets how to determine whether this view is important for accessibility
   11679      * which is if it fires accessibility events and if it is reported to
   11680      * accessibility services that query the screen.
   11681      *
   11682      * @param mode How to determine whether this view is important for accessibility.
   11683      *
   11684      * @attr ref android.R.styleable#View_importantForAccessibility
   11685      *
   11686      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   11687      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   11688      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   11689      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   11690      */
   11691     public void setImportantForAccessibility(int mode) {
   11692         final int oldMode = getImportantForAccessibility();
   11693         if (mode != oldMode) {
   11694             final boolean hideDescendants =
   11695                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
   11696 
   11697             // If this node or its descendants are no longer important, try to
   11698             // clear accessibility focus.
   11699             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
   11700                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
   11701                 if (focusHost != null) {
   11702                     focusHost.clearAccessibilityFocus();
   11703                 }
   11704             }
   11705 
   11706             // If we're moving between AUTO and another state, we might not need
   11707             // to send a subtree changed notification. We'll store the computed
   11708             // importance, since we'll need to check it later to make sure.
   11709             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
   11710                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   11711             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
   11712             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   11713             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
   11714                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   11715             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
   11716                 notifySubtreeAccessibilityStateChangedIfNeeded();
   11717             } else {
   11718                 notifyViewAccessibilityStateChangedIfNeeded(
   11719                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   11720             }
   11721         }
   11722     }
   11723 
   11724     /**
   11725      * Returns the view within this view's hierarchy that is hosting
   11726      * accessibility focus.
   11727      *
   11728      * @param searchDescendants whether to search for focus in descendant views
   11729      * @return the view hosting accessibility focus, or {@code null}
   11730      */
   11731     private View findAccessibilityFocusHost(boolean searchDescendants) {
   11732         if (isAccessibilityFocusedViewOrHost()) {
   11733             return this;
   11734         }
   11735 
   11736         if (searchDescendants) {
   11737             final ViewRootImpl viewRoot = getViewRootImpl();
   11738             if (viewRoot != null) {
   11739                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
   11740                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   11741                     return focusHost;
   11742                 }
   11743             }
   11744         }
   11745 
   11746         return null;
   11747     }
   11748 
   11749     /**
   11750      * Computes whether this view should be exposed for accessibility. In
   11751      * general, views that are interactive or provide information are exposed
   11752      * while views that serve only as containers are hidden.
   11753      * <p>
   11754      * If an ancestor of this view has importance
   11755      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
   11756      * returns <code>false</code>.
   11757      * <p>
   11758      * Otherwise, the value is computed according to the view's
   11759      * {@link #getImportantForAccessibility()} value:
   11760      * <ol>
   11761      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
   11762      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
   11763      * </code>
   11764      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
   11765      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
   11766      * view satisfies any of the following:
   11767      * <ul>
   11768      * <li>Is actionable, e.g. {@link #isClickable()},
   11769      * {@link #isLongClickable()}, or {@link #isFocusable()}
   11770      * <li>Has an {@link AccessibilityDelegate}
   11771      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
   11772      * {@link OnKeyListener}, etc.
   11773      * <li>Is an accessibility live region, e.g.
   11774      * {@link #getAccessibilityLiveRegion()} is not
   11775      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
   11776      * </ul>
   11777      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
   11778      * </ol>
   11779      *
   11780      * @return Whether the view is exposed for accessibility.
   11781      * @see #setImportantForAccessibility(int)
   11782      * @see #getImportantForAccessibility()
   11783      */
   11784     public boolean isImportantForAccessibility() {
   11785         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   11786                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   11787         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
   11788                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   11789             return false;
   11790         }
   11791 
   11792         // Check parent mode to ensure we're not hidden.
   11793         ViewParent parent = mParent;
   11794         while (parent instanceof View) {
   11795             if (((View) parent).getImportantForAccessibility()
   11796                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   11797                 return false;
   11798             }
   11799             parent = parent.getParent();
   11800         }
   11801 
   11802         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
   11803                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
   11804                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
   11805                 || isAccessibilityPane();
   11806     }
   11807 
   11808     /**
   11809      * Gets the parent for accessibility purposes. Note that the parent for
   11810      * accessibility is not necessary the immediate parent. It is the first
   11811      * predecessor that is important for accessibility.
   11812      *
   11813      * @return The parent for accessibility purposes.
   11814      */
   11815     public ViewParent getParentForAccessibility() {
   11816         if (mParent instanceof View) {
   11817             View parentView = (View) mParent;
   11818             if (parentView.includeForAccessibility()) {
   11819                 return mParent;
   11820             } else {
   11821                 return mParent.getParentForAccessibility();
   11822             }
   11823         }
   11824         return null;
   11825     }
   11826 
   11827     /** @hide */
   11828     View getSelfOrParentImportantForA11y() {
   11829         if (isImportantForAccessibility()) return this;
   11830         ViewParent parent = getParentForAccessibility();
   11831         if (parent instanceof View) return (View) parent;
   11832         return null;
   11833     }
   11834 
   11835     /**
   11836      * Adds the children of this View relevant for accessibility to the given list
   11837      * as output. Since some Views are not important for accessibility the added
   11838      * child views are not necessarily direct children of this view, rather they are
   11839      * the first level of descendants important for accessibility.
   11840      *
   11841      * @param outChildren The output list that will receive children for accessibility.
   11842      */
   11843     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
   11844 
   11845     }
   11846 
   11847     /**
   11848      * Whether to regard this view for accessibility. A view is regarded for
   11849      * accessibility if it is important for accessibility or the querying
   11850      * accessibility service has explicitly requested that view not
   11851      * important for accessibility are regarded.
   11852      *
   11853      * @return Whether to regard the view for accessibility.
   11854      *
   11855      * @hide
   11856      */
   11857     public boolean includeForAccessibility() {
   11858         if (mAttachInfo != null) {
   11859             return (mAttachInfo.mAccessibilityFetchFlags
   11860                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
   11861                     || isImportantForAccessibility();
   11862         }
   11863         return false;
   11864     }
   11865 
   11866     /**
   11867      * Returns whether the View is considered actionable from
   11868      * accessibility perspective. Such view are important for
   11869      * accessibility.
   11870      *
   11871      * @return True if the view is actionable for accessibility.
   11872      *
   11873      * @hide
   11874      */
   11875     public boolean isActionableForAccessibility() {
   11876         return (isClickable() || isLongClickable() || isFocusable());
   11877     }
   11878 
   11879     /**
   11880      * Returns whether the View has registered callbacks which makes it
   11881      * important for accessibility.
   11882      *
   11883      * @return True if the view is actionable for accessibility.
   11884      */
   11885     private boolean hasListenersForAccessibility() {
   11886         ListenerInfo info = getListenerInfo();
   11887         return mTouchDelegate != null || info.mOnKeyListener != null
   11888                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
   11889                 || info.mOnHoverListener != null || info.mOnDragListener != null;
   11890     }
   11891 
   11892     /**
   11893      * Notifies that the accessibility state of this view changed. The change
   11894      * is local to this view and does not represent structural changes such
   11895      * as children and parent. For example, the view became focusable. The
   11896      * notification is at at most once every
   11897      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   11898      * to avoid unnecessary load to the system. Also once a view has a pending
   11899      * notification this method is a NOP until the notification has been sent.
   11900      *
   11901      * @hide
   11902      */
   11903     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
   11904         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   11905             return;
   11906         }
   11907 
   11908         // Changes to views with a pane title count as window state changes, as the pane title
   11909         // marks them as significant parts of the UI.
   11910         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
   11911                 && isAccessibilityPane()) {
   11912             // If the pane isn't visible, content changed events are sufficient unless we're
   11913             // reporting that the view just disappeared
   11914             if ((getVisibility() == VISIBLE)
   11915                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
   11916                 final AccessibilityEvent event = AccessibilityEvent.obtain();
   11917                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
   11918                 event.setContentChangeTypes(changeType);
   11919                 event.setSource(this);
   11920                 onPopulateAccessibilityEvent(event);
   11921                 if (mParent != null) {
   11922                     try {
   11923                         mParent.requestSendAccessibilityEvent(this, event);
   11924                     } catch (AbstractMethodError e) {
   11925                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
   11926                                 + " does not fully implement ViewParent", e);
   11927                     }
   11928                 }
   11929                 return;
   11930             }
   11931         }
   11932 
   11933         // If this is a live region, we should send a subtree change event
   11934         // from this view immediately. Otherwise, we can let it propagate up.
   11935         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
   11936             final AccessibilityEvent event = AccessibilityEvent.obtain();
   11937             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
   11938             event.setContentChangeTypes(changeType);
   11939             sendAccessibilityEventUnchecked(event);
   11940         } else if (mParent != null) {
   11941             try {
   11942                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
   11943             } catch (AbstractMethodError e) {
   11944                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   11945                         " does not fully implement ViewParent", e);
   11946             }
   11947         }
   11948     }
   11949 
   11950     /**
   11951      * Notifies that the accessibility state of this view changed. The change
   11952      * is *not* local to this view and does represent structural changes such
   11953      * as children and parent. For example, the view size changed. The
   11954      * notification is at at most once every
   11955      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   11956      * to avoid unnecessary load to the system. Also once a view has a pending
   11957      * notification this method is a NOP until the notification has been sent.
   11958      *
   11959      * @hide
   11960      */
   11961     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
   11962         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   11963             return;
   11964         }
   11965 
   11966         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
   11967             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   11968             if (mParent != null) {
   11969                 try {
   11970                     mParent.notifySubtreeAccessibilityStateChanged(
   11971                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
   11972                 } catch (AbstractMethodError e) {
   11973                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   11974                             " does not fully implement ViewParent", e);
   11975                 }
   11976             }
   11977         }
   11978     }
   11979 
   11980     /**
   11981      * Change the visibility of the View without triggering any other changes. This is
   11982      * important for transitions, where visibility changes should not adjust focus or
   11983      * trigger a new layout. This is only used when the visibility has already been changed
   11984      * and we need a transient value during an animation. When the animation completes,
   11985      * the original visibility value is always restored.
   11986      *
   11987      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   11988      * @hide
   11989      */
   11990     public void setTransitionVisibility(@Visibility int visibility) {
   11991         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
   11992     }
   11993 
   11994     /**
   11995      * Reset the flag indicating the accessibility state of the subtree rooted
   11996      * at this view changed.
   11997      */
   11998     void resetSubtreeAccessibilityStateChanged() {
   11999         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   12000     }
   12001 
   12002     /**
   12003      * Report an accessibility action to this view's parents for delegated processing.
   12004      *
   12005      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
   12006      * call this method to delegate an accessibility action to a supporting parent. If the parent
   12007      * returns true from its
   12008      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
   12009      * method this method will return true to signify that the action was consumed.</p>
   12010      *
   12011      * <p>This method is useful for implementing nested scrolling child views. If
   12012      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
   12013      * a custom view implementation may invoke this method to allow a parent to consume the
   12014      * scroll first. If this method returns true the custom view should skip its own scrolling
   12015      * behavior.</p>
   12016      *
   12017      * @param action Accessibility action to delegate
   12018      * @param arguments Optional action arguments
   12019      * @return true if the action was consumed by a parent
   12020      */
   12021     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
   12022         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
   12023             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
   12024                 return true;
   12025             }
   12026         }
   12027         return false;
   12028     }
   12029 
   12030     /**
   12031      * Performs the specified accessibility action on the view. For
   12032      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   12033      * <p>
   12034      * If an {@link AccessibilityDelegate} has been specified via calling
   12035      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   12036      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
   12037      * is responsible for handling this call.
   12038      * </p>
   12039      *
   12040      * <p>The default implementation will delegate
   12041      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
   12042      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
   12043      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
   12044      *
   12045      * @param action The action to perform.
   12046      * @param arguments Optional action arguments.
   12047      * @return Whether the action was performed.
   12048      */
   12049     public boolean performAccessibilityAction(int action, Bundle arguments) {
   12050       if (mAccessibilityDelegate != null) {
   12051           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
   12052       } else {
   12053           return performAccessibilityActionInternal(action, arguments);
   12054       }
   12055     }
   12056 
   12057    /**
   12058     * @see #performAccessibilityAction(int, Bundle)
   12059     *
   12060     * Note: Called from the default {@link AccessibilityDelegate}.
   12061     *
   12062     * @hide
   12063     */
   12064     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
   12065         if (isNestedScrollingEnabled()
   12066                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
   12067                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
   12068                 || action == R.id.accessibilityActionScrollUp
   12069                 || action == R.id.accessibilityActionScrollLeft
   12070                 || action == R.id.accessibilityActionScrollDown
   12071                 || action == R.id.accessibilityActionScrollRight)) {
   12072             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
   12073                 return true;
   12074             }
   12075         }
   12076 
   12077         switch (action) {
   12078             case AccessibilityNodeInfo.ACTION_CLICK: {
   12079                 if (isClickable()) {
   12080                     performClickInternal();
   12081                     return true;
   12082                 }
   12083             } break;
   12084             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
   12085                 if (isLongClickable()) {
   12086                     performLongClick();
   12087                     return true;
   12088                 }
   12089             } break;
   12090             case AccessibilityNodeInfo.ACTION_FOCUS: {
   12091                 if (!hasFocus()) {
   12092                     // Get out of touch mode since accessibility
   12093                     // wants to move focus around.
   12094                     getViewRootImpl().ensureTouchMode(false);
   12095                     return requestFocus();
   12096                 }
   12097             } break;
   12098             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
   12099                 if (hasFocus()) {
   12100                     clearFocus();
   12101                     return !isFocused();
   12102                 }
   12103             } break;
   12104             case AccessibilityNodeInfo.ACTION_SELECT: {
   12105                 if (!isSelected()) {
   12106                     setSelected(true);
   12107                     return isSelected();
   12108                 }
   12109             } break;
   12110             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
   12111                 if (isSelected()) {
   12112                     setSelected(false);
   12113                     return !isSelected();
   12114                 }
   12115             } break;
   12116             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
   12117                 if (!isAccessibilityFocused()) {
   12118                     return requestAccessibilityFocus();
   12119                 }
   12120             } break;
   12121             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
   12122                 if (isAccessibilityFocused()) {
   12123                     clearAccessibilityFocus();
   12124                     return true;
   12125                 }
   12126             } break;
   12127             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
   12128                 if (arguments != null) {
   12129                     final int granularity = arguments.getInt(
   12130                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   12131                     final boolean extendSelection = arguments.getBoolean(
   12132                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   12133                     return traverseAtGranularity(granularity, true, extendSelection);
   12134                 }
   12135             } break;
   12136             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
   12137                 if (arguments != null) {
   12138                     final int granularity = arguments.getInt(
   12139                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   12140                     final boolean extendSelection = arguments.getBoolean(
   12141                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   12142                     return traverseAtGranularity(granularity, false, extendSelection);
   12143                 }
   12144             } break;
   12145             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
   12146                 CharSequence text = getIterableTextForAccessibility();
   12147                 if (text == null) {
   12148                     return false;
   12149                 }
   12150                 final int start = (arguments != null) ? arguments.getInt(
   12151                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
   12152                 final int end = (arguments != null) ? arguments.getInt(
   12153                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
   12154                 // Only cursor position can be specified (selection length == 0)
   12155                 if ((getAccessibilitySelectionStart() != start
   12156                         || getAccessibilitySelectionEnd() != end)
   12157                         && (start == end)) {
   12158                     setAccessibilitySelection(start, end);
   12159                     notifyViewAccessibilityStateChangedIfNeeded(
   12160                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   12161                     return true;
   12162                 }
   12163             } break;
   12164             case R.id.accessibilityActionShowOnScreen: {
   12165                 if (mAttachInfo != null) {
   12166                     final Rect r = mAttachInfo.mTmpInvalRect;
   12167                     getDrawingRect(r);
   12168                     return requestRectangleOnScreen(r, true);
   12169                 }
   12170             } break;
   12171             case R.id.accessibilityActionContextClick: {
   12172                 if (isContextClickable()) {
   12173                     performContextClick();
   12174                     return true;
   12175                 }
   12176             } break;
   12177             case R.id.accessibilityActionShowTooltip: {
   12178                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
   12179                     // Tooltip already showing
   12180                     return false;
   12181                 }
   12182                 return showLongClickTooltip(0, 0);
   12183             }
   12184             case R.id.accessibilityActionHideTooltip: {
   12185                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
   12186                     // No tooltip showing
   12187                     return false;
   12188                 }
   12189                 hideTooltip();
   12190                 return true;
   12191             }
   12192         }
   12193         return false;
   12194     }
   12195 
   12196     private boolean traverseAtGranularity(int granularity, boolean forward,
   12197             boolean extendSelection) {
   12198         CharSequence text = getIterableTextForAccessibility();
   12199         if (text == null || text.length() == 0) {
   12200             return false;
   12201         }
   12202         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
   12203         if (iterator == null) {
   12204             return false;
   12205         }
   12206         int current = getAccessibilitySelectionEnd();
   12207         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   12208             current = forward ? 0 : text.length();
   12209         }
   12210         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
   12211         if (range == null) {
   12212             return false;
   12213         }
   12214         final int segmentStart = range[0];
   12215         final int segmentEnd = range[1];
   12216         int selectionStart;
   12217         int selectionEnd;
   12218         if (extendSelection && isAccessibilitySelectionExtendable()) {
   12219             selectionStart = getAccessibilitySelectionStart();
   12220             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   12221                 selectionStart = forward ? segmentStart : segmentEnd;
   12222             }
   12223             selectionEnd = forward ? segmentEnd : segmentStart;
   12224         } else {
   12225             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
   12226         }
   12227         setAccessibilitySelection(selectionStart, selectionEnd);
   12228         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
   12229                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
   12230         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
   12231         return true;
   12232     }
   12233 
   12234     /**
   12235      * Gets the text reported for accessibility purposes.
   12236      *
   12237      * @return The accessibility text.
   12238      *
   12239      * @hide
   12240      */
   12241     public CharSequence getIterableTextForAccessibility() {
   12242         return getContentDescription();
   12243     }
   12244 
   12245     /**
   12246      * Gets whether accessibility selection can be extended.
   12247      *
   12248      * @return If selection is extensible.
   12249      *
   12250      * @hide
   12251      */
   12252     public boolean isAccessibilitySelectionExtendable() {
   12253         return false;
   12254     }
   12255 
   12256     /**
   12257      * @hide
   12258      */
   12259     public int getAccessibilitySelectionStart() {
   12260         return mAccessibilityCursorPosition;
   12261     }
   12262 
   12263     /**
   12264      * @hide
   12265      */
   12266     public int getAccessibilitySelectionEnd() {
   12267         return getAccessibilitySelectionStart();
   12268     }
   12269 
   12270     /**
   12271      * @hide
   12272      */
   12273     public void setAccessibilitySelection(int start, int end) {
   12274         if (start ==  end && end == mAccessibilityCursorPosition) {
   12275             return;
   12276         }
   12277         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
   12278             mAccessibilityCursorPosition = start;
   12279         } else {
   12280             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   12281         }
   12282         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
   12283     }
   12284 
   12285     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
   12286             int fromIndex, int toIndex) {
   12287         if (mParent == null) {
   12288             return;
   12289         }
   12290         AccessibilityEvent event = AccessibilityEvent.obtain(
   12291                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
   12292         onInitializeAccessibilityEvent(event);
   12293         onPopulateAccessibilityEvent(event);
   12294         event.setFromIndex(fromIndex);
   12295         event.setToIndex(toIndex);
   12296         event.setAction(action);
   12297         event.setMovementGranularity(granularity);
   12298         mParent.requestSendAccessibilityEvent(this, event);
   12299     }
   12300 
   12301     /**
   12302      * @hide
   12303      */
   12304     public TextSegmentIterator getIteratorForGranularity(int granularity) {
   12305         switch (granularity) {
   12306             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
   12307                 CharSequence text = getIterableTextForAccessibility();
   12308                 if (text != null && text.length() > 0) {
   12309                     CharacterTextSegmentIterator iterator =
   12310                         CharacterTextSegmentIterator.getInstance(
   12311                                 mContext.getResources().getConfiguration().locale);
   12312                     iterator.initialize(text.toString());
   12313                     return iterator;
   12314                 }
   12315             } break;
   12316             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
   12317                 CharSequence text = getIterableTextForAccessibility();
   12318                 if (text != null && text.length() > 0) {
   12319                     WordTextSegmentIterator iterator =
   12320                         WordTextSegmentIterator.getInstance(
   12321                                 mContext.getResources().getConfiguration().locale);
   12322                     iterator.initialize(text.toString());
   12323                     return iterator;
   12324                 }
   12325             } break;
   12326             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
   12327                 CharSequence text = getIterableTextForAccessibility();
   12328                 if (text != null && text.length() > 0) {
   12329                     ParagraphTextSegmentIterator iterator =
   12330                         ParagraphTextSegmentIterator.getInstance();
   12331                     iterator.initialize(text.toString());
   12332                     return iterator;
   12333                 }
   12334             } break;
   12335         }
   12336         return null;
   12337     }
   12338 
   12339     /**
   12340      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
   12341      * and {@link #onFinishTemporaryDetach()}.
   12342      *
   12343      * <p>This method always returns {@code true} when called directly or indirectly from
   12344      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
   12345      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
   12346      * <ul>
   12347      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
   12348      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
   12349      * </ul>
   12350      * </p>
   12351      *
   12352      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
   12353      * and {@link #onFinishTemporaryDetach()}.
   12354      */
   12355     public final boolean isTemporarilyDetached() {
   12356         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
   12357     }
   12358 
   12359     /**
   12360      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
   12361      * a container View.
   12362      */
   12363     @CallSuper
   12364     public void dispatchStartTemporaryDetach() {
   12365         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
   12366         notifyEnterOrExitForAutoFillIfNeeded(false);
   12367         onStartTemporaryDetach();
   12368     }
   12369 
   12370     /**
   12371      * This is called when a container is going to temporarily detach a child, with
   12372      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
   12373      * It will either be followed by {@link #onFinishTemporaryDetach()} or
   12374      * {@link #onDetachedFromWindow()} when the container is done.
   12375      */
   12376     public void onStartTemporaryDetach() {
   12377         removeUnsetPressCallback();
   12378         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   12379     }
   12380 
   12381     /**
   12382      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
   12383      * a container View.
   12384      */
   12385     @CallSuper
   12386     public void dispatchFinishTemporaryDetach() {
   12387         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
   12388         onFinishTemporaryDetach();
   12389         if (hasWindowFocus() && hasFocus()) {
   12390             InputMethodManager.getInstance().focusIn(this);
   12391         }
   12392         notifyEnterOrExitForAutoFillIfNeeded(true);
   12393     }
   12394 
   12395     /**
   12396      * Called after {@link #onStartTemporaryDetach} when the container is done
   12397      * changing the view.
   12398      */
   12399     public void onFinishTemporaryDetach() {
   12400     }
   12401 
   12402     /**
   12403      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
   12404      * for this view's window.  Returns null if the view is not currently attached
   12405      * to the window.  Normally you will not need to use this directly, but
   12406      * just use the standard high-level event callbacks like
   12407      * {@link #onKeyDown(int, KeyEvent)}.
   12408      */
   12409     public KeyEvent.DispatcherState getKeyDispatcherState() {
   12410         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
   12411     }
   12412 
   12413     /**
   12414      * Dispatch a key event before it is processed by any input method
   12415      * associated with the view hierarchy.  This can be used to intercept
   12416      * key events in special situations before the IME consumes them; a
   12417      * typical example would be handling the BACK key to update the application's
   12418      * UI instead of allowing the IME to see it and close itself.
   12419      *
   12420      * @param event The key event to be dispatched.
   12421      * @return True if the event was handled, false otherwise.
   12422      */
   12423     public boolean dispatchKeyEventPreIme(KeyEvent event) {
   12424         return onKeyPreIme(event.getKeyCode(), event);
   12425     }
   12426 
   12427     /**
   12428      * Dispatch a key event to the next view on the focus path. This path runs
   12429      * from the top of the view tree down to the currently focused view. If this
   12430      * view has focus, it will dispatch to itself. Otherwise it will dispatch
   12431      * the next node down the focus path. This method also fires any key
   12432      * listeners.
   12433      *
   12434      * @param event The key event to be dispatched.
   12435      * @return True if the event was handled, false otherwise.
   12436      */
   12437     public boolean dispatchKeyEvent(KeyEvent event) {
   12438         if (mInputEventConsistencyVerifier != null) {
   12439             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
   12440         }
   12441 
   12442         // Give any attached key listener a first crack at the event.
   12443         //noinspection SimplifiableIfStatement
   12444         ListenerInfo li = mListenerInfo;
   12445         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   12446                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
   12447             return true;
   12448         }
   12449 
   12450         if (event.dispatch(this, mAttachInfo != null
   12451                 ? mAttachInfo.mKeyDispatchState : null, this)) {
   12452             return true;
   12453         }
   12454 
   12455         if (mInputEventConsistencyVerifier != null) {
   12456             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   12457         }
   12458         return false;
   12459     }
   12460 
   12461     /**
   12462      * Dispatches a key shortcut event.
   12463      *
   12464      * @param event The key event to be dispatched.
   12465      * @return True if the event was handled by the view, false otherwise.
   12466      */
   12467     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   12468         return onKeyShortcut(event.getKeyCode(), event);
   12469     }
   12470 
   12471     /**
   12472      * Pass the touch screen motion event down to the target view, or this
   12473      * view if it is the target.
   12474      *
   12475      * @param event The motion event to be dispatched.
   12476      * @return True if the event was handled by the view, false otherwise.
   12477      */
   12478     public boolean dispatchTouchEvent(MotionEvent event) {
   12479         // If the event should be handled by accessibility focus first.
   12480         if (event.isTargetAccessibilityFocus()) {
   12481             // We don't have focus or no virtual descendant has it, do not handle the event.
   12482             if (!isAccessibilityFocusedViewOrHost()) {
   12483                 return false;
   12484             }
   12485             // We have focus and got the event, then use normal event dispatch.
   12486             event.setTargetAccessibilityFocus(false);
   12487         }
   12488 
   12489         boolean result = false;
   12490 
   12491         if (mInputEventConsistencyVerifier != null) {
   12492             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
   12493         }
   12494 
   12495         final int actionMasked = event.getActionMasked();
   12496         if (actionMasked == MotionEvent.ACTION_DOWN) {
   12497             // Defensive cleanup for new gesture
   12498             stopNestedScroll();
   12499         }
   12500 
   12501         if (onFilterTouchEventForSecurity(event)) {
   12502             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
   12503                 result = true;
   12504             }
   12505             //noinspection SimplifiableIfStatement
   12506             ListenerInfo li = mListenerInfo;
   12507             if (li != null && li.mOnTouchListener != null
   12508                     && (mViewFlags & ENABLED_MASK) == ENABLED
   12509                     && li.mOnTouchListener.onTouch(this, event)) {
   12510                 result = true;
   12511             }
   12512 
   12513             if (!result && onTouchEvent(event)) {
   12514                 result = true;
   12515             }
   12516         }
   12517 
   12518         if (!result && mInputEventConsistencyVerifier != null) {
   12519             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   12520         }
   12521 
   12522         // Clean up after nested scrolls if this is the end of a gesture;
   12523         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
   12524         // of the gesture.
   12525         if (actionMasked == MotionEvent.ACTION_UP ||
   12526                 actionMasked == MotionEvent.ACTION_CANCEL ||
   12527                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
   12528             stopNestedScroll();
   12529         }
   12530 
   12531         return result;
   12532     }
   12533 
   12534     boolean isAccessibilityFocusedViewOrHost() {
   12535         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
   12536                 .getAccessibilityFocusedHost() == this);
   12537     }
   12538 
   12539     /**
   12540      * Filter the touch event to apply security policies.
   12541      *
   12542      * @param event The motion event to be filtered.
   12543      * @return True if the event should be dispatched, false if the event should be dropped.
   12544      *
   12545      * @see #getFilterTouchesWhenObscured
   12546      */
   12547     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
   12548         //noinspection RedundantIfStatement
   12549         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
   12550                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
   12551             // Window is obscured, drop this touch.
   12552             return false;
   12553         }
   12554         return true;
   12555     }
   12556 
   12557     /**
   12558      * Pass a trackball motion event down to the focused view.
   12559      *
   12560      * @param event The motion event to be dispatched.
   12561      * @return True if the event was handled by the view, false otherwise.
   12562      */
   12563     public boolean dispatchTrackballEvent(MotionEvent event) {
   12564         if (mInputEventConsistencyVerifier != null) {
   12565             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
   12566         }
   12567 
   12568         return onTrackballEvent(event);
   12569     }
   12570 
   12571     /**
   12572      * Pass a captured pointer event down to the focused view.
   12573      *
   12574      * @param event The motion event to be dispatched.
   12575      * @return True if the event was handled by the view, false otherwise.
   12576      */
   12577     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
   12578         if (!hasPointerCapture()) {
   12579             return false;
   12580         }
   12581         //noinspection SimplifiableIfStatement
   12582         ListenerInfo li = mListenerInfo;
   12583         if (li != null && li.mOnCapturedPointerListener != null
   12584                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
   12585             return true;
   12586         }
   12587         return onCapturedPointerEvent(event);
   12588     }
   12589 
   12590     /**
   12591      * Dispatch a generic motion event.
   12592      * <p>
   12593      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   12594      * are delivered to the view under the pointer.  All other generic motion events are
   12595      * delivered to the focused view.  Hover events are handled specially and are delivered
   12596      * to {@link #onHoverEvent(MotionEvent)}.
   12597      * </p>
   12598      *
   12599      * @param event The motion event to be dispatched.
   12600      * @return True if the event was handled by the view, false otherwise.
   12601      */
   12602     public boolean dispatchGenericMotionEvent(MotionEvent event) {
   12603         if (mInputEventConsistencyVerifier != null) {
   12604             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
   12605         }
   12606 
   12607         final int source = event.getSource();
   12608         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   12609             final int action = event.getAction();
   12610             if (action == MotionEvent.ACTION_HOVER_ENTER
   12611                     || action == MotionEvent.ACTION_HOVER_MOVE
   12612                     || action == MotionEvent.ACTION_HOVER_EXIT) {
   12613                 if (dispatchHoverEvent(event)) {
   12614                     return true;
   12615                 }
   12616             } else if (dispatchGenericPointerEvent(event)) {
   12617                 return true;
   12618             }
   12619         } else if (dispatchGenericFocusedEvent(event)) {
   12620             return true;
   12621         }
   12622 
   12623         if (dispatchGenericMotionEventInternal(event)) {
   12624             return true;
   12625         }
   12626 
   12627         if (mInputEventConsistencyVerifier != null) {
   12628             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   12629         }
   12630         return false;
   12631     }
   12632 
   12633     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
   12634         //noinspection SimplifiableIfStatement
   12635         ListenerInfo li = mListenerInfo;
   12636         if (li != null && li.mOnGenericMotionListener != null
   12637                 && (mViewFlags & ENABLED_MASK) == ENABLED
   12638                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
   12639             return true;
   12640         }
   12641 
   12642         if (onGenericMotionEvent(event)) {
   12643             return true;
   12644         }
   12645 
   12646         final int actionButton = event.getActionButton();
   12647         switch (event.getActionMasked()) {
   12648             case MotionEvent.ACTION_BUTTON_PRESS:
   12649                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
   12650                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   12651                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   12652                     if (performContextClick(event.getX(), event.getY())) {
   12653                         mInContextButtonPress = true;
   12654                         setPressed(true, event.getX(), event.getY());
   12655                         removeTapCallback();
   12656                         removeLongPressCallback();
   12657                         return true;
   12658                     }
   12659                 }
   12660                 break;
   12661 
   12662             case MotionEvent.ACTION_BUTTON_RELEASE:
   12663                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   12664                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   12665                     mInContextButtonPress = false;
   12666                     mIgnoreNextUpEvent = true;
   12667                 }
   12668                 break;
   12669         }
   12670 
   12671         if (mInputEventConsistencyVerifier != null) {
   12672             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   12673         }
   12674         return false;
   12675     }
   12676 
   12677     /**
   12678      * Dispatch a hover event.
   12679      * <p>
   12680      * Do not call this method directly.
   12681      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   12682      * </p>
   12683      *
   12684      * @param event The motion event to be dispatched.
   12685      * @return True if the event was handled by the view, false otherwise.
   12686      */
   12687     protected boolean dispatchHoverEvent(MotionEvent event) {
   12688         ListenerInfo li = mListenerInfo;
   12689         //noinspection SimplifiableIfStatement
   12690         if (li != null && li.mOnHoverListener != null
   12691                 && (mViewFlags & ENABLED_MASK) == ENABLED
   12692                 && li.mOnHoverListener.onHover(this, event)) {
   12693             return true;
   12694         }
   12695 
   12696         return onHoverEvent(event);
   12697     }
   12698 
   12699     /**
   12700      * Returns true if the view has a child to which it has recently sent
   12701      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
   12702      * it does not have a hovered child, then it must be the innermost hovered view.
   12703      * @hide
   12704      */
   12705     protected boolean hasHoveredChild() {
   12706         return false;
   12707     }
   12708 
   12709     /**
   12710      * Dispatch a generic motion event to the view under the first pointer.
   12711      * <p>
   12712      * Do not call this method directly.
   12713      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   12714      * </p>
   12715      *
   12716      * @param event The motion event to be dispatched.
   12717      * @return True if the event was handled by the view, false otherwise.
   12718      */
   12719     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
   12720         return false;
   12721     }
   12722 
   12723     /**
   12724      * Dispatch a generic motion event to the currently focused view.
   12725      * <p>
   12726      * Do not call this method directly.
   12727      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   12728      * </p>
   12729      *
   12730      * @param event The motion event to be dispatched.
   12731      * @return True if the event was handled by the view, false otherwise.
   12732      */
   12733     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
   12734         return false;
   12735     }
   12736 
   12737     /**
   12738      * Dispatch a pointer event.
   12739      * <p>
   12740      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
   12741      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
   12742      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
   12743      * and should not be expected to handle other pointing device features.
   12744      * </p>
   12745      *
   12746      * @param event The motion event to be dispatched.
   12747      * @return True if the event was handled by the view, false otherwise.
   12748      * @hide
   12749      */
   12750     public final boolean dispatchPointerEvent(MotionEvent event) {
   12751         if (event.isTouchEvent()) {
   12752             return dispatchTouchEvent(event);
   12753         } else {
   12754             return dispatchGenericMotionEvent(event);
   12755         }
   12756     }
   12757 
   12758     /**
   12759      * Called when the window containing this view gains or loses window focus.
   12760      * ViewGroups should override to route to their children.
   12761      *
   12762      * @param hasFocus True if the window containing this view now has focus,
   12763      *        false otherwise.
   12764      */
   12765     public void dispatchWindowFocusChanged(boolean hasFocus) {
   12766         onWindowFocusChanged(hasFocus);
   12767     }
   12768 
   12769     /**
   12770      * Called when the window containing this view gains or loses focus.  Note
   12771      * that this is separate from view focus: to receive key events, both
   12772      * your view and its window must have focus.  If a window is displayed
   12773      * on top of yours that takes input focus, then your own window will lose
   12774      * focus but the view focus will remain unchanged.
   12775      *
   12776      * @param hasWindowFocus True if the window containing this view now has
   12777      *        focus, false otherwise.
   12778      */
   12779     public void onWindowFocusChanged(boolean hasWindowFocus) {
   12780         InputMethodManager imm = InputMethodManager.peekInstance();
   12781         if (!hasWindowFocus) {
   12782             if (isPressed()) {
   12783                 setPressed(false);
   12784             }
   12785             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   12786             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
   12787                 imm.focusOut(this);
   12788             }
   12789             removeLongPressCallback();
   12790             removeTapCallback();
   12791             onFocusLost();
   12792         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
   12793             imm.focusIn(this);
   12794         }
   12795 
   12796         refreshDrawableState();
   12797     }
   12798 
   12799     /**
   12800      * Returns true if this view is in a window that currently has window focus.
   12801      * Note that this is not the same as the view itself having focus.
   12802      *
   12803      * @return True if this view is in a window that currently has window focus.
   12804      */
   12805     public boolean hasWindowFocus() {
   12806         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
   12807     }
   12808 
   12809     /**
   12810      * Dispatch a view visibility change down the view hierarchy.
   12811      * ViewGroups should override to route to their children.
   12812      * @param changedView The view whose visibility changed. Could be 'this' or
   12813      * an ancestor view.
   12814      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   12815      * {@link #INVISIBLE} or {@link #GONE}.
   12816      */
   12817     protected void dispatchVisibilityChanged(@NonNull View changedView,
   12818             @Visibility int visibility) {
   12819         onVisibilityChanged(changedView, visibility);
   12820     }
   12821 
   12822     /**
   12823      * Called when the visibility of the view or an ancestor of the view has
   12824      * changed.
   12825      *
   12826      * @param changedView The view whose visibility changed. May be
   12827      *                    {@code this} or an ancestor view.
   12828      * @param visibility The new visibility, one of {@link #VISIBLE},
   12829      *                   {@link #INVISIBLE} or {@link #GONE}.
   12830      */
   12831     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
   12832     }
   12833 
   12834     /**
   12835      * Dispatch a hint about whether this view is displayed. For instance, when
   12836      * a View moves out of the screen, it might receives a display hint indicating
   12837      * the view is not displayed. Applications should not <em>rely</em> on this hint
   12838      * as there is no guarantee that they will receive one.
   12839      *
   12840      * @param hint A hint about whether or not this view is displayed:
   12841      * {@link #VISIBLE} or {@link #INVISIBLE}.
   12842      */
   12843     public void dispatchDisplayHint(@Visibility int hint) {
   12844         onDisplayHint(hint);
   12845     }
   12846 
   12847     /**
   12848      * Gives this view a hint about whether is displayed or not. For instance, when
   12849      * a View moves out of the screen, it might receives a display hint indicating
   12850      * the view is not displayed. Applications should not <em>rely</em> on this hint
   12851      * as there is no guarantee that they will receive one.
   12852      *
   12853      * @param hint A hint about whether or not this view is displayed:
   12854      * {@link #VISIBLE} or {@link #INVISIBLE}.
   12855      */
   12856     protected void onDisplayHint(@Visibility int hint) {
   12857     }
   12858 
   12859     /**
   12860      * Dispatch a window visibility change down the view hierarchy.
   12861      * ViewGroups should override to route to their children.
   12862      *
   12863      * @param visibility The new visibility of the window.
   12864      *
   12865      * @see #onWindowVisibilityChanged(int)
   12866      */
   12867     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
   12868         onWindowVisibilityChanged(visibility);
   12869     }
   12870 
   12871     /**
   12872      * Called when the window containing has change its visibility
   12873      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
   12874      * that this tells you whether or not your window is being made visible
   12875      * to the window manager; this does <em>not</em> tell you whether or not
   12876      * your window is obscured by other windows on the screen, even if it
   12877      * is itself visible.
   12878      *
   12879      * @param visibility The new visibility of the window.
   12880      */
   12881     protected void onWindowVisibilityChanged(@Visibility int visibility) {
   12882         if (visibility == VISIBLE) {
   12883             initialAwakenScrollBars();
   12884         }
   12885     }
   12886 
   12887     /**
   12888      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
   12889      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
   12890      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
   12891      *
   12892      * @param isVisible true if this view's visibility to the user is uninterrupted by its
   12893      *                  ancestors or by window visibility
   12894      * @return true if this view is visible to the user, not counting clipping or overlapping
   12895      */
   12896     boolean dispatchVisibilityAggregated(boolean isVisible) {
   12897         final boolean thisVisible = getVisibility() == VISIBLE;
   12898         // If we're not visible but something is telling us we are, ignore it.
   12899         if (thisVisible || !isVisible) {
   12900             onVisibilityAggregated(isVisible);
   12901         }
   12902         return thisVisible && isVisible;
   12903     }
   12904 
   12905     /**
   12906      * Called when the user-visibility of this View is potentially affected by a change
   12907      * to this view itself, an ancestor view or the window this view is attached to.
   12908      *
   12909      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
   12910      *                  and this view's window is also visible
   12911      */
   12912     @CallSuper
   12913     public void onVisibilityAggregated(boolean isVisible) {
   12914         // Update our internal visibility tracking so we can detect changes
   12915         boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
   12916         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
   12917                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
   12918         if (isVisible && mAttachInfo != null) {
   12919             initialAwakenScrollBars();
   12920         }
   12921 
   12922         final Drawable dr = mBackground;
   12923         if (dr != null && isVisible != dr.isVisible()) {
   12924             dr.setVisible(isVisible, false);
   12925         }
   12926         final Drawable hl = mDefaultFocusHighlight;
   12927         if (hl != null && isVisible != hl.isVisible()) {
   12928             hl.setVisible(isVisible, false);
   12929         }
   12930         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   12931         if (fg != null && isVisible != fg.isVisible()) {
   12932             fg.setVisible(isVisible, false);
   12933         }
   12934 
   12935         if (isAutofillable()) {
   12936             AutofillManager afm = getAutofillManager();
   12937 
   12938             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
   12939                 if (mVisibilityChangeForAutofillHandler != null) {
   12940                     mVisibilityChangeForAutofillHandler.removeMessages(0);
   12941                 }
   12942 
   12943                 // If the view is in the background but still part of the hierarchy this is called
   12944                 // with isVisible=false. Hence visibility==false requires further checks
   12945                 if (isVisible) {
   12946                     afm.notifyViewVisibilityChanged(this, true);
   12947                 } else {
   12948                     if (mVisibilityChangeForAutofillHandler == null) {
   12949                         mVisibilityChangeForAutofillHandler =
   12950                                 new VisibilityChangeForAutofillHandler(afm, this);
   12951                     }
   12952                     // Let current operation (e.g. removal of the view from the hierarchy)
   12953                     // finish before checking state
   12954                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
   12955                 }
   12956             }
   12957         }
   12958         if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
   12959             if (isVisible != oldVisible) {
   12960                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
   12961                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
   12962                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
   12963             }
   12964         }
   12965     }
   12966 
   12967     /**
   12968      * Returns the current visibility of the window this view is attached to
   12969      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
   12970      *
   12971      * @return Returns the current visibility of the view's window.
   12972      */
   12973     @Visibility
   12974     public int getWindowVisibility() {
   12975         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
   12976     }
   12977 
   12978     /**
   12979      * Retrieve the overall visible display size in which the window this view is
   12980      * attached to has been positioned in.  This takes into account screen
   12981      * decorations above the window, for both cases where the window itself
   12982      * is being position inside of them or the window is being placed under
   12983      * then and covered insets are used for the window to position its content
   12984      * inside.  In effect, this tells you the available area where content can
   12985      * be placed and remain visible to users.
   12986      *
   12987      * <p>This function requires an IPC back to the window manager to retrieve
   12988      * the requested information, so should not be used in performance critical
   12989      * code like drawing.
   12990      *
   12991      * @param outRect Filled in with the visible display frame.  If the view
   12992      * is not attached to a window, this is simply the raw display size.
   12993      */
   12994     public void getWindowVisibleDisplayFrame(Rect outRect) {
   12995         if (mAttachInfo != null) {
   12996             try {
   12997                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   12998             } catch (RemoteException e) {
   12999                 return;
   13000             }
   13001             // XXX This is really broken, and probably all needs to be done
   13002             // in the window manager, and we need to know more about whether
   13003             // we want the area behind or in front of the IME.
   13004             final Rect insets = mAttachInfo.mVisibleInsets;
   13005             outRect.left += insets.left;
   13006             outRect.top += insets.top;
   13007             outRect.right -= insets.right;
   13008             outRect.bottom -= insets.bottom;
   13009             return;
   13010         }
   13011         // The view is not attached to a display so we don't have a context.
   13012         // Make a best guess about the display size.
   13013         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   13014         d.getRectSize(outRect);
   13015     }
   13016 
   13017     /**
   13018      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
   13019      * is currently in without any insets.
   13020      *
   13021      * @hide
   13022      */
   13023     public void getWindowDisplayFrame(Rect outRect) {
   13024         if (mAttachInfo != null) {
   13025             try {
   13026                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   13027             } catch (RemoteException e) {
   13028                 return;
   13029             }
   13030             return;
   13031         }
   13032         // The view is not attached to a display so we don't have a context.
   13033         // Make a best guess about the display size.
   13034         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   13035         d.getRectSize(outRect);
   13036     }
   13037 
   13038     /**
   13039      * Dispatch a notification about a resource configuration change down
   13040      * the view hierarchy.
   13041      * ViewGroups should override to route to their children.
   13042      *
   13043      * @param newConfig The new resource configuration.
   13044      *
   13045      * @see #onConfigurationChanged(android.content.res.Configuration)
   13046      */
   13047     public void dispatchConfigurationChanged(Configuration newConfig) {
   13048         onConfigurationChanged(newConfig);
   13049     }
   13050 
   13051     /**
   13052      * Called when the current configuration of the resources being used
   13053      * by the application have changed.  You can use this to decide when
   13054      * to reload resources that can changed based on orientation and other
   13055      * configuration characteristics.  You only need to use this if you are
   13056      * not relying on the normal {@link android.app.Activity} mechanism of
   13057      * recreating the activity instance upon a configuration change.
   13058      *
   13059      * @param newConfig The new resource configuration.
   13060      */
   13061     protected void onConfigurationChanged(Configuration newConfig) {
   13062     }
   13063 
   13064     /**
   13065      * Private function to aggregate all per-view attributes in to the view
   13066      * root.
   13067      */
   13068     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   13069         performCollectViewAttributes(attachInfo, visibility);
   13070     }
   13071 
   13072     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   13073         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
   13074             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
   13075                 attachInfo.mKeepScreenOn = true;
   13076             }
   13077             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
   13078             ListenerInfo li = mListenerInfo;
   13079             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   13080                 attachInfo.mHasSystemUiListeners = true;
   13081             }
   13082         }
   13083     }
   13084 
   13085     void needGlobalAttributesUpdate(boolean force) {
   13086         final AttachInfo ai = mAttachInfo;
   13087         if (ai != null && !ai.mRecomputeGlobalAttributes) {
   13088             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
   13089                     || ai.mHasSystemUiListeners) {
   13090                 ai.mRecomputeGlobalAttributes = true;
   13091             }
   13092         }
   13093     }
   13094 
   13095     /**
   13096      * Returns whether the device is currently in touch mode.  Touch mode is entered
   13097      * once the user begins interacting with the device by touch, and affects various
   13098      * things like whether focus is always visible to the user.
   13099      *
   13100      * @return Whether the device is in touch mode.
   13101      */
   13102     @ViewDebug.ExportedProperty
   13103     public boolean isInTouchMode() {
   13104         if (mAttachInfo != null) {
   13105             return mAttachInfo.mInTouchMode;
   13106         } else {
   13107             return ViewRootImpl.isInTouchMode();
   13108         }
   13109     }
   13110 
   13111     /**
   13112      * Returns the context the view is running in, through which it can
   13113      * access the current theme, resources, etc.
   13114      *
   13115      * @return The view's Context.
   13116      */
   13117     @ViewDebug.CapturedViewProperty
   13118     public final Context getContext() {
   13119         return mContext;
   13120     }
   13121 
   13122     /**
   13123      * Handle a key event before it is processed by any input method
   13124      * associated with the view hierarchy.  This can be used to intercept
   13125      * key events in special situations before the IME consumes them; a
   13126      * typical example would be handling the BACK key to update the application's
   13127      * UI instead of allowing the IME to see it and close itself.
   13128      *
   13129      * @param keyCode The value in event.getKeyCode().
   13130      * @param event Description of the key event.
   13131      * @return If you handled the event, return true. If you want to allow the
   13132      *         event to be handled by the next receiver, return false.
   13133      */
   13134     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
   13135         return false;
   13136     }
   13137 
   13138     /**
   13139      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
   13140      * KeyEvent.Callback.onKeyDown()}: perform press of the view
   13141      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
   13142      * is released, if the view is enabled and clickable.
   13143      * <p>
   13144      * Key presses in software keyboards will generally NOT trigger this
   13145      * listener, although some may elect to do so in some situations. Do not
   13146      * rely on this to catch software key presses.
   13147      *
   13148      * @param keyCode a key code that represents the button pressed, from
   13149      *                {@link android.view.KeyEvent}
   13150      * @param event the KeyEvent object that defines the button action
   13151      */
   13152     public boolean onKeyDown(int keyCode, KeyEvent event) {
   13153         if (KeyEvent.isConfirmKey(keyCode)) {
   13154             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   13155                 return true;
   13156             }
   13157 
   13158             if (event.getRepeatCount() == 0) {
   13159                 // Long clickable items don't necessarily have to be clickable.
   13160                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
   13161                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   13162                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
   13163                     // For the purposes of menu anchoring and drawable hotspots,
   13164                     // key events are considered to be at the center of the view.
   13165                     final float x = getWidth() / 2f;
   13166                     final float y = getHeight() / 2f;
   13167                     if (clickable) {
   13168                         setPressed(true, x, y);
   13169                     }
   13170                     checkForLongClick(0, x, y);
   13171                     return true;
   13172                 }
   13173             }
   13174         }
   13175 
   13176         return false;
   13177     }
   13178 
   13179     /**
   13180      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
   13181      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
   13182      * the event).
   13183      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   13184      * although some may elect to do so in some situations. Do not rely on this to
   13185      * catch software key presses.
   13186      */
   13187     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
   13188         return false;
   13189     }
   13190 
   13191     /**
   13192      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
   13193      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
   13194      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
   13195      * or {@link KeyEvent#KEYCODE_SPACE} is released.
   13196      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   13197      * although some may elect to do so in some situations. Do not rely on this to
   13198      * catch software key presses.
   13199      *
   13200      * @param keyCode A key code that represents the button pressed, from
   13201      *                {@link android.view.KeyEvent}.
   13202      * @param event   The KeyEvent object that defines the button action.
   13203      */
   13204     public boolean onKeyUp(int keyCode, KeyEvent event) {
   13205         if (KeyEvent.isConfirmKey(keyCode)) {
   13206             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   13207                 return true;
   13208             }
   13209             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
   13210                 setPressed(false);
   13211 
   13212                 if (!mHasPerformedLongPress) {
   13213                     // This is a tap, so remove the longpress check
   13214                     removeLongPressCallback();
   13215                     if (!event.isCanceled()) {
   13216                         return performClickInternal();
   13217                     }
   13218                 }
   13219             }
   13220         }
   13221         return false;
   13222     }
   13223 
   13224     /**
   13225      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   13226      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
   13227      * the event).
   13228      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   13229      * although some may elect to do so in some situations. Do not rely on this to
   13230      * catch software key presses.
   13231      *
   13232      * @param keyCode     A key code that represents the button pressed, from
   13233      *                    {@link android.view.KeyEvent}.
   13234      * @param repeatCount The number of times the action was made.
   13235      * @param event       The KeyEvent object that defines the button action.
   13236      */
   13237     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
   13238         return false;
   13239     }
   13240 
   13241     /**
   13242      * Called on the focused view when a key shortcut event is not handled.
   13243      * Override this method to implement local key shortcuts for the View.
   13244      * Key shortcuts can also be implemented by setting the
   13245      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
   13246      *
   13247      * @param keyCode The value in event.getKeyCode().
   13248      * @param event Description of the key event.
   13249      * @return If you handled the event, return true. If you want to allow the
   13250      *         event to be handled by the next receiver, return false.
   13251      */
   13252     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
   13253         return false;
   13254     }
   13255 
   13256     /**
   13257      * Check whether the called view is a text editor, in which case it
   13258      * would make sense to automatically display a soft input window for
   13259      * it.  Subclasses should override this if they implement
   13260      * {@link #onCreateInputConnection(EditorInfo)} to return true if
   13261      * a call on that method would return a non-null InputConnection, and
   13262      * they are really a first-class editor that the user would normally
   13263      * start typing on when the go into a window containing your view.
   13264      *
   13265      * <p>The default implementation always returns false.  This does
   13266      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
   13267      * will not be called or the user can not otherwise perform edits on your
   13268      * view; it is just a hint to the system that this is not the primary
   13269      * purpose of this view.
   13270      *
   13271      * @return Returns true if this view is a text editor, else false.
   13272      */
   13273     public boolean onCheckIsTextEditor() {
   13274         return false;
   13275     }
   13276 
   13277     /**
   13278      * Create a new InputConnection for an InputMethod to interact
   13279      * with the view.  The default implementation returns null, since it doesn't
   13280      * support input methods.  You can override this to implement such support.
   13281      * This is only needed for views that take focus and text input.
   13282      *
   13283      * <p>When implementing this, you probably also want to implement
   13284      * {@link #onCheckIsTextEditor()} to indicate you will return a
   13285      * non-null InputConnection.</p>
   13286      *
   13287      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
   13288      * object correctly and in its entirety, so that the connected IME can rely
   13289      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
   13290      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
   13291      * must be filled in with the correct cursor position for IMEs to work correctly
   13292      * with your application.</p>
   13293      *
   13294      * @param outAttrs Fill in with attribute information about the connection.
   13295      */
   13296     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   13297         return null;
   13298     }
   13299 
   13300     /**
   13301      * Called by the {@link android.view.inputmethod.InputMethodManager}
   13302      * when a view who is not the current
   13303      * input connection target is trying to make a call on the manager.  The
   13304      * default implementation returns false; you can override this to return
   13305      * true for certain views if you are performing InputConnection proxying
   13306      * to them.
   13307      * @param view The View that is making the InputMethodManager call.
   13308      * @return Return true to allow the call, false to reject.
   13309      */
   13310     public boolean checkInputConnectionProxy(View view) {
   13311         return false;
   13312     }
   13313 
   13314     /**
   13315      * Show the context menu for this view. It is not safe to hold on to the
   13316      * menu after returning from this method.
   13317      *
   13318      * You should normally not overload this method. Overload
   13319      * {@link #onCreateContextMenu(ContextMenu)} or define an
   13320      * {@link OnCreateContextMenuListener} to add items to the context menu.
   13321      *
   13322      * @param menu The context menu to populate
   13323      */
   13324     public void createContextMenu(ContextMenu menu) {
   13325         ContextMenuInfo menuInfo = getContextMenuInfo();
   13326 
   13327         // Sets the current menu info so all items added to menu will have
   13328         // my extra info set.
   13329         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
   13330 
   13331         onCreateContextMenu(menu);
   13332         ListenerInfo li = mListenerInfo;
   13333         if (li != null && li.mOnCreateContextMenuListener != null) {
   13334             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
   13335         }
   13336 
   13337         // Clear the extra information so subsequent items that aren't mine don't
   13338         // have my extra info.
   13339         ((MenuBuilder)menu).setCurrentMenuInfo(null);
   13340 
   13341         if (mParent != null) {
   13342             mParent.createContextMenu(menu);
   13343         }
   13344     }
   13345 
   13346     /**
   13347      * Views should implement this if they have extra information to associate
   13348      * with the context menu. The return result is supplied as a parameter to
   13349      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
   13350      * callback.
   13351      *
   13352      * @return Extra information about the item for which the context menu
   13353      *         should be shown. This information will vary across different
   13354      *         subclasses of View.
   13355      */
   13356     protected ContextMenuInfo getContextMenuInfo() {
   13357         return null;
   13358     }
   13359 
   13360     /**
   13361      * Views should implement this if the view itself is going to add items to
   13362      * the context menu.
   13363      *
   13364      * @param menu the context menu to populate
   13365      */
   13366     protected void onCreateContextMenu(ContextMenu menu) {
   13367     }
   13368 
   13369     /**
   13370      * Implement this method to handle trackball motion events.  The
   13371      * <em>relative</em> movement of the trackball since the last event
   13372      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
   13373      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
   13374      * that a movement of 1 corresponds to the user pressing one DPAD key (so
   13375      * they will often be fractional values, representing the more fine-grained
   13376      * movement information available from a trackball).
   13377      *
   13378      * @param event The motion event.
   13379      * @return True if the event was handled, false otherwise.
   13380      */
   13381     public boolean onTrackballEvent(MotionEvent event) {
   13382         return false;
   13383     }
   13384 
   13385     /**
   13386      * Implement this method to handle generic motion events.
   13387      * <p>
   13388      * Generic motion events describe joystick movements, mouse hovers, track pad
   13389      * touches, scroll wheel movements and other input events.  The
   13390      * {@link MotionEvent#getSource() source} of the motion event specifies
   13391      * the class of input that was received.  Implementations of this method
   13392      * must examine the bits in the source before processing the event.
   13393      * The following code example shows how this is done.
   13394      * </p><p>
   13395      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   13396      * are delivered to the view under the pointer.  All other generic motion events are
   13397      * delivered to the focused view.
   13398      * </p>
   13399      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
   13400      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
   13401      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
   13402      *             // process the joystick movement...
   13403      *             return true;
   13404      *         }
   13405      *     }
   13406      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
   13407      *         switch (event.getAction()) {
   13408      *             case MotionEvent.ACTION_HOVER_MOVE:
   13409      *                 // process the mouse hover movement...
   13410      *                 return true;
   13411      *             case MotionEvent.ACTION_SCROLL:
   13412      *                 // process the scroll wheel movement...
   13413      *                 return true;
   13414      *         }
   13415      *     }
   13416      *     return super.onGenericMotionEvent(event);
   13417      * }</pre>
   13418      *
   13419      * @param event The generic motion event being processed.
   13420      * @return True if the event was handled, false otherwise.
   13421      */
   13422     public boolean onGenericMotionEvent(MotionEvent event) {
   13423         return false;
   13424     }
   13425 
   13426     /**
   13427      * Implement this method to handle hover events.
   13428      * <p>
   13429      * This method is called whenever a pointer is hovering into, over, or out of the
   13430      * bounds of a view and the view is not currently being touched.
   13431      * Hover events are represented as pointer events with action
   13432      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
   13433      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
   13434      * </p>
   13435      * <ul>
   13436      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
   13437      * when the pointer enters the bounds of the view.</li>
   13438      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
   13439      * when the pointer has already entered the bounds of the view and has moved.</li>
   13440      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
   13441      * when the pointer has exited the bounds of the view or when the pointer is
   13442      * about to go down due to a button click, tap, or similar user action that
   13443      * causes the view to be touched.</li>
   13444      * </ul>
   13445      * <p>
   13446      * The view should implement this method to return true to indicate that it is
   13447      * handling the hover event, such as by changing its drawable state.
   13448      * </p><p>
   13449      * The default implementation calls {@link #setHovered} to update the hovered state
   13450      * of the view when a hover enter or hover exit event is received, if the view
   13451      * is enabled and is clickable.  The default implementation also sends hover
   13452      * accessibility events.
   13453      * </p>
   13454      *
   13455      * @param event The motion event that describes the hover.
   13456      * @return True if the view handled the hover event.
   13457      *
   13458      * @see #isHovered
   13459      * @see #setHovered
   13460      * @see #onHoverChanged
   13461      */
   13462     public boolean onHoverEvent(MotionEvent event) {
   13463         // The root view may receive hover (or touch) events that are outside the bounds of
   13464         // the window.  This code ensures that we only send accessibility events for
   13465         // hovers that are actually within the bounds of the root view.
   13466         final int action = event.getActionMasked();
   13467         if (!mSendingHoverAccessibilityEvents) {
   13468             if ((action == MotionEvent.ACTION_HOVER_ENTER
   13469                     || action == MotionEvent.ACTION_HOVER_MOVE)
   13470                     && !hasHoveredChild()
   13471                     && pointInView(event.getX(), event.getY())) {
   13472                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
   13473                 mSendingHoverAccessibilityEvents = true;
   13474             }
   13475         } else {
   13476             if (action == MotionEvent.ACTION_HOVER_EXIT
   13477                     || (action == MotionEvent.ACTION_MOVE
   13478                             && !pointInView(event.getX(), event.getY()))) {
   13479                 mSendingHoverAccessibilityEvents = false;
   13480                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
   13481             }
   13482         }
   13483 
   13484         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
   13485                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
   13486                 && isOnScrollbar(event.getX(), event.getY())) {
   13487             awakenScrollBars();
   13488         }
   13489 
   13490         // If we consider ourself hoverable, or if we we're already hovered,
   13491         // handle changing state in response to ENTER and EXIT events.
   13492         if (isHoverable() || isHovered()) {
   13493             switch (action) {
   13494                 case MotionEvent.ACTION_HOVER_ENTER:
   13495                     setHovered(true);
   13496                     break;
   13497                 case MotionEvent.ACTION_HOVER_EXIT:
   13498                     setHovered(false);
   13499                     break;
   13500             }
   13501 
   13502             // Dispatch the event to onGenericMotionEvent before returning true.
   13503             // This is to provide compatibility with existing applications that
   13504             // handled HOVER_MOVE events in onGenericMotionEvent and that would
   13505             // break because of the new default handling for hoverable views
   13506             // in onHoverEvent.
   13507             // Note that onGenericMotionEvent will be called by default when
   13508             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
   13509             dispatchGenericMotionEventInternal(event);
   13510             // The event was already handled by calling setHovered(), so always
   13511             // return true.
   13512             return true;
   13513         }
   13514 
   13515         return false;
   13516     }
   13517 
   13518     /**
   13519      * Returns true if the view should handle {@link #onHoverEvent}
   13520      * by calling {@link #setHovered} to change its hovered state.
   13521      *
   13522      * @return True if the view is hoverable.
   13523      */
   13524     private boolean isHoverable() {
   13525         final int viewFlags = mViewFlags;
   13526         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   13527             return false;
   13528         }
   13529 
   13530         return (viewFlags & CLICKABLE) == CLICKABLE
   13531                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   13532                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   13533     }
   13534 
   13535     /**
   13536      * Returns true if the view is currently hovered.
   13537      *
   13538      * @return True if the view is currently hovered.
   13539      *
   13540      * @see #setHovered
   13541      * @see #onHoverChanged
   13542      */
   13543     @ViewDebug.ExportedProperty
   13544     public boolean isHovered() {
   13545         return (mPrivateFlags & PFLAG_HOVERED) != 0;
   13546     }
   13547 
   13548     /**
   13549      * Sets whether the view is currently hovered.
   13550      * <p>
   13551      * Calling this method also changes the drawable state of the view.  This
   13552      * enables the view to react to hover by using different drawable resources
   13553      * to change its appearance.
   13554      * </p><p>
   13555      * The {@link #onHoverChanged} method is called when the hovered state changes.
   13556      * </p>
   13557      *
   13558      * @param hovered True if the view is hovered.
   13559      *
   13560      * @see #isHovered
   13561      * @see #onHoverChanged
   13562      */
   13563     public void setHovered(boolean hovered) {
   13564         if (hovered) {
   13565             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
   13566                 mPrivateFlags |= PFLAG_HOVERED;
   13567                 refreshDrawableState();
   13568                 onHoverChanged(true);
   13569             }
   13570         } else {
   13571             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
   13572                 mPrivateFlags &= ~PFLAG_HOVERED;
   13573                 refreshDrawableState();
   13574                 onHoverChanged(false);
   13575             }
   13576         }
   13577     }
   13578 
   13579     /**
   13580      * Implement this method to handle hover state changes.
   13581      * <p>
   13582      * This method is called whenever the hover state changes as a result of a
   13583      * call to {@link #setHovered}.
   13584      * </p>
   13585      *
   13586      * @param hovered The current hover state, as returned by {@link #isHovered}.
   13587      *
   13588      * @see #isHovered
   13589      * @see #setHovered
   13590      */
   13591     public void onHoverChanged(boolean hovered) {
   13592     }
   13593 
   13594     /**
   13595      * Handles scroll bar dragging by mouse input.
   13596      *
   13597      * @hide
   13598      * @param event The motion event.
   13599      *
   13600      * @return true if the event was handled as a scroll bar dragging, false otherwise.
   13601      */
   13602     protected boolean handleScrollBarDragging(MotionEvent event) {
   13603         if (mScrollCache == null) {
   13604             return false;
   13605         }
   13606         final float x = event.getX();
   13607         final float y = event.getY();
   13608         final int action = event.getAction();
   13609         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
   13610                 && action != MotionEvent.ACTION_DOWN)
   13611                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
   13612                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
   13613             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
   13614             return false;
   13615         }
   13616 
   13617         switch (action) {
   13618             case MotionEvent.ACTION_MOVE:
   13619                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
   13620                     return false;
   13621                 }
   13622                 if (mScrollCache.mScrollBarDraggingState
   13623                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
   13624                     final Rect bounds = mScrollCache.mScrollBarBounds;
   13625                     getVerticalScrollBarBounds(bounds, null);
   13626                     final int range = computeVerticalScrollRange();
   13627                     final int offset = computeVerticalScrollOffset();
   13628                     final int extent = computeVerticalScrollExtent();
   13629 
   13630                     final int thumbLength = ScrollBarUtils.getThumbLength(
   13631                             bounds.height(), bounds.width(), extent, range);
   13632                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
   13633                             bounds.height(), thumbLength, extent, range, offset);
   13634 
   13635                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
   13636                     final float maxThumbOffset = bounds.height() - thumbLength;
   13637                     final float newThumbOffset =
   13638                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
   13639                     final int height = getHeight();
   13640                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
   13641                             && height > 0 && extent > 0) {
   13642                         final int newY = Math.round((range - extent)
   13643                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
   13644                         if (newY != getScrollY()) {
   13645                             mScrollCache.mScrollBarDraggingPos = y;
   13646                             setScrollY(newY);
   13647                         }
   13648                     }
   13649                     return true;
   13650                 }
   13651                 if (mScrollCache.mScrollBarDraggingState
   13652                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
   13653                     final Rect bounds = mScrollCache.mScrollBarBounds;
   13654                     getHorizontalScrollBarBounds(bounds, null);
   13655                     final int range = computeHorizontalScrollRange();
   13656                     final int offset = computeHorizontalScrollOffset();
   13657                     final int extent = computeHorizontalScrollExtent();
   13658 
   13659                     final int thumbLength = ScrollBarUtils.getThumbLength(
   13660                             bounds.width(), bounds.height(), extent, range);
   13661                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
   13662                             bounds.width(), thumbLength, extent, range, offset);
   13663 
   13664                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
   13665                     final float maxThumbOffset = bounds.width() - thumbLength;
   13666                     final float newThumbOffset =
   13667                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
   13668                     final int width = getWidth();
   13669                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
   13670                             && width > 0 && extent > 0) {
   13671                         final int newX = Math.round((range - extent)
   13672                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
   13673                         if (newX != getScrollX()) {
   13674                             mScrollCache.mScrollBarDraggingPos = x;
   13675                             setScrollX(newX);
   13676                         }
   13677                     }
   13678                     return true;
   13679                 }
   13680             case MotionEvent.ACTION_DOWN:
   13681                 if (mScrollCache.state == ScrollabilityCache.OFF) {
   13682                     return false;
   13683                 }
   13684                 if (isOnVerticalScrollbarThumb(x, y)) {
   13685                     mScrollCache.mScrollBarDraggingState =
   13686                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
   13687                     mScrollCache.mScrollBarDraggingPos = y;
   13688                     return true;
   13689                 }
   13690                 if (isOnHorizontalScrollbarThumb(x, y)) {
   13691                     mScrollCache.mScrollBarDraggingState =
   13692                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
   13693                     mScrollCache.mScrollBarDraggingPos = x;
   13694                     return true;
   13695                 }
   13696         }
   13697         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
   13698         return false;
   13699     }
   13700 
   13701     /**
   13702      * Implement this method to handle touch screen motion events.
   13703      * <p>
   13704      * If this method is used to detect click actions, it is recommended that
   13705      * the actions be performed by implementing and calling
   13706      * {@link #performClick()}. This will ensure consistent system behavior,
   13707      * including:
   13708      * <ul>
   13709      * <li>obeying click sound preferences
   13710      * <li>dispatching OnClickListener calls
   13711      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
   13712      * accessibility features are enabled
   13713      * </ul>
   13714      *
   13715      * @param event The motion event.
   13716      * @return True if the event was handled, false otherwise.
   13717      */
   13718     public boolean onTouchEvent(MotionEvent event) {
   13719         final float x = event.getX();
   13720         final float y = event.getY();
   13721         final int viewFlags = mViewFlags;
   13722         final int action = event.getAction();
   13723 
   13724         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
   13725                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   13726                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   13727 
   13728         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   13729             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
   13730                 setPressed(false);
   13731             }
   13732             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   13733             // A disabled view that is clickable still consumes the touch
   13734             // events, it just doesn't respond to them.
   13735             return clickable;
   13736         }
   13737         if (mTouchDelegate != null) {
   13738             if (mTouchDelegate.onTouchEvent(event)) {
   13739                 return true;
   13740             }
   13741         }
   13742 
   13743         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
   13744             switch (action) {
   13745                 case MotionEvent.ACTION_UP:
   13746                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   13747                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
   13748                         handleTooltipUp();
   13749                     }
   13750                     if (!clickable) {
   13751                         removeTapCallback();
   13752                         removeLongPressCallback();
   13753                         mInContextButtonPress = false;
   13754                         mHasPerformedLongPress = false;
   13755                         mIgnoreNextUpEvent = false;
   13756                         break;
   13757                     }
   13758                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
   13759                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
   13760                         // take focus if we don't have it already and we should in
   13761                         // touch mode.
   13762                         boolean focusTaken = false;
   13763                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
   13764                             focusTaken = requestFocus();
   13765                         }
   13766 
   13767                         if (prepressed) {
   13768                             // The button is being released before we actually
   13769                             // showed it as pressed.  Make it show the pressed
   13770                             // state now (before scheduling the click) to ensure
   13771                             // the user sees it.
   13772                             setPressed(true, x, y);
   13773                         }
   13774 
   13775                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
   13776                             // This is a tap, so remove the longpress check
   13777                             removeLongPressCallback();
   13778 
   13779                             // Only perform take click actions if we were in the pressed state
   13780                             if (!focusTaken) {
   13781                                 // Use a Runnable and post this rather than calling
   13782                                 // performClick directly. This lets other visual state
   13783                                 // of the view update before click actions start.
   13784                                 if (mPerformClick == null) {
   13785                                     mPerformClick = new PerformClick();
   13786                                 }
   13787                                 if (!post(mPerformClick)) {
   13788                                     performClickInternal();
   13789                                 }
   13790                             }
   13791                         }
   13792 
   13793                         if (mUnsetPressedState == null) {
   13794                             mUnsetPressedState = new UnsetPressedState();
   13795                         }
   13796 
   13797                         if (prepressed) {
   13798                             postDelayed(mUnsetPressedState,
   13799                                     ViewConfiguration.getPressedStateDuration());
   13800                         } else if (!post(mUnsetPressedState)) {
   13801                             // If the post failed, unpress right now
   13802                             mUnsetPressedState.run();
   13803                         }
   13804 
   13805                         removeTapCallback();
   13806                     }
   13807                     mIgnoreNextUpEvent = false;
   13808                     break;
   13809 
   13810                 case MotionEvent.ACTION_DOWN:
   13811                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
   13812                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
   13813                     }
   13814                     mHasPerformedLongPress = false;
   13815 
   13816                     if (!clickable) {
   13817                         checkForLongClick(0, x, y);
   13818                         break;
   13819                     }
   13820 
   13821                     if (performButtonActionOnTouchDown(event)) {
   13822                         break;
   13823                     }
   13824 
   13825                     // Walk up the hierarchy to determine if we're inside a scrolling container.
   13826                     boolean isInScrollingContainer = isInScrollingContainer();
   13827 
   13828                     // For views inside a scrolling container, delay the pressed feedback for
   13829                     // a short period in case this is a scroll.
   13830                     if (isInScrollingContainer) {
   13831                         mPrivateFlags |= PFLAG_PREPRESSED;
   13832                         if (mPendingCheckForTap == null) {
   13833                             mPendingCheckForTap = new CheckForTap();
   13834                         }
   13835                         mPendingCheckForTap.x = event.getX();
   13836                         mPendingCheckForTap.y = event.getY();
   13837                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
   13838                     } else {
   13839                         // Not inside a scrolling container, so show the feedback right away
   13840                         setPressed(true, x, y);
   13841                         checkForLongClick(0, x, y);
   13842                     }
   13843                     break;
   13844 
   13845                 case MotionEvent.ACTION_CANCEL:
   13846                     if (clickable) {
   13847                         setPressed(false);
   13848                     }
   13849                     removeTapCallback();
   13850                     removeLongPressCallback();
   13851                     mInContextButtonPress = false;
   13852                     mHasPerformedLongPress = false;
   13853                     mIgnoreNextUpEvent = false;
   13854                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   13855                     break;
   13856 
   13857                 case MotionEvent.ACTION_MOVE:
   13858                     if (clickable) {
   13859                         drawableHotspotChanged(x, y);
   13860                     }
   13861 
   13862                     // Be lenient about moving outside of buttons
   13863                     if (!pointInView(x, y, mTouchSlop)) {
   13864                         // Outside button
   13865                         // Remove any future long press/tap checks
   13866                         removeTapCallback();
   13867                         removeLongPressCallback();
   13868                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
   13869                             setPressed(false);
   13870                         }
   13871                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   13872                     }
   13873                     break;
   13874             }
   13875 
   13876             return true;
   13877         }
   13878 
   13879         return false;
   13880     }
   13881 
   13882     /**
   13883      * @hide
   13884      */
   13885     public boolean isInScrollingContainer() {
   13886         ViewParent p = getParent();
   13887         while (p != null && p instanceof ViewGroup) {
   13888             if (((ViewGroup) p).shouldDelayChildPressedState()) {
   13889                 return true;
   13890             }
   13891             p = p.getParent();
   13892         }
   13893         return false;
   13894     }
   13895 
   13896     /**
   13897      * Remove the longpress detection timer.
   13898      */
   13899     private void removeLongPressCallback() {
   13900         if (mPendingCheckForLongPress != null) {
   13901             removeCallbacks(mPendingCheckForLongPress);
   13902         }
   13903     }
   13904 
   13905     /**
   13906      * Remove the pending click action
   13907      */
   13908     private void removePerformClickCallback() {
   13909         if (mPerformClick != null) {
   13910             removeCallbacks(mPerformClick);
   13911         }
   13912     }
   13913 
   13914     /**
   13915      * Remove the prepress detection timer.
   13916      */
   13917     private void removeUnsetPressCallback() {
   13918         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
   13919             setPressed(false);
   13920             removeCallbacks(mUnsetPressedState);
   13921         }
   13922     }
   13923 
   13924     /**
   13925      * Remove the tap detection timer.
   13926      */
   13927     private void removeTapCallback() {
   13928         if (mPendingCheckForTap != null) {
   13929             mPrivateFlags &= ~PFLAG_PREPRESSED;
   13930             removeCallbacks(mPendingCheckForTap);
   13931         }
   13932     }
   13933 
   13934     /**
   13935      * Cancels a pending long press.  Your subclass can use this if you
   13936      * want the context menu to come up if the user presses and holds
   13937      * at the same place, but you don't want it to come up if they press
   13938      * and then move around enough to cause scrolling.
   13939      */
   13940     public void cancelLongPress() {
   13941         removeLongPressCallback();
   13942 
   13943         /*
   13944          * The prepressed state handled by the tap callback is a display
   13945          * construct, but the tap callback will post a long press callback
   13946          * less its own timeout. Remove it here.
   13947          */
   13948         removeTapCallback();
   13949     }
   13950 
   13951     /**
   13952      * Sets the TouchDelegate for this View.
   13953      */
   13954     public void setTouchDelegate(TouchDelegate delegate) {
   13955         mTouchDelegate = delegate;
   13956     }
   13957 
   13958     /**
   13959      * Gets the TouchDelegate for this View.
   13960      */
   13961     public TouchDelegate getTouchDelegate() {
   13962         return mTouchDelegate;
   13963     }
   13964 
   13965     /**
   13966      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
   13967      *
   13968      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
   13969      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
   13970      * available. This method should only be called for touch events.
   13971      *
   13972      * <p class="note">This api is not intended for most applications. Buffered dispatch
   13973      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
   13974      * streams will not improve your input latency. Side effects include: increased latency,
   13975      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
   13976      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
   13977      * you.</p>
   13978      */
   13979     public final void requestUnbufferedDispatch(MotionEvent event) {
   13980         final int action = event.getAction();
   13981         if (mAttachInfo == null
   13982                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
   13983                 || !event.isTouchEvent()) {
   13984             return;
   13985         }
   13986         mAttachInfo.mUnbufferedDispatchRequested = true;
   13987     }
   13988 
   13989     private boolean hasSize() {
   13990         return (mBottom > mTop) && (mRight > mLeft);
   13991     }
   13992 
   13993     private boolean canTakeFocus() {
   13994         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
   13995                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
   13996                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
   13997                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
   13998     }
   13999 
   14000     /**
   14001      * Set flags controlling behavior of this view.
   14002      *
   14003      * @param flags Constant indicating the value which should be set
   14004      * @param mask Constant indicating the bit range that should be changed
   14005      */
   14006     void setFlags(int flags, int mask) {
   14007         final boolean accessibilityEnabled =
   14008                 AccessibilityManager.getInstance(mContext).isEnabled();
   14009         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
   14010 
   14011         int old = mViewFlags;
   14012         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
   14013 
   14014         int changed = mViewFlags ^ old;
   14015         if (changed == 0) {
   14016             return;
   14017         }
   14018         int privateFlags = mPrivateFlags;
   14019         boolean shouldNotifyFocusableAvailable = false;
   14020 
   14021         // If focusable is auto, update the FOCUSABLE bit.
   14022         int focusableChangedByAuto = 0;
   14023         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
   14024                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
   14025             // Heuristic only takes into account whether view is clickable.
   14026             final int newFocus;
   14027             if ((mViewFlags & CLICKABLE) != 0) {
   14028                 newFocus = FOCUSABLE;
   14029             } else {
   14030                 newFocus = NOT_FOCUSABLE;
   14031             }
   14032             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
   14033             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
   14034             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
   14035         }
   14036 
   14037         /* Check if the FOCUSABLE bit has changed */
   14038         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
   14039             if (((old & FOCUSABLE) == FOCUSABLE)
   14040                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
   14041                 /* Give up focus if we are no longer focusable */
   14042                 clearFocus();
   14043                 if (mParent instanceof ViewGroup) {
   14044                     ((ViewGroup) mParent).clearFocusedInCluster();
   14045                 }
   14046             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
   14047                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
   14048                 /*
   14049                  * Tell the view system that we are now available to take focus
   14050                  * if no one else already has it.
   14051                  */
   14052                 if (mParent != null) {
   14053                     ViewRootImpl viewRootImpl = getViewRootImpl();
   14054                     if (!sAutoFocusableOffUIThreadWontNotifyParents
   14055                             || focusableChangedByAuto == 0
   14056                             || viewRootImpl == null
   14057                             || viewRootImpl.mThread == Thread.currentThread()) {
   14058                         shouldNotifyFocusableAvailable = canTakeFocus();
   14059                     }
   14060                 }
   14061             }
   14062         }
   14063 
   14064         final int newVisibility = flags & VISIBILITY_MASK;
   14065         if (newVisibility == VISIBLE) {
   14066             if ((changed & VISIBILITY_MASK) != 0) {
   14067                 /*
   14068                  * If this view is becoming visible, invalidate it in case it changed while
   14069                  * it was not visible. Marking it drawn ensures that the invalidation will
   14070                  * go through.
   14071                  */
   14072                 mPrivateFlags |= PFLAG_DRAWN;
   14073                 invalidate(true);
   14074 
   14075                 needGlobalAttributesUpdate(true);
   14076 
   14077                 // a view becoming visible is worth notifying the parent about in case nothing has
   14078                 // focus. Even if this specific view isn't focusable, it may contain something that
   14079                 // is, so let the root view try to give this focus if nothing else does.
   14080                 shouldNotifyFocusableAvailable = hasSize();
   14081             }
   14082         }
   14083 
   14084         if ((changed & ENABLED_MASK) != 0) {
   14085             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
   14086                 // a view becoming enabled should notify the parent as long as the view is also
   14087                 // visible and the parent wasn't already notified by becoming visible during this
   14088                 // setFlags invocation.
   14089                 shouldNotifyFocusableAvailable = canTakeFocus();
   14090             } else {
   14091                 if (isFocused()) clearFocus();
   14092             }
   14093         }
   14094 
   14095         if (shouldNotifyFocusableAvailable && mParent != null) {
   14096             mParent.focusableViewAvailable(this);
   14097         }
   14098 
   14099         /* Check if the GONE bit has changed */
   14100         if ((changed & GONE) != 0) {
   14101             needGlobalAttributesUpdate(false);
   14102             requestLayout();
   14103 
   14104             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
   14105                 if (hasFocus()) {
   14106                     clearFocus();
   14107                     if (mParent instanceof ViewGroup) {
   14108                         ((ViewGroup) mParent).clearFocusedInCluster();
   14109                     }
   14110                 }
   14111                 clearAccessibilityFocus();
   14112                 destroyDrawingCache();
   14113                 if (mParent instanceof View) {
   14114                     // GONE views noop invalidation, so invalidate the parent
   14115                     ((View) mParent).invalidate(true);
   14116                 }
   14117                 // Mark the view drawn to ensure that it gets invalidated properly the next
   14118                 // time it is visible and gets invalidated
   14119                 mPrivateFlags |= PFLAG_DRAWN;
   14120             }
   14121             if (mAttachInfo != null) {
   14122                 mAttachInfo.mViewVisibilityChanged = true;
   14123             }
   14124         }
   14125 
   14126         /* Check if the VISIBLE bit has changed */
   14127         if ((changed & INVISIBLE) != 0) {
   14128             needGlobalAttributesUpdate(false);
   14129             /*
   14130              * If this view is becoming invisible, set the DRAWN flag so that
   14131              * the next invalidate() will not be skipped.
   14132              */
   14133             mPrivateFlags |= PFLAG_DRAWN;
   14134 
   14135             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
   14136                 // root view becoming invisible shouldn't clear focus and accessibility focus
   14137                 if (getRootView() != this) {
   14138                     if (hasFocus()) {
   14139                         clearFocus();
   14140                         if (mParent instanceof ViewGroup) {
   14141                             ((ViewGroup) mParent).clearFocusedInCluster();
   14142                         }
   14143                     }
   14144                     clearAccessibilityFocus();
   14145                 }
   14146             }
   14147             if (mAttachInfo != null) {
   14148                 mAttachInfo.mViewVisibilityChanged = true;
   14149             }
   14150         }
   14151 
   14152         if ((changed & VISIBILITY_MASK) != 0) {
   14153             // If the view is invisible, cleanup its display list to free up resources
   14154             if (newVisibility != VISIBLE && mAttachInfo != null) {
   14155                 cleanupDraw();
   14156             }
   14157 
   14158             if (mParent instanceof ViewGroup) {
   14159                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
   14160                         (changed & VISIBILITY_MASK), newVisibility);
   14161                 ((View) mParent).invalidate(true);
   14162             } else if (mParent != null) {
   14163                 mParent.invalidateChild(this, null);
   14164             }
   14165 
   14166             if (mAttachInfo != null) {
   14167                 dispatchVisibilityChanged(this, newVisibility);
   14168 
   14169                 // Aggregated visibility changes are dispatched to attached views
   14170                 // in visible windows where the parent is currently shown/drawn
   14171                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
   14172                 // discounting clipping or overlapping. This makes it a good place
   14173                 // to change animation states.
   14174                 if (mParent != null && getWindowVisibility() == VISIBLE &&
   14175                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
   14176                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
   14177                 }
   14178                 notifySubtreeAccessibilityStateChangedIfNeeded();
   14179             }
   14180         }
   14181 
   14182         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
   14183             destroyDrawingCache();
   14184         }
   14185 
   14186         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
   14187             destroyDrawingCache();
   14188             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   14189             invalidateParentCaches();
   14190         }
   14191 
   14192         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
   14193             destroyDrawingCache();
   14194             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   14195         }
   14196 
   14197         if ((changed & DRAW_MASK) != 0) {
   14198             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
   14199                 if (mBackground != null
   14200                         || mDefaultFocusHighlight != null
   14201                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
   14202                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   14203                 } else {
   14204                     mPrivateFlags |= PFLAG_SKIP_DRAW;
   14205                 }
   14206             } else {
   14207                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   14208             }
   14209             requestLayout();
   14210             invalidate(true);
   14211         }
   14212 
   14213         if ((changed & KEEP_SCREEN_ON) != 0) {
   14214             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   14215                 mParent.recomputeViewAttributes(this);
   14216             }
   14217         }
   14218 
   14219         if (accessibilityEnabled) {
   14220             // If we're an accessibility pane and the visibility changed, we already have sent
   14221             // a state change, so we really don't need to report other changes.
   14222             if (isAccessibilityPane()) {
   14223                 changed &= ~VISIBILITY_MASK;
   14224             }
   14225             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
   14226                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
   14227                     || (changed & CONTEXT_CLICKABLE) != 0) {
   14228                 if (oldIncludeForAccessibility != includeForAccessibility()) {
   14229                     notifySubtreeAccessibilityStateChangedIfNeeded();
   14230                 } else {
   14231                     notifyViewAccessibilityStateChangedIfNeeded(
   14232                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   14233                 }
   14234             } else if ((changed & ENABLED_MASK) != 0) {
   14235                 notifyViewAccessibilityStateChangedIfNeeded(
   14236                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   14237             }
   14238         }
   14239     }
   14240 
   14241     /**
   14242      * Change the view's z order in the tree, so it's on top of other sibling
   14243      * views. This ordering change may affect layout, if the parent container
   14244      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
   14245      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
   14246      * method should be followed by calls to {@link #requestLayout()} and
   14247      * {@link View#invalidate()} on the view's parent to force the parent to redraw
   14248      * with the new child ordering.
   14249      *
   14250      * @see ViewGroup#bringChildToFront(View)
   14251      */
   14252     public void bringToFront() {
   14253         if (mParent != null) {
   14254             mParent.bringChildToFront(this);
   14255         }
   14256     }
   14257 
   14258     /**
   14259      * This is called in response to an internal scroll in this view (i.e., the
   14260      * view scrolled its own contents). This is typically as a result of
   14261      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
   14262      * called.
   14263      *
   14264      * @param l Current horizontal scroll origin.
   14265      * @param t Current vertical scroll origin.
   14266      * @param oldl Previous horizontal scroll origin.
   14267      * @param oldt Previous vertical scroll origin.
   14268      */
   14269     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   14270         notifySubtreeAccessibilityStateChangedIfNeeded();
   14271 
   14272         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   14273             postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
   14274         }
   14275 
   14276         mBackgroundSizeChanged = true;
   14277         mDefaultFocusHighlightSizeChanged = true;
   14278         if (mForegroundInfo != null) {
   14279             mForegroundInfo.mBoundsChanged = true;
   14280         }
   14281 
   14282         final AttachInfo ai = mAttachInfo;
   14283         if (ai != null) {
   14284             ai.mViewScrollChanged = true;
   14285         }
   14286 
   14287         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
   14288             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
   14289         }
   14290     }
   14291 
   14292     /**
   14293      * Interface definition for a callback to be invoked when the scroll
   14294      * X or Y positions of a view change.
   14295      * <p>
   14296      * <b>Note:</b> Some views handle scrolling independently from View and may
   14297      * have their own separate listeners for scroll-type events. For example,
   14298      * {@link android.widget.ListView ListView} allows clients to register an
   14299      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   14300      * to listen for changes in list scroll position.
   14301      *
   14302      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
   14303      */
   14304     public interface OnScrollChangeListener {
   14305         /**
   14306          * Called when the scroll position of a view changes.
   14307          *
   14308          * @param v The view whose scroll position has changed.
   14309          * @param scrollX Current horizontal scroll origin.
   14310          * @param scrollY Current vertical scroll origin.
   14311          * @param oldScrollX Previous horizontal scroll origin.
   14312          * @param oldScrollY Previous vertical scroll origin.
   14313          */
   14314         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
   14315     }
   14316 
   14317     /**
   14318      * Interface definition for a callback to be invoked when the layout bounds of a view
   14319      * changes due to layout processing.
   14320      */
   14321     public interface OnLayoutChangeListener {
   14322         /**
   14323          * Called when the layout bounds of a view changes due to layout processing.
   14324          *
   14325          * @param v The view whose bounds have changed.
   14326          * @param left The new value of the view's left property.
   14327          * @param top The new value of the view's top property.
   14328          * @param right The new value of the view's right property.
   14329          * @param bottom The new value of the view's bottom property.
   14330          * @param oldLeft The previous value of the view's left property.
   14331          * @param oldTop The previous value of the view's top property.
   14332          * @param oldRight The previous value of the view's right property.
   14333          * @param oldBottom The previous value of the view's bottom property.
   14334          */
   14335         void onLayoutChange(View v, int left, int top, int right, int bottom,
   14336             int oldLeft, int oldTop, int oldRight, int oldBottom);
   14337     }
   14338 
   14339     /**
   14340      * This is called during layout when the size of this view has changed. If
   14341      * you were just added to the view hierarchy, you're called with the old
   14342      * values of 0.
   14343      *
   14344      * @param w Current width of this view.
   14345      * @param h Current height of this view.
   14346      * @param oldw Old width of this view.
   14347      * @param oldh Old height of this view.
   14348      */
   14349     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   14350     }
   14351 
   14352     /**
   14353      * Called by draw to draw the child views. This may be overridden
   14354      * by derived classes to gain control just before its children are drawn
   14355      * (but after its own view has been drawn).
   14356      * @param canvas the canvas on which to draw the view
   14357      */
   14358     protected void dispatchDraw(Canvas canvas) {
   14359 
   14360     }
   14361 
   14362     /**
   14363      * Gets the parent of this view. Note that the parent is a
   14364      * ViewParent and not necessarily a View.
   14365      *
   14366      * @return Parent of this view.
   14367      */
   14368     public final ViewParent getParent() {
   14369         return mParent;
   14370     }
   14371 
   14372     /**
   14373      * Set the horizontal scrolled position of your view. This will cause a call to
   14374      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   14375      * invalidated.
   14376      * @param value the x position to scroll to
   14377      */
   14378     public void setScrollX(int value) {
   14379         scrollTo(value, mScrollY);
   14380     }
   14381 
   14382     /**
   14383      * Set the vertical scrolled position of your view. This will cause a call to
   14384      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   14385      * invalidated.
   14386      * @param value the y position to scroll to
   14387      */
   14388     public void setScrollY(int value) {
   14389         scrollTo(mScrollX, value);
   14390     }
   14391 
   14392     /**
   14393      * Return the scrolled left position of this view. This is the left edge of
   14394      * the displayed part of your view. You do not need to draw any pixels
   14395      * farther left, since those are outside of the frame of your view on
   14396      * screen.
   14397      *
   14398      * @return The left edge of the displayed part of your view, in pixels.
   14399      */
   14400     public final int getScrollX() {
   14401         return mScrollX;
   14402     }
   14403 
   14404     /**
   14405      * Return the scrolled top position of this view. This is the top edge of
   14406      * the displayed part of your view. You do not need to draw any pixels above
   14407      * it, since those are outside of the frame of your view on screen.
   14408      *
   14409      * @return The top edge of the displayed part of your view, in pixels.
   14410      */
   14411     public final int getScrollY() {
   14412         return mScrollY;
   14413     }
   14414 
   14415     /**
   14416      * Return the width of your view.
   14417      *
   14418      * @return The width of your view, in pixels.
   14419      */
   14420     @ViewDebug.ExportedProperty(category = "layout")
   14421     public final int getWidth() {
   14422         return mRight - mLeft;
   14423     }
   14424 
   14425     /**
   14426      * Return the height of your view.
   14427      *
   14428      * @return The height of your view, in pixels.
   14429      */
   14430     @ViewDebug.ExportedProperty(category = "layout")
   14431     public final int getHeight() {
   14432         return mBottom - mTop;
   14433     }
   14434 
   14435     /**
   14436      * Return the visible drawing bounds of your view. Fills in the output
   14437      * rectangle with the values from getScrollX(), getScrollY(),
   14438      * getWidth(), and getHeight(). These bounds do not account for any
   14439      * transformation properties currently set on the view, such as
   14440      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
   14441      *
   14442      * @param outRect The (scrolled) drawing bounds of the view.
   14443      */
   14444     public void getDrawingRect(Rect outRect) {
   14445         outRect.left = mScrollX;
   14446         outRect.top = mScrollY;
   14447         outRect.right = mScrollX + (mRight - mLeft);
   14448         outRect.bottom = mScrollY + (mBottom - mTop);
   14449     }
   14450 
   14451     /**
   14452      * Like {@link #getMeasuredWidthAndState()}, but only returns the
   14453      * raw width component (that is the result is masked by
   14454      * {@link #MEASURED_SIZE_MASK}).
   14455      *
   14456      * @return The raw measured width of this view.
   14457      */
   14458     public final int getMeasuredWidth() {
   14459         return mMeasuredWidth & MEASURED_SIZE_MASK;
   14460     }
   14461 
   14462     /**
   14463      * Return the full width measurement information for this view as computed
   14464      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   14465      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   14466      * This should be used during measurement and layout calculations only. Use
   14467      * {@link #getWidth()} to see how wide a view is after layout.
   14468      *
   14469      * @return The measured width of this view as a bit mask.
   14470      */
   14471     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   14472             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   14473                     name = "MEASURED_STATE_TOO_SMALL"),
   14474     })
   14475     public final int getMeasuredWidthAndState() {
   14476         return mMeasuredWidth;
   14477     }
   14478 
   14479     /**
   14480      * Like {@link #getMeasuredHeightAndState()}, but only returns the
   14481      * raw height component (that is the result is masked by
   14482      * {@link #MEASURED_SIZE_MASK}).
   14483      *
   14484      * @return The raw measured height of this view.
   14485      */
   14486     public final int getMeasuredHeight() {
   14487         return mMeasuredHeight & MEASURED_SIZE_MASK;
   14488     }
   14489 
   14490     /**
   14491      * Return the full height measurement information for this view as computed
   14492      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   14493      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   14494      * This should be used during measurement and layout calculations only. Use
   14495      * {@link #getHeight()} to see how wide a view is after layout.
   14496      *
   14497      * @return The measured height of this view as a bit mask.
   14498      */
   14499     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   14500             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   14501                     name = "MEASURED_STATE_TOO_SMALL"),
   14502     })
   14503     public final int getMeasuredHeightAndState() {
   14504         return mMeasuredHeight;
   14505     }
   14506 
   14507     /**
   14508      * Return only the state bits of {@link #getMeasuredWidthAndState()}
   14509      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
   14510      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
   14511      * and the height component is at the shifted bits
   14512      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
   14513      */
   14514     public final int getMeasuredState() {
   14515         return (mMeasuredWidth&MEASURED_STATE_MASK)
   14516                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
   14517                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
   14518     }
   14519 
   14520     /**
   14521      * The transform matrix of this view, which is calculated based on the current
   14522      * rotation, scale, and pivot properties.
   14523      *
   14524      * @see #getRotation()
   14525      * @see #getScaleX()
   14526      * @see #getScaleY()
   14527      * @see #getPivotX()
   14528      * @see #getPivotY()
   14529      * @return The current transform matrix for the view
   14530      */
   14531     public Matrix getMatrix() {
   14532         ensureTransformationInfo();
   14533         final Matrix matrix = mTransformationInfo.mMatrix;
   14534         mRenderNode.getMatrix(matrix);
   14535         return matrix;
   14536     }
   14537 
   14538     /**
   14539      * Returns true if the transform matrix is the identity matrix.
   14540      * Recomputes the matrix if necessary.
   14541      *
   14542      * @return True if the transform matrix is the identity matrix, false otherwise.
   14543      */
   14544     final boolean hasIdentityMatrix() {
   14545         return mRenderNode.hasIdentityMatrix();
   14546     }
   14547 
   14548     void ensureTransformationInfo() {
   14549         if (mTransformationInfo == null) {
   14550             mTransformationInfo = new TransformationInfo();
   14551         }
   14552     }
   14553 
   14554     /**
   14555      * Utility method to retrieve the inverse of the current mMatrix property.
   14556      * We cache the matrix to avoid recalculating it when transform properties
   14557      * have not changed.
   14558      *
   14559      * @return The inverse of the current matrix of this view.
   14560      * @hide
   14561      */
   14562     public final Matrix getInverseMatrix() {
   14563         ensureTransformationInfo();
   14564         if (mTransformationInfo.mInverseMatrix == null) {
   14565             mTransformationInfo.mInverseMatrix = new Matrix();
   14566         }
   14567         final Matrix matrix = mTransformationInfo.mInverseMatrix;
   14568         mRenderNode.getInverseMatrix(matrix);
   14569         return matrix;
   14570     }
   14571 
   14572     /**
   14573      * Gets the distance along the Z axis from the camera to this view.
   14574      *
   14575      * @see #setCameraDistance(float)
   14576      *
   14577      * @return The distance along the Z axis.
   14578      */
   14579     public float getCameraDistance() {
   14580         final float dpi = mResources.getDisplayMetrics().densityDpi;
   14581         return -(mRenderNode.getCameraDistance() * dpi);
   14582     }
   14583 
   14584     /**
   14585      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
   14586      * views are drawn) from the camera to this view. The camera's distance
   14587      * affects 3D transformations, for instance rotations around the X and Y
   14588      * axis. If the rotationX or rotationY properties are changed and this view is
   14589      * large (more than half the size of the screen), it is recommended to always
   14590      * use a camera distance that's greater than the height (X axis rotation) or
   14591      * the width (Y axis rotation) of this view.</p>
   14592      *
   14593      * <p>The distance of the camera from the view plane can have an affect on the
   14594      * perspective distortion of the view when it is rotated around the x or y axis.
   14595      * For example, a large distance will result in a large viewing angle, and there
   14596      * will not be much perspective distortion of the view as it rotates. A short
   14597      * distance may cause much more perspective distortion upon rotation, and can
   14598      * also result in some drawing artifacts if the rotated view ends up partially
   14599      * behind the camera (which is why the recommendation is to use a distance at
   14600      * least as far as the size of the view, if the view is to be rotated.)</p>
   14601      *
   14602      * <p>The distance is expressed in "depth pixels." The default distance depends
   14603      * on the screen density. For instance, on a medium density display, the
   14604      * default distance is 1280. On a high density display, the default distance
   14605      * is 1920.</p>
   14606      *
   14607      * <p>If you want to specify a distance that leads to visually consistent
   14608      * results across various densities, use the following formula:</p>
   14609      * <pre>
   14610      * float scale = context.getResources().getDisplayMetrics().density;
   14611      * view.setCameraDistance(distance * scale);
   14612      * </pre>
   14613      *
   14614      * <p>The density scale factor of a high density display is 1.5,
   14615      * and 1920 = 1280 * 1.5.</p>
   14616      *
   14617      * @param distance The distance in "depth pixels", if negative the opposite
   14618      *        value is used
   14619      *
   14620      * @see #setRotationX(float)
   14621      * @see #setRotationY(float)
   14622      */
   14623     public void setCameraDistance(float distance) {
   14624         final float dpi = mResources.getDisplayMetrics().densityDpi;
   14625 
   14626         invalidateViewProperty(true, false);
   14627         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
   14628         invalidateViewProperty(false, false);
   14629 
   14630         invalidateParentIfNeededAndWasQuickRejected();
   14631     }
   14632 
   14633     /**
   14634      * The degrees that the view is rotated around the pivot point.
   14635      *
   14636      * @see #setRotation(float)
   14637      * @see #getPivotX()
   14638      * @see #getPivotY()
   14639      *
   14640      * @return The degrees of rotation.
   14641      */
   14642     @ViewDebug.ExportedProperty(category = "drawing")
   14643     public float getRotation() {
   14644         return mRenderNode.getRotation();
   14645     }
   14646 
   14647     /**
   14648      * Sets the degrees that the view is rotated around the pivot point. Increasing values
   14649      * result in clockwise rotation.
   14650      *
   14651      * @param rotation The degrees of rotation.
   14652      *
   14653      * @see #getRotation()
   14654      * @see #getPivotX()
   14655      * @see #getPivotY()
   14656      * @see #setRotationX(float)
   14657      * @see #setRotationY(float)
   14658      *
   14659      * @attr ref android.R.styleable#View_rotation
   14660      */
   14661     public void setRotation(float rotation) {
   14662         if (rotation != getRotation()) {
   14663             // Double-invalidation is necessary to capture view's old and new areas
   14664             invalidateViewProperty(true, false);
   14665             mRenderNode.setRotation(rotation);
   14666             invalidateViewProperty(false, true);
   14667 
   14668             invalidateParentIfNeededAndWasQuickRejected();
   14669             notifySubtreeAccessibilityStateChangedIfNeeded();
   14670         }
   14671     }
   14672 
   14673     /**
   14674      * The degrees that the view is rotated around the vertical axis through the pivot point.
   14675      *
   14676      * @see #getPivotX()
   14677      * @see #getPivotY()
   14678      * @see #setRotationY(float)
   14679      *
   14680      * @return The degrees of Y rotation.
   14681      */
   14682     @ViewDebug.ExportedProperty(category = "drawing")
   14683     public float getRotationY() {
   14684         return mRenderNode.getRotationY();
   14685     }
   14686 
   14687     /**
   14688      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
   14689      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
   14690      * down the y axis.
   14691      *
   14692      * When rotating large views, it is recommended to adjust the camera distance
   14693      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   14694      *
   14695      * @param rotationY The degrees of Y rotation.
   14696      *
   14697      * @see #getRotationY()
   14698      * @see #getPivotX()
   14699      * @see #getPivotY()
   14700      * @see #setRotation(float)
   14701      * @see #setRotationX(float)
   14702      * @see #setCameraDistance(float)
   14703      *
   14704      * @attr ref android.R.styleable#View_rotationY
   14705      */
   14706     public void setRotationY(float rotationY) {
   14707         if (rotationY != getRotationY()) {
   14708             invalidateViewProperty(true, false);
   14709             mRenderNode.setRotationY(rotationY);
   14710             invalidateViewProperty(false, true);
   14711 
   14712             invalidateParentIfNeededAndWasQuickRejected();
   14713             notifySubtreeAccessibilityStateChangedIfNeeded();
   14714         }
   14715     }
   14716 
   14717     /**
   14718      * The degrees that the view is rotated around the horizontal axis through the pivot point.
   14719      *
   14720      * @see #getPivotX()
   14721      * @see #getPivotY()
   14722      * @see #setRotationX(float)
   14723      *
   14724      * @return The degrees of X rotation.
   14725      */
   14726     @ViewDebug.ExportedProperty(category = "drawing")
   14727     public float getRotationX() {
   14728         return mRenderNode.getRotationX();
   14729     }
   14730 
   14731     /**
   14732      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
   14733      * Increasing values result in clockwise rotation from the viewpoint of looking down the
   14734      * x axis.
   14735      *
   14736      * When rotating large views, it is recommended to adjust the camera distance
   14737      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   14738      *
   14739      * @param rotationX The degrees of X rotation.
   14740      *
   14741      * @see #getRotationX()
   14742      * @see #getPivotX()
   14743      * @see #getPivotY()
   14744      * @see #setRotation(float)
   14745      * @see #setRotationY(float)
   14746      * @see #setCameraDistance(float)
   14747      *
   14748      * @attr ref android.R.styleable#View_rotationX
   14749      */
   14750     public void setRotationX(float rotationX) {
   14751         if (rotationX != getRotationX()) {
   14752             invalidateViewProperty(true, false);
   14753             mRenderNode.setRotationX(rotationX);
   14754             invalidateViewProperty(false, true);
   14755 
   14756             invalidateParentIfNeededAndWasQuickRejected();
   14757             notifySubtreeAccessibilityStateChangedIfNeeded();
   14758         }
   14759     }
   14760 
   14761     /**
   14762      * The amount that the view is scaled in x around the pivot point, as a proportion of
   14763      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
   14764      *
   14765      * <p>By default, this is 1.0f.
   14766      *
   14767      * @see #getPivotX()
   14768      * @see #getPivotY()
   14769      * @return The scaling factor.
   14770      */
   14771     @ViewDebug.ExportedProperty(category = "drawing")
   14772     public float getScaleX() {
   14773         return mRenderNode.getScaleX();
   14774     }
   14775 
   14776     /**
   14777      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
   14778      * the view's unscaled width. A value of 1 means that no scaling is applied.
   14779      *
   14780      * @param scaleX The scaling factor.
   14781      * @see #getPivotX()
   14782      * @see #getPivotY()
   14783      *
   14784      * @attr ref android.R.styleable#View_scaleX
   14785      */
   14786     public void setScaleX(float scaleX) {
   14787         if (scaleX != getScaleX()) {
   14788             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
   14789             invalidateViewProperty(true, false);
   14790             mRenderNode.setScaleX(scaleX);
   14791             invalidateViewProperty(false, true);
   14792 
   14793             invalidateParentIfNeededAndWasQuickRejected();
   14794             notifySubtreeAccessibilityStateChangedIfNeeded();
   14795         }
   14796     }
   14797 
   14798     /**
   14799      * The amount that the view is scaled in y around the pivot point, as a proportion of
   14800      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
   14801      *
   14802      * <p>By default, this is 1.0f.
   14803      *
   14804      * @see #getPivotX()
   14805      * @see #getPivotY()
   14806      * @return The scaling factor.
   14807      */
   14808     @ViewDebug.ExportedProperty(category = "drawing")
   14809     public float getScaleY() {
   14810         return mRenderNode.getScaleY();
   14811     }
   14812 
   14813     /**
   14814      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
   14815      * the view's unscaled width. A value of 1 means that no scaling is applied.
   14816      *
   14817      * @param scaleY The scaling factor.
   14818      * @see #getPivotX()
   14819      * @see #getPivotY()
   14820      *
   14821      * @attr ref android.R.styleable#View_scaleY
   14822      */
   14823     public void setScaleY(float scaleY) {
   14824         if (scaleY != getScaleY()) {
   14825             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
   14826             invalidateViewProperty(true, false);
   14827             mRenderNode.setScaleY(scaleY);
   14828             invalidateViewProperty(false, true);
   14829 
   14830             invalidateParentIfNeededAndWasQuickRejected();
   14831             notifySubtreeAccessibilityStateChangedIfNeeded();
   14832         }
   14833     }
   14834 
   14835     /**
   14836      * The x location of the point around which the view is {@link #setRotation(float) rotated}
   14837      * and {@link #setScaleX(float) scaled}.
   14838      *
   14839      * @see #getRotation()
   14840      * @see #getScaleX()
   14841      * @see #getScaleY()
   14842      * @see #getPivotY()
   14843      * @return The x location of the pivot point.
   14844      *
   14845      * @attr ref android.R.styleable#View_transformPivotX
   14846      */
   14847     @ViewDebug.ExportedProperty(category = "drawing")
   14848     public float getPivotX() {
   14849         return mRenderNode.getPivotX();
   14850     }
   14851 
   14852     /**
   14853      * Sets the x location of the point around which the view is
   14854      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
   14855      * By default, the pivot point is centered on the object.
   14856      * Setting this property disables this behavior and causes the view to use only the
   14857      * explicitly set pivotX and pivotY values.
   14858      *
   14859      * @param pivotX The x location of the pivot point.
   14860      * @see #getRotation()
   14861      * @see #getScaleX()
   14862      * @see #getScaleY()
   14863      * @see #getPivotY()
   14864      *
   14865      * @attr ref android.R.styleable#View_transformPivotX
   14866      */
   14867     public void setPivotX(float pivotX) {
   14868         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
   14869             invalidateViewProperty(true, false);
   14870             mRenderNode.setPivotX(pivotX);
   14871             invalidateViewProperty(false, true);
   14872 
   14873             invalidateParentIfNeededAndWasQuickRejected();
   14874         }
   14875     }
   14876 
   14877     /**
   14878      * The y location of the point around which the view is {@link #setRotation(float) rotated}
   14879      * and {@link #setScaleY(float) scaled}.
   14880      *
   14881      * @see #getRotation()
   14882      * @see #getScaleX()
   14883      * @see #getScaleY()
   14884      * @see #getPivotY()
   14885      * @return The y location of the pivot point.
   14886      *
   14887      * @attr ref android.R.styleable#View_transformPivotY
   14888      */
   14889     @ViewDebug.ExportedProperty(category = "drawing")
   14890     public float getPivotY() {
   14891         return mRenderNode.getPivotY();
   14892     }
   14893 
   14894     /**
   14895      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
   14896      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
   14897      * Setting this property disables this behavior and causes the view to use only the
   14898      * explicitly set pivotX and pivotY values.
   14899      *
   14900      * @param pivotY The y location of the pivot point.
   14901      * @see #getRotation()
   14902      * @see #getScaleX()
   14903      * @see #getScaleY()
   14904      * @see #getPivotY()
   14905      *
   14906      * @attr ref android.R.styleable#View_transformPivotY
   14907      */
   14908     public void setPivotY(float pivotY) {
   14909         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
   14910             invalidateViewProperty(true, false);
   14911             mRenderNode.setPivotY(pivotY);
   14912             invalidateViewProperty(false, true);
   14913 
   14914             invalidateParentIfNeededAndWasQuickRejected();
   14915         }
   14916     }
   14917 
   14918     /**
   14919      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
   14920      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
   14921      * of the view.
   14922      *
   14923      * @return True if a pivot has been set, false if the default pivot is being used
   14924      */
   14925     public boolean isPivotSet() {
   14926         return mRenderNode.isPivotExplicitlySet();
   14927     }
   14928 
   14929     /**
   14930      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
   14931      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
   14932      * and the pivot used for rotation will return to default of being centered on the view.
   14933      */
   14934     public void resetPivot() {
   14935         if (mRenderNode.resetPivot()) {
   14936             invalidateViewProperty(false, false);
   14937         }
   14938     }
   14939 
   14940     /**
   14941      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
   14942      * completely transparent and 1 means the view is completely opaque.
   14943      *
   14944      * <p>By default this is 1.0f.
   14945      * @return The opacity of the view.
   14946      */
   14947     @ViewDebug.ExportedProperty(category = "drawing")
   14948     public float getAlpha() {
   14949         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
   14950     }
   14951 
   14952     /**
   14953      * Sets the behavior for overlapping rendering for this view (see {@link
   14954      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
   14955      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
   14956      * providing the value which is then used internally. That is, when {@link
   14957      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
   14958      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
   14959      * instead.
   14960      *
   14961      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
   14962      * instead of that returned by {@link #hasOverlappingRendering()}.
   14963      *
   14964      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
   14965      */
   14966     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
   14967         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
   14968         if (hasOverlappingRendering) {
   14969             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
   14970         } else {
   14971             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
   14972         }
   14973     }
   14974 
   14975     /**
   14976      * Returns the value for overlapping rendering that is used internally. This is either
   14977      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
   14978      * the return value of {@link #hasOverlappingRendering()}, otherwise.
   14979      *
   14980      * @return The value for overlapping rendering being used internally.
   14981      */
   14982     public final boolean getHasOverlappingRendering() {
   14983         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
   14984                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
   14985                 hasOverlappingRendering();
   14986     }
   14987 
   14988     /**
   14989      * Returns whether this View has content which overlaps.
   14990      *
   14991      * <p>This function, intended to be overridden by specific View types, is an optimization when
   14992      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
   14993      * an offscreen buffer and then composited into place, which can be expensive. If the view has
   14994      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
   14995      * directly. An example of overlapping rendering is a TextView with a background image, such as
   14996      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
   14997      * ImageView with only the foreground image. The default implementation returns true; subclasses
   14998      * should override if they have cases which can be optimized.</p>
   14999      *
   15000      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
   15001      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
   15002      *
   15003      * @return true if the content in this view might overlap, false otherwise.
   15004      */
   15005     @ViewDebug.ExportedProperty(category = "drawing")
   15006     public boolean hasOverlappingRendering() {
   15007         return true;
   15008     }
   15009 
   15010     /**
   15011      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
   15012      * completely transparent and 1 means the view is completely opaque.
   15013      *
   15014      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
   15015      * can have significant performance implications, especially for large views. It is best to use
   15016      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
   15017      *
   15018      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
   15019      * strongly recommended for performance reasons to either override
   15020      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
   15021      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
   15022      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
   15023      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
   15024      * of rendering cost, even for simple or small views. Starting with
   15025      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
   15026      * applied to the view at the rendering level.</p>
   15027      *
   15028      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
   15029      * responsible for applying the opacity itself.</p>
   15030      *
   15031      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
   15032      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
   15033      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
   15034      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
   15035      *
   15036      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
   15037      * value will clip a View to its bounds, unless the View returns <code>false</code> from
   15038      * {@link #hasOverlappingRendering}.</p>
   15039      *
   15040      * @param alpha The opacity of the view.
   15041      *
   15042      * @see #hasOverlappingRendering()
   15043      * @see #setLayerType(int, android.graphics.Paint)
   15044      *
   15045      * @attr ref android.R.styleable#View_alpha
   15046      */
   15047     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
   15048         ensureTransformationInfo();
   15049         if (mTransformationInfo.mAlpha != alpha) {
   15050             setAlphaInternal(alpha);
   15051             if (onSetAlpha((int) (alpha * 255))) {
   15052                 mPrivateFlags |= PFLAG_ALPHA_SET;
   15053                 // subclass is handling alpha - don't optimize rendering cache invalidation
   15054                 invalidateParentCaches();
   15055                 invalidate(true);
   15056             } else {
   15057                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   15058                 invalidateViewProperty(true, false);
   15059                 mRenderNode.setAlpha(getFinalAlpha());
   15060             }
   15061         }
   15062     }
   15063 
   15064     /**
   15065      * Faster version of setAlpha() which performs the same steps except there are
   15066      * no calls to invalidate(). The caller of this function should perform proper invalidation
   15067      * on the parent and this object. The return value indicates whether the subclass handles
   15068      * alpha (the return value for onSetAlpha()).
   15069      *
   15070      * @param alpha The new value for the alpha property
   15071      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
   15072      *         the new value for the alpha property is different from the old value
   15073      */
   15074     boolean setAlphaNoInvalidation(float alpha) {
   15075         ensureTransformationInfo();
   15076         if (mTransformationInfo.mAlpha != alpha) {
   15077             setAlphaInternal(alpha);
   15078             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
   15079             if (subclassHandlesAlpha) {
   15080                 mPrivateFlags |= PFLAG_ALPHA_SET;
   15081                 return true;
   15082             } else {
   15083                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   15084                 mRenderNode.setAlpha(getFinalAlpha());
   15085             }
   15086         }
   15087         return false;
   15088     }
   15089 
   15090     private void setAlphaInternal(float alpha) {
   15091         float oldAlpha = mTransformationInfo.mAlpha;
   15092         mTransformationInfo.mAlpha = alpha;
   15093         // Report visibility changes, which can affect children, to accessibility
   15094         if ((alpha == 0) ^ (oldAlpha == 0)) {
   15095             notifySubtreeAccessibilityStateChangedIfNeeded();
   15096         }
   15097     }
   15098 
   15099     /**
   15100      * This property is hidden and intended only for use by the Fade transition, which
   15101      * animates it to produce a visual translucency that does not side-effect (or get
   15102      * affected by) the real alpha property. This value is composited with the other
   15103      * alpha value (and the AlphaAnimation value, when that is present) to produce
   15104      * a final visual translucency result, which is what is passed into the DisplayList.
   15105      *
   15106      * @hide
   15107      */
   15108     public void setTransitionAlpha(float alpha) {
   15109         ensureTransformationInfo();
   15110         if (mTransformationInfo.mTransitionAlpha != alpha) {
   15111             mTransformationInfo.mTransitionAlpha = alpha;
   15112             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   15113             invalidateViewProperty(true, false);
   15114             mRenderNode.setAlpha(getFinalAlpha());
   15115         }
   15116     }
   15117 
   15118     /**
   15119      * Calculates the visual alpha of this view, which is a combination of the actual
   15120      * alpha value and the transitionAlpha value (if set).
   15121      */
   15122     private float getFinalAlpha() {
   15123         if (mTransformationInfo != null) {
   15124             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
   15125         }
   15126         return 1;
   15127     }
   15128 
   15129     /**
   15130      * This property is hidden and intended only for use by the Fade transition, which
   15131      * animates it to produce a visual translucency that does not side-effect (or get
   15132      * affected by) the real alpha property. This value is composited with the other
   15133      * alpha value (and the AlphaAnimation value, when that is present) to produce
   15134      * a final visual translucency result, which is what is passed into the DisplayList.
   15135      *
   15136      * @hide
   15137      */
   15138     @ViewDebug.ExportedProperty(category = "drawing")
   15139     public float getTransitionAlpha() {
   15140         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
   15141     }
   15142 
   15143     /**
   15144      * Top position of this view relative to its parent.
   15145      *
   15146      * @return The top of this view, in pixels.
   15147      */
   15148     @ViewDebug.CapturedViewProperty
   15149     public final int getTop() {
   15150         return mTop;
   15151     }
   15152 
   15153     /**
   15154      * Sets the top position of this view relative to its parent. This method is meant to be called
   15155      * by the layout system and should not generally be called otherwise, because the property
   15156      * may be changed at any time by the layout.
   15157      *
   15158      * @param top The top of this view, in pixels.
   15159      */
   15160     public final void setTop(int top) {
   15161         if (top != mTop) {
   15162             final boolean matrixIsIdentity = hasIdentityMatrix();
   15163             if (matrixIsIdentity) {
   15164                 if (mAttachInfo != null) {
   15165                     int minTop;
   15166                     int yLoc;
   15167                     if (top < mTop) {
   15168                         minTop = top;
   15169                         yLoc = top - mTop;
   15170                     } else {
   15171                         minTop = mTop;
   15172                         yLoc = 0;
   15173                     }
   15174                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
   15175                 }
   15176             } else {
   15177                 // Double-invalidation is necessary to capture view's old and new areas
   15178                 invalidate(true);
   15179             }
   15180 
   15181             int width = mRight - mLeft;
   15182             int oldHeight = mBottom - mTop;
   15183 
   15184             mTop = top;
   15185             mRenderNode.setTop(mTop);
   15186 
   15187             sizeChange(width, mBottom - mTop, width, oldHeight);
   15188 
   15189             if (!matrixIsIdentity) {
   15190                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   15191                 invalidate(true);
   15192             }
   15193             mBackgroundSizeChanged = true;
   15194             mDefaultFocusHighlightSizeChanged = true;
   15195             if (mForegroundInfo != null) {
   15196                 mForegroundInfo.mBoundsChanged = true;
   15197             }
   15198             invalidateParentIfNeeded();
   15199             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   15200                 // View was rejected last time it was drawn by its parent; this may have changed
   15201                 invalidateParentIfNeeded();
   15202             }
   15203         }
   15204     }
   15205 
   15206     /**
   15207      * Bottom position of this view relative to its parent.
   15208      *
   15209      * @return The bottom of this view, in pixels.
   15210      */
   15211     @ViewDebug.CapturedViewProperty
   15212     public final int getBottom() {
   15213         return mBottom;
   15214     }
   15215 
   15216     /**
   15217      * True if this view has changed since the last time being drawn.
   15218      *
   15219      * @return The dirty state of this view.
   15220      */
   15221     public boolean isDirty() {
   15222         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
   15223     }
   15224 
   15225     /**
   15226      * Sets the bottom position of this view relative to its parent. This method is meant to be
   15227      * called by the layout system and should not generally be called otherwise, because the
   15228      * property may be changed at any time by the layout.
   15229      *
   15230      * @param bottom The bottom of this view, in pixels.
   15231      */
   15232     public final void setBottom(int bottom) {
   15233         if (bottom != mBottom) {
   15234             final boolean matrixIsIdentity = hasIdentityMatrix();
   15235             if (matrixIsIdentity) {
   15236                 if (mAttachInfo != null) {
   15237                     int maxBottom;
   15238                     if (bottom < mBottom) {
   15239                         maxBottom = mBottom;
   15240                     } else {
   15241                         maxBottom = bottom;
   15242                     }
   15243                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
   15244                 }
   15245             } else {
   15246                 // Double-invalidation is necessary to capture view's old and new areas
   15247                 invalidate(true);
   15248             }
   15249 
   15250             int width = mRight - mLeft;
   15251             int oldHeight = mBottom - mTop;
   15252 
   15253             mBottom = bottom;
   15254             mRenderNode.setBottom(mBottom);
   15255 
   15256             sizeChange(width, mBottom - mTop, width, oldHeight);
   15257 
   15258             if (!matrixIsIdentity) {
   15259                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   15260                 invalidate(true);
   15261             }
   15262             mBackgroundSizeChanged = true;
   15263             mDefaultFocusHighlightSizeChanged = true;
   15264             if (mForegroundInfo != null) {
   15265                 mForegroundInfo.mBoundsChanged = true;
   15266             }
   15267             invalidateParentIfNeeded();
   15268             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   15269                 // View was rejected last time it was drawn by its parent; this may have changed
   15270                 invalidateParentIfNeeded();
   15271             }
   15272         }
   15273     }
   15274 
   15275     /**
   15276      * Left position of this view relative to its parent.
   15277      *
   15278      * @return The left edge of this view, in pixels.
   15279      */
   15280     @ViewDebug.CapturedViewProperty
   15281     public final int getLeft() {
   15282         return mLeft;
   15283     }
   15284 
   15285     /**
   15286      * Sets the left position of this view relative to its parent. This method is meant to be called
   15287      * by the layout system and should not generally be called otherwise, because the property
   15288      * may be changed at any time by the layout.
   15289      *
   15290      * @param left The left of this view, in pixels.
   15291      */
   15292     public final void setLeft(int left) {
   15293         if (left != mLeft) {
   15294             final boolean matrixIsIdentity = hasIdentityMatrix();
   15295             if (matrixIsIdentity) {
   15296                 if (mAttachInfo != null) {
   15297                     int minLeft;
   15298                     int xLoc;
   15299                     if (left < mLeft) {
   15300                         minLeft = left;
   15301                         xLoc = left - mLeft;
   15302                     } else {
   15303                         minLeft = mLeft;
   15304                         xLoc = 0;
   15305                     }
   15306                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
   15307                 }
   15308             } else {
   15309                 // Double-invalidation is necessary to capture view's old and new areas
   15310                 invalidate(true);
   15311             }
   15312 
   15313             int oldWidth = mRight - mLeft;
   15314             int height = mBottom - mTop;
   15315 
   15316             mLeft = left;
   15317             mRenderNode.setLeft(left);
   15318 
   15319             sizeChange(mRight - mLeft, height, oldWidth, height);
   15320 
   15321             if (!matrixIsIdentity) {
   15322                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   15323                 invalidate(true);
   15324             }
   15325             mBackgroundSizeChanged = true;
   15326             mDefaultFocusHighlightSizeChanged = true;
   15327             if (mForegroundInfo != null) {
   15328                 mForegroundInfo.mBoundsChanged = true;
   15329             }
   15330             invalidateParentIfNeeded();
   15331             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   15332                 // View was rejected last time it was drawn by its parent; this may have changed
   15333                 invalidateParentIfNeeded();
   15334             }
   15335         }
   15336     }
   15337 
   15338     /**
   15339      * Right position of this view relative to its parent.
   15340      *
   15341      * @return The right edge of this view, in pixels.
   15342      */
   15343     @ViewDebug.CapturedViewProperty
   15344     public final int getRight() {
   15345         return mRight;
   15346     }
   15347 
   15348     /**
   15349      * Sets the right position of this view relative to its parent. This method is meant to be called
   15350      * by the layout system and should not generally be called otherwise, because the property
   15351      * may be changed at any time by the layout.
   15352      *
   15353      * @param right The right of this view, in pixels.
   15354      */
   15355     public final void setRight(int right) {
   15356         if (right != mRight) {
   15357             final boolean matrixIsIdentity = hasIdentityMatrix();
   15358             if (matrixIsIdentity) {
   15359                 if (mAttachInfo != null) {
   15360                     int maxRight;
   15361                     if (right < mRight) {
   15362                         maxRight = mRight;
   15363                     } else {
   15364                         maxRight = right;
   15365                     }
   15366                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
   15367                 }
   15368             } else {
   15369                 // Double-invalidation is necessary to capture view's old and new areas
   15370                 invalidate(true);
   15371             }
   15372 
   15373             int oldWidth = mRight - mLeft;
   15374             int height = mBottom - mTop;
   15375 
   15376             mRight = right;
   15377             mRenderNode.setRight(mRight);
   15378 
   15379             sizeChange(mRight - mLeft, height, oldWidth, height);
   15380 
   15381             if (!matrixIsIdentity) {
   15382                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   15383                 invalidate(true);
   15384             }
   15385             mBackgroundSizeChanged = true;
   15386             mDefaultFocusHighlightSizeChanged = true;
   15387             if (mForegroundInfo != null) {
   15388                 mForegroundInfo.mBoundsChanged = true;
   15389             }
   15390             invalidateParentIfNeeded();
   15391             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   15392                 // View was rejected last time it was drawn by its parent; this may have changed
   15393                 invalidateParentIfNeeded();
   15394             }
   15395         }
   15396     }
   15397 
   15398     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
   15399         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
   15400     }
   15401 
   15402     private static float sanitizeFloatPropertyValue(float value, String propertyName,
   15403             float min, float max) {
   15404         // The expected "nothing bad happened" path
   15405         if (value >= min && value <= max) return value;
   15406 
   15407         if (value < min || value == Float.NEGATIVE_INFINITY) {
   15408             if (sThrowOnInvalidFloatProperties) {
   15409                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
   15410                         + value + ", the value must be >= " + min);
   15411             }
   15412             return min;
   15413         }
   15414 
   15415         if (value > max || value == Float.POSITIVE_INFINITY) {
   15416             if (sThrowOnInvalidFloatProperties) {
   15417                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
   15418                         + value + ", the value must be <= " + max);
   15419             }
   15420             return max;
   15421         }
   15422 
   15423         if (Float.isNaN(value)) {
   15424             if (sThrowOnInvalidFloatProperties) {
   15425                 throw new IllegalArgumentException(
   15426                         "Cannot set '" + propertyName + "' to Float.NaN");
   15427             }
   15428             return 0; // Unclear which direction this NaN went so... 0?
   15429         }
   15430 
   15431         // Shouldn't be possible to reach this.
   15432         throw new IllegalStateException("How do you get here?? " + value);
   15433     }
   15434 
   15435     /**
   15436      * The visual x position of this view, in pixels. This is equivalent to the
   15437      * {@link #setTranslationX(float) translationX} property plus the current
   15438      * {@link #getLeft() left} property.
   15439      *
   15440      * @return The visual x position of this view, in pixels.
   15441      */
   15442     @ViewDebug.ExportedProperty(category = "drawing")
   15443     public float getX() {
   15444         return mLeft + getTranslationX();
   15445     }
   15446 
   15447     /**
   15448      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
   15449      * {@link #setTranslationX(float) translationX} property to be the difference between
   15450      * the x value passed in and the current {@link #getLeft() left} property.
   15451      *
   15452      * @param x The visual x position of this view, in pixels.
   15453      */
   15454     public void setX(float x) {
   15455         setTranslationX(x - mLeft);
   15456     }
   15457 
   15458     /**
   15459      * The visual y position of this view, in pixels. This is equivalent to the
   15460      * {@link #setTranslationY(float) translationY} property plus the current
   15461      * {@link #getTop() top} property.
   15462      *
   15463      * @return The visual y position of this view, in pixels.
   15464      */
   15465     @ViewDebug.ExportedProperty(category = "drawing")
   15466     public float getY() {
   15467         return mTop + getTranslationY();
   15468     }
   15469 
   15470     /**
   15471      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
   15472      * {@link #setTranslationY(float) translationY} property to be the difference between
   15473      * the y value passed in and the current {@link #getTop() top} property.
   15474      *
   15475      * @param y The visual y position of this view, in pixels.
   15476      */
   15477     public void setY(float y) {
   15478         setTranslationY(y - mTop);
   15479     }
   15480 
   15481     /**
   15482      * The visual z position of this view, in pixels. This is equivalent to the
   15483      * {@link #setTranslationZ(float) translationZ} property plus the current
   15484      * {@link #getElevation() elevation} property.
   15485      *
   15486      * @return The visual z position of this view, in pixels.
   15487      */
   15488     @ViewDebug.ExportedProperty(category = "drawing")
   15489     public float getZ() {
   15490         return getElevation() + getTranslationZ();
   15491     }
   15492 
   15493     /**
   15494      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
   15495      * {@link #setTranslationZ(float) translationZ} property to be the difference between
   15496      * the x value passed in and the current {@link #getElevation() elevation} property.
   15497      *
   15498      * @param z The visual z position of this view, in pixels.
   15499      */
   15500     public void setZ(float z) {
   15501         setTranslationZ(z - getElevation());
   15502     }
   15503 
   15504     /**
   15505      * The base elevation of this view relative to its parent, in pixels.
   15506      *
   15507      * @return The base depth position of the view, in pixels.
   15508      */
   15509     @ViewDebug.ExportedProperty(category = "drawing")
   15510     public float getElevation() {
   15511         return mRenderNode.getElevation();
   15512     }
   15513 
   15514     /**
   15515      * Sets the base elevation of this view, in pixels.
   15516      *
   15517      * @attr ref android.R.styleable#View_elevation
   15518      */
   15519     public void setElevation(float elevation) {
   15520         if (elevation != getElevation()) {
   15521             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
   15522             invalidateViewProperty(true, false);
   15523             mRenderNode.setElevation(elevation);
   15524             invalidateViewProperty(false, true);
   15525 
   15526             invalidateParentIfNeededAndWasQuickRejected();
   15527         }
   15528     }
   15529 
   15530     /**
   15531      * The horizontal location of this view relative to its {@link #getLeft() left} position.
   15532      * This position is post-layout, in addition to wherever the object's
   15533      * layout placed it.
   15534      *
   15535      * @return The horizontal position of this view relative to its left position, in pixels.
   15536      */
   15537     @ViewDebug.ExportedProperty(category = "drawing")
   15538     public float getTranslationX() {
   15539         return mRenderNode.getTranslationX();
   15540     }
   15541 
   15542     /**
   15543      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
   15544      * This effectively positions the object post-layout, in addition to wherever the object's
   15545      * layout placed it.
   15546      *
   15547      * @param translationX The horizontal position of this view relative to its left position,
   15548      * in pixels.
   15549      *
   15550      * @attr ref android.R.styleable#View_translationX
   15551      */
   15552     public void setTranslationX(float translationX) {
   15553         if (translationX != getTranslationX()) {
   15554             invalidateViewProperty(true, false);
   15555             mRenderNode.setTranslationX(translationX);
   15556             invalidateViewProperty(false, true);
   15557 
   15558             invalidateParentIfNeededAndWasQuickRejected();
   15559             notifySubtreeAccessibilityStateChangedIfNeeded();
   15560         }
   15561     }
   15562 
   15563     /**
   15564      * The vertical location of this view relative to its {@link #getTop() top} position.
   15565      * This position is post-layout, in addition to wherever the object's
   15566      * layout placed it.
   15567      *
   15568      * @return The vertical position of this view relative to its top position,
   15569      * in pixels.
   15570      */
   15571     @ViewDebug.ExportedProperty(category = "drawing")
   15572     public float getTranslationY() {
   15573         return mRenderNode.getTranslationY();
   15574     }
   15575 
   15576     /**
   15577      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
   15578      * This effectively positions the object post-layout, in addition to wherever the object's
   15579      * layout placed it.
   15580      *
   15581      * @param translationY The vertical position of this view relative to its top position,
   15582      * in pixels.
   15583      *
   15584      * @attr ref android.R.styleable#View_translationY
   15585      */
   15586     public void setTranslationY(float translationY) {
   15587         if (translationY != getTranslationY()) {
   15588             invalidateViewProperty(true, false);
   15589             mRenderNode.setTranslationY(translationY);
   15590             invalidateViewProperty(false, true);
   15591 
   15592             invalidateParentIfNeededAndWasQuickRejected();
   15593             notifySubtreeAccessibilityStateChangedIfNeeded();
   15594         }
   15595     }
   15596 
   15597     /**
   15598      * The depth location of this view relative to its {@link #getElevation() elevation}.
   15599      *
   15600      * @return The depth of this view relative to its elevation.
   15601      */
   15602     @ViewDebug.ExportedProperty(category = "drawing")
   15603     public float getTranslationZ() {
   15604         return mRenderNode.getTranslationZ();
   15605     }
   15606 
   15607     /**
   15608      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
   15609      *
   15610      * @attr ref android.R.styleable#View_translationZ
   15611      */
   15612     public void setTranslationZ(float translationZ) {
   15613         if (translationZ != getTranslationZ()) {
   15614             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
   15615             invalidateViewProperty(true, false);
   15616             mRenderNode.setTranslationZ(translationZ);
   15617             invalidateViewProperty(false, true);
   15618 
   15619             invalidateParentIfNeededAndWasQuickRejected();
   15620         }
   15621     }
   15622 
   15623     /** @hide */
   15624     public void setAnimationMatrix(Matrix matrix) {
   15625         invalidateViewProperty(true, false);
   15626         mRenderNode.setAnimationMatrix(matrix);
   15627         invalidateViewProperty(false, true);
   15628 
   15629         invalidateParentIfNeededAndWasQuickRejected();
   15630     }
   15631 
   15632     /**
   15633      * Returns the current StateListAnimator if exists.
   15634      *
   15635      * @return StateListAnimator or null if it does not exists
   15636      * @see    #setStateListAnimator(android.animation.StateListAnimator)
   15637      */
   15638     public StateListAnimator getStateListAnimator() {
   15639         return mStateListAnimator;
   15640     }
   15641 
   15642     /**
   15643      * Attaches the provided StateListAnimator to this View.
   15644      * <p>
   15645      * Any previously attached StateListAnimator will be detached.
   15646      *
   15647      * @param stateListAnimator The StateListAnimator to update the view
   15648      * @see android.animation.StateListAnimator
   15649      */
   15650     public void setStateListAnimator(StateListAnimator stateListAnimator) {
   15651         if (mStateListAnimator == stateListAnimator) {
   15652             return;
   15653         }
   15654         if (mStateListAnimator != null) {
   15655             mStateListAnimator.setTarget(null);
   15656         }
   15657         mStateListAnimator = stateListAnimator;
   15658         if (stateListAnimator != null) {
   15659             stateListAnimator.setTarget(this);
   15660             if (isAttachedToWindow()) {
   15661                 stateListAnimator.setState(getDrawableState());
   15662             }
   15663         }
   15664     }
   15665 
   15666     /**
   15667      * Returns whether the Outline should be used to clip the contents of the View.
   15668      * <p>
   15669      * Note that this flag will only be respected if the View's Outline returns true from
   15670      * {@link Outline#canClip()}.
   15671      *
   15672      * @see #setOutlineProvider(ViewOutlineProvider)
   15673      * @see #setClipToOutline(boolean)
   15674      */
   15675     public final boolean getClipToOutline() {
   15676         return mRenderNode.getClipToOutline();
   15677     }
   15678 
   15679     /**
   15680      * Sets whether the View's Outline should be used to clip the contents of the View.
   15681      * <p>
   15682      * Only a single non-rectangular clip can be applied on a View at any time.
   15683      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
   15684      * circular reveal} animation take priority over Outline clipping, and
   15685      * child Outline clipping takes priority over Outline clipping done by a
   15686      * parent.
   15687      * <p>
   15688      * Note that this flag will only be respected if the View's Outline returns true from
   15689      * {@link Outline#canClip()}.
   15690      *
   15691      * @see #setOutlineProvider(ViewOutlineProvider)
   15692      * @see #getClipToOutline()
   15693      */
   15694     public void setClipToOutline(boolean clipToOutline) {
   15695         damageInParent();
   15696         if (getClipToOutline() != clipToOutline) {
   15697             mRenderNode.setClipToOutline(clipToOutline);
   15698         }
   15699     }
   15700 
   15701     // correspond to the enum values of View_outlineProvider
   15702     private static final int PROVIDER_BACKGROUND = 0;
   15703     private static final int PROVIDER_NONE = 1;
   15704     private static final int PROVIDER_BOUNDS = 2;
   15705     private static final int PROVIDER_PADDED_BOUNDS = 3;
   15706     private void setOutlineProviderFromAttribute(int providerInt) {
   15707         switch (providerInt) {
   15708             case PROVIDER_BACKGROUND:
   15709                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
   15710                 break;
   15711             case PROVIDER_NONE:
   15712                 setOutlineProvider(null);
   15713                 break;
   15714             case PROVIDER_BOUNDS:
   15715                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
   15716                 break;
   15717             case PROVIDER_PADDED_BOUNDS:
   15718                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
   15719                 break;
   15720         }
   15721     }
   15722 
   15723     /**
   15724      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
   15725      * the shape of the shadow it casts, and enables outline clipping.
   15726      * <p>
   15727      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
   15728      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
   15729      * outline provider with this method allows this behavior to be overridden.
   15730      * <p>
   15731      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
   15732      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
   15733      * <p>
   15734      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
   15735      *
   15736      * @see #setClipToOutline(boolean)
   15737      * @see #getClipToOutline()
   15738      * @see #getOutlineProvider()
   15739      */
   15740     public void setOutlineProvider(ViewOutlineProvider provider) {
   15741         mOutlineProvider = provider;
   15742         invalidateOutline();
   15743     }
   15744 
   15745     /**
   15746      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
   15747      * that defines the shape of the shadow it casts, and enables outline clipping.
   15748      *
   15749      * @see #setOutlineProvider(ViewOutlineProvider)
   15750      */
   15751     public ViewOutlineProvider getOutlineProvider() {
   15752         return mOutlineProvider;
   15753     }
   15754 
   15755     /**
   15756      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
   15757      *
   15758      * @see #setOutlineProvider(ViewOutlineProvider)
   15759      */
   15760     public void invalidateOutline() {
   15761         rebuildOutline();
   15762 
   15763         notifySubtreeAccessibilityStateChangedIfNeeded();
   15764         invalidateViewProperty(false, false);
   15765     }
   15766 
   15767     /**
   15768      * Internal version of {@link #invalidateOutline()} which invalidates the
   15769      * outline without invalidating the view itself. This is intended to be called from
   15770      * within methods in the View class itself which are the result of the view being
   15771      * invalidated already. For example, when we are drawing the background of a View,
   15772      * we invalidate the outline in case it changed in the meantime, but we do not
   15773      * need to invalidate the view because we're already drawing the background as part
   15774      * of drawing the view in response to an earlier invalidation of the view.
   15775      */
   15776     private void rebuildOutline() {
   15777         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
   15778         if (mAttachInfo == null) return;
   15779 
   15780         if (mOutlineProvider == null) {
   15781             // no provider, remove outline
   15782             mRenderNode.setOutline(null);
   15783         } else {
   15784             final Outline outline = mAttachInfo.mTmpOutline;
   15785             outline.setEmpty();
   15786             outline.setAlpha(1.0f);
   15787 
   15788             mOutlineProvider.getOutline(this, outline);
   15789             mRenderNode.setOutline(outline);
   15790         }
   15791     }
   15792 
   15793     /**
   15794      * HierarchyViewer only
   15795      *
   15796      * @hide
   15797      */
   15798     @ViewDebug.ExportedProperty(category = "drawing")
   15799     public boolean hasShadow() {
   15800         return mRenderNode.hasShadow();
   15801     }
   15802 
   15803     /**
   15804      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
   15805      * elevation value.
   15806      * <p>
   15807      * By default the shadow color is black. Generally, this color will be opaque so the intensity
   15808      * of the shadow is consistent between different views with different colors.
   15809      * <p>
   15810      * The opacity of the final spot shadow is a function of the shadow caster height, the
   15811      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
   15812      * {@link android.R.attr#spotShadowAlpha} theme attribute.
   15813      *
   15814      * @attr ref android.R.styleable#View_outlineSpotShadowColor
   15815      * @param color The color this View will cast for its elevation spot shadow.
   15816      */
   15817     public void setOutlineSpotShadowColor(@ColorInt int color) {
   15818         if (mRenderNode.setSpotShadowColor(color)) {
   15819             invalidateViewProperty(true, true);
   15820         }
   15821     }
   15822 
   15823     /**
   15824      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
   15825      * was set
   15826      */
   15827     public @ColorInt int getOutlineSpotShadowColor() {
   15828         return mRenderNode.getSpotShadowColor();
   15829     }
   15830 
   15831     /**
   15832      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
   15833      * elevation value.
   15834      * <p>
   15835      * By default the shadow color is black. Generally, this color will be opaque so the intensity
   15836      * of the shadow is consistent between different views with different colors.
   15837      * <p>
   15838      * The opacity of the final ambient shadow is a function of the shadow caster height, the
   15839      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
   15840      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
   15841      *
   15842      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
   15843      * @param color The color this View will cast for its elevation shadow.
   15844      */
   15845     public void setOutlineAmbientShadowColor(@ColorInt int color) {
   15846         if (mRenderNode.setAmbientShadowColor(color)) {
   15847             invalidateViewProperty(true, true);
   15848         }
   15849     }
   15850 
   15851     /**
   15852      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
   15853      * nothing was set
   15854      */
   15855     public @ColorInt int getOutlineAmbientShadowColor() {
   15856         return mRenderNode.getAmbientShadowColor();
   15857     }
   15858 
   15859 
   15860     /** @hide */
   15861     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
   15862         mRenderNode.setRevealClip(shouldClip, x, y, radius);
   15863         invalidateViewProperty(false, false);
   15864     }
   15865 
   15866     /**
   15867      * Hit rectangle in parent's coordinates
   15868      *
   15869      * @param outRect The hit rectangle of the view.
   15870      */
   15871     public void getHitRect(Rect outRect) {
   15872         if (hasIdentityMatrix() || mAttachInfo == null) {
   15873             outRect.set(mLeft, mTop, mRight, mBottom);
   15874         } else {
   15875             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
   15876             tmpRect.set(0, 0, getWidth(), getHeight());
   15877             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
   15878             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
   15879                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
   15880         }
   15881     }
   15882 
   15883     /**
   15884      * Determines whether the given point, in local coordinates is inside the view.
   15885      */
   15886     /*package*/ final boolean pointInView(float localX, float localY) {
   15887         return pointInView(localX, localY, 0);
   15888     }
   15889 
   15890     /**
   15891      * Utility method to determine whether the given point, in local coordinates,
   15892      * is inside the view, where the area of the view is expanded by the slop factor.
   15893      * This method is called while processing touch-move events to determine if the event
   15894      * is still within the view.
   15895      *
   15896      * @hide
   15897      */
   15898     public boolean pointInView(float localX, float localY, float slop) {
   15899         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
   15900                 localY < ((mBottom - mTop) + slop);
   15901     }
   15902 
   15903     /**
   15904      * When a view has focus and the user navigates away from it, the next view is searched for
   15905      * starting from the rectangle filled in by this method.
   15906      *
   15907      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
   15908      * of the view.  However, if your view maintains some idea of internal selection,
   15909      * such as a cursor, or a selected row or column, you should override this method and
   15910      * fill in a more specific rectangle.
   15911      *
   15912      * @param r The rectangle to fill in, in this view's coordinates.
   15913      */
   15914     public void getFocusedRect(Rect r) {
   15915         getDrawingRect(r);
   15916     }
   15917 
   15918     /**
   15919      * If some part of this view is not clipped by any of its parents, then
   15920      * return that area in r in global (root) coordinates. To convert r to local
   15921      * coordinates (without taking possible View rotations into account), offset
   15922      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
   15923      * If the view is completely clipped or translated out, return false.
   15924      *
   15925      * @param r If true is returned, r holds the global coordinates of the
   15926      *        visible portion of this view.
   15927      * @param globalOffset If true is returned, globalOffset holds the dx,dy
   15928      *        between this view and its root. globalOffet may be null.
   15929      * @return true if r is non-empty (i.e. part of the view is visible at the
   15930      *         root level.
   15931      */
   15932     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
   15933         int width = mRight - mLeft;
   15934         int height = mBottom - mTop;
   15935         if (width > 0 && height > 0) {
   15936             r.set(0, 0, width, height);
   15937             if (globalOffset != null) {
   15938                 globalOffset.set(-mScrollX, -mScrollY);
   15939             }
   15940             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
   15941         }
   15942         return false;
   15943     }
   15944 
   15945     public final boolean getGlobalVisibleRect(Rect r) {
   15946         return getGlobalVisibleRect(r, null);
   15947     }
   15948 
   15949     public final boolean getLocalVisibleRect(Rect r) {
   15950         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
   15951         if (getGlobalVisibleRect(r, offset)) {
   15952             r.offset(-offset.x, -offset.y); // make r local
   15953             return true;
   15954         }
   15955         return false;
   15956     }
   15957 
   15958     /**
   15959      * Offset this view's vertical location by the specified number of pixels.
   15960      *
   15961      * @param offset the number of pixels to offset the view by
   15962      */
   15963     public void offsetTopAndBottom(int offset) {
   15964         if (offset != 0) {
   15965             final boolean matrixIsIdentity = hasIdentityMatrix();
   15966             if (matrixIsIdentity) {
   15967                 if (isHardwareAccelerated()) {
   15968                     invalidateViewProperty(false, false);
   15969                 } else {
   15970                     final ViewParent p = mParent;
   15971                     if (p != null && mAttachInfo != null) {
   15972                         final Rect r = mAttachInfo.mTmpInvalRect;
   15973                         int minTop;
   15974                         int maxBottom;
   15975                         int yLoc;
   15976                         if (offset < 0) {
   15977                             minTop = mTop + offset;
   15978                             maxBottom = mBottom;
   15979                             yLoc = offset;
   15980                         } else {
   15981                             minTop = mTop;
   15982                             maxBottom = mBottom + offset;
   15983                             yLoc = 0;
   15984                         }
   15985                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
   15986                         p.invalidateChild(this, r);
   15987                     }
   15988                 }
   15989             } else {
   15990                 invalidateViewProperty(false, false);
   15991             }
   15992 
   15993             mTop += offset;
   15994             mBottom += offset;
   15995             mRenderNode.offsetTopAndBottom(offset);
   15996             if (isHardwareAccelerated()) {
   15997                 invalidateViewProperty(false, false);
   15998                 invalidateParentIfNeededAndWasQuickRejected();
   15999             } else {
   16000                 if (!matrixIsIdentity) {
   16001                     invalidateViewProperty(false, true);
   16002                 }
   16003                 invalidateParentIfNeeded();
   16004             }
   16005             notifySubtreeAccessibilityStateChangedIfNeeded();
   16006         }
   16007     }
   16008 
   16009     /**
   16010      * Offset this view's horizontal location by the specified amount of pixels.
   16011      *
   16012      * @param offset the number of pixels to offset the view by
   16013      */
   16014     public void offsetLeftAndRight(int offset) {
   16015         if (offset != 0) {
   16016             final boolean matrixIsIdentity = hasIdentityMatrix();
   16017             if (matrixIsIdentity) {
   16018                 if (isHardwareAccelerated()) {
   16019                     invalidateViewProperty(false, false);
   16020                 } else {
   16021                     final ViewParent p = mParent;
   16022                     if (p != null && mAttachInfo != null) {
   16023                         final Rect r = mAttachInfo.mTmpInvalRect;
   16024                         int minLeft;
   16025                         int maxRight;
   16026                         if (offset < 0) {
   16027                             minLeft = mLeft + offset;
   16028                             maxRight = mRight;
   16029                         } else {
   16030                             minLeft = mLeft;
   16031                             maxRight = mRight + offset;
   16032                         }
   16033                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
   16034                         p.invalidateChild(this, r);
   16035                     }
   16036                 }
   16037             } else {
   16038                 invalidateViewProperty(false, false);
   16039             }
   16040 
   16041             mLeft += offset;
   16042             mRight += offset;
   16043             mRenderNode.offsetLeftAndRight(offset);
   16044             if (isHardwareAccelerated()) {
   16045                 invalidateViewProperty(false, false);
   16046                 invalidateParentIfNeededAndWasQuickRejected();
   16047             } else {
   16048                 if (!matrixIsIdentity) {
   16049                     invalidateViewProperty(false, true);
   16050                 }
   16051                 invalidateParentIfNeeded();
   16052             }
   16053             notifySubtreeAccessibilityStateChangedIfNeeded();
   16054         }
   16055     }
   16056 
   16057     /**
   16058      * Get the LayoutParams associated with this view. All views should have
   16059      * layout parameters. These supply parameters to the <i>parent</i> of this
   16060      * view specifying how it should be arranged. There are many subclasses of
   16061      * ViewGroup.LayoutParams, and these correspond to the different subclasses
   16062      * of ViewGroup that are responsible for arranging their children.
   16063      *
   16064      * This method may return null if this View is not attached to a parent
   16065      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
   16066      * was not invoked successfully. When a View is attached to a parent
   16067      * ViewGroup, this method must not return null.
   16068      *
   16069      * @return The LayoutParams associated with this view, or null if no
   16070      *         parameters have been set yet
   16071      */
   16072     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
   16073     public ViewGroup.LayoutParams getLayoutParams() {
   16074         return mLayoutParams;
   16075     }
   16076 
   16077     /**
   16078      * Set the layout parameters associated with this view. These supply
   16079      * parameters to the <i>parent</i> of this view specifying how it should be
   16080      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
   16081      * correspond to the different subclasses of ViewGroup that are responsible
   16082      * for arranging their children.
   16083      *
   16084      * @param params The layout parameters for this view, cannot be null
   16085      */
   16086     public void setLayoutParams(ViewGroup.LayoutParams params) {
   16087         if (params == null) {
   16088             throw new NullPointerException("Layout parameters cannot be null");
   16089         }
   16090         mLayoutParams = params;
   16091         resolveLayoutParams();
   16092         if (mParent instanceof ViewGroup) {
   16093             ((ViewGroup) mParent).onSetLayoutParams(this, params);
   16094         }
   16095         requestLayout();
   16096     }
   16097 
   16098     /**
   16099      * Resolve the layout parameters depending on the resolved layout direction
   16100      *
   16101      * @hide
   16102      */
   16103     public void resolveLayoutParams() {
   16104         if (mLayoutParams != null) {
   16105             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
   16106         }
   16107     }
   16108 
   16109     /**
   16110      * Set the scrolled position of your view. This will cause a call to
   16111      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   16112      * invalidated.
   16113      * @param x the x position to scroll to
   16114      * @param y the y position to scroll to
   16115      */
   16116     public void scrollTo(int x, int y) {
   16117         if (mScrollX != x || mScrollY != y) {
   16118             int oldX = mScrollX;
   16119             int oldY = mScrollY;
   16120             mScrollX = x;
   16121             mScrollY = y;
   16122             invalidateParentCaches();
   16123             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
   16124             if (!awakenScrollBars()) {
   16125                 postInvalidateOnAnimation();
   16126             }
   16127         }
   16128     }
   16129 
   16130     /**
   16131      * Move the scrolled position of your view. This will cause a call to
   16132      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   16133      * invalidated.
   16134      * @param x the amount of pixels to scroll by horizontally
   16135      * @param y the amount of pixels to scroll by vertically
   16136      */
   16137     public void scrollBy(int x, int y) {
   16138         scrollTo(mScrollX + x, mScrollY + y);
   16139     }
   16140 
   16141     /**
   16142      * <p>Trigger the scrollbars to draw. When invoked this method starts an
   16143      * animation to fade the scrollbars out after a default delay. If a subclass
   16144      * provides animated scrolling, the start delay should equal the duration
   16145      * of the scrolling animation.</p>
   16146      *
   16147      * <p>The animation starts only if at least one of the scrollbars is
   16148      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
   16149      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   16150      * this method returns true, and false otherwise. If the animation is
   16151      * started, this method calls {@link #invalidate()}; in that case the
   16152      * caller should not call {@link #invalidate()}.</p>
   16153      *
   16154      * <p>This method should be invoked every time a subclass directly updates
   16155      * the scroll parameters.</p>
   16156      *
   16157      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
   16158      * and {@link #scrollTo(int, int)}.</p>
   16159      *
   16160      * @return true if the animation is played, false otherwise
   16161      *
   16162      * @see #awakenScrollBars(int)
   16163      * @see #scrollBy(int, int)
   16164      * @see #scrollTo(int, int)
   16165      * @see #isHorizontalScrollBarEnabled()
   16166      * @see #isVerticalScrollBarEnabled()
   16167      * @see #setHorizontalScrollBarEnabled(boolean)
   16168      * @see #setVerticalScrollBarEnabled(boolean)
   16169      */
   16170     protected boolean awakenScrollBars() {
   16171         return mScrollCache != null &&
   16172                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
   16173     }
   16174 
   16175     /**
   16176      * Trigger the scrollbars to draw.
   16177      * This method differs from awakenScrollBars() only in its default duration.
   16178      * initialAwakenScrollBars() will show the scroll bars for longer than
   16179      * usual to give the user more of a chance to notice them.
   16180      *
   16181      * @return true if the animation is played, false otherwise.
   16182      */
   16183     private boolean initialAwakenScrollBars() {
   16184         return mScrollCache != null &&
   16185                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
   16186     }
   16187 
   16188     /**
   16189      * <p>
   16190      * Trigger the scrollbars to draw. When invoked this method starts an
   16191      * animation to fade the scrollbars out after a fixed delay. If a subclass
   16192      * provides animated scrolling, the start delay should equal the duration of
   16193      * the scrolling animation.
   16194      * </p>
   16195      *
   16196      * <p>
   16197      * The animation starts only if at least one of the scrollbars is enabled,
   16198      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   16199      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   16200      * this method returns true, and false otherwise. If the animation is
   16201      * started, this method calls {@link #invalidate()}; in that case the caller
   16202      * should not call {@link #invalidate()}.
   16203      * </p>
   16204      *
   16205      * <p>
   16206      * This method should be invoked every time a subclass directly updates the
   16207      * scroll parameters.
   16208      * </p>
   16209      *
   16210      * @param startDelay the delay, in milliseconds, after which the animation
   16211      *        should start; when the delay is 0, the animation starts
   16212      *        immediately
   16213      * @return true if the animation is played, false otherwise
   16214      *
   16215      * @see #scrollBy(int, int)
   16216      * @see #scrollTo(int, int)
   16217      * @see #isHorizontalScrollBarEnabled()
   16218      * @see #isVerticalScrollBarEnabled()
   16219      * @see #setHorizontalScrollBarEnabled(boolean)
   16220      * @see #setVerticalScrollBarEnabled(boolean)
   16221      */
   16222     protected boolean awakenScrollBars(int startDelay) {
   16223         return awakenScrollBars(startDelay, true);
   16224     }
   16225 
   16226     /**
   16227      * <p>
   16228      * Trigger the scrollbars to draw. When invoked this method starts an
   16229      * animation to fade the scrollbars out after a fixed delay. If a subclass
   16230      * provides animated scrolling, the start delay should equal the duration of
   16231      * the scrolling animation.
   16232      * </p>
   16233      *
   16234      * <p>
   16235      * The animation starts only if at least one of the scrollbars is enabled,
   16236      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   16237      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   16238      * this method returns true, and false otherwise. If the animation is
   16239      * started, this method calls {@link #invalidate()} if the invalidate parameter
   16240      * is set to true; in that case the caller
   16241      * should not call {@link #invalidate()}.
   16242      * </p>
   16243      *
   16244      * <p>
   16245      * This method should be invoked every time a subclass directly updates the
   16246      * scroll parameters.
   16247      * </p>
   16248      *
   16249      * @param startDelay the delay, in milliseconds, after which the animation
   16250      *        should start; when the delay is 0, the animation starts
   16251      *        immediately
   16252      *
   16253      * @param invalidate Whether this method should call invalidate
   16254      *
   16255      * @return true if the animation is played, false otherwise
   16256      *
   16257      * @see #scrollBy(int, int)
   16258      * @see #scrollTo(int, int)
   16259      * @see #isHorizontalScrollBarEnabled()
   16260      * @see #isVerticalScrollBarEnabled()
   16261      * @see #setHorizontalScrollBarEnabled(boolean)
   16262      * @see #setVerticalScrollBarEnabled(boolean)
   16263      */
   16264     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
   16265         final ScrollabilityCache scrollCache = mScrollCache;
   16266 
   16267         if (scrollCache == null || !scrollCache.fadeScrollBars) {
   16268             return false;
   16269         }
   16270 
   16271         if (scrollCache.scrollBar == null) {
   16272             scrollCache.scrollBar = new ScrollBarDrawable();
   16273             scrollCache.scrollBar.setState(getDrawableState());
   16274             scrollCache.scrollBar.setCallback(this);
   16275         }
   16276 
   16277         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
   16278 
   16279             if (invalidate) {
   16280                 // Invalidate to show the scrollbars
   16281                 postInvalidateOnAnimation();
   16282             }
   16283 
   16284             if (scrollCache.state == ScrollabilityCache.OFF) {
   16285                 // FIXME: this is copied from WindowManagerService.
   16286                 // We should get this value from the system when it
   16287                 // is possible to do so.
   16288                 final int KEY_REPEAT_FIRST_DELAY = 750;
   16289                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
   16290             }
   16291 
   16292             // Tell mScrollCache when we should start fading. This may
   16293             // extend the fade start time if one was already scheduled
   16294             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
   16295             scrollCache.fadeStartTime = fadeStartTime;
   16296             scrollCache.state = ScrollabilityCache.ON;
   16297 
   16298             // Schedule our fader to run, unscheduling any old ones first
   16299             if (mAttachInfo != null) {
   16300                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
   16301                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
   16302             }
   16303 
   16304             return true;
   16305         }
   16306 
   16307         return false;
   16308     }
   16309 
   16310     /**
   16311      * Do not invalidate views which are not visible and which are not running an animation. They
   16312      * will not get drawn and they should not set dirty flags as if they will be drawn
   16313      */
   16314     private boolean skipInvalidate() {
   16315         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
   16316                 (!(mParent instanceof ViewGroup) ||
   16317                         !((ViewGroup) mParent).isViewTransitioning(this));
   16318     }
   16319 
   16320     /**
   16321      * Mark the area defined by dirty as needing to be drawn. If the view is
   16322      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   16323      * point in the future.
   16324      * <p>
   16325      * This must be called from a UI thread. To call from a non-UI thread, call
   16326      * {@link #postInvalidate()}.
   16327      * <p>
   16328      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
   16329      * {@code dirty}.
   16330      *
   16331      * @param dirty the rectangle representing the bounds of the dirty region
   16332      *
   16333      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
   16334      * the importance of the dirty rectangle. In API 21 the given rectangle is
   16335      * ignored entirely in favor of an internally-calculated area instead.
   16336      * Because of this, clients are encouraged to just call {@link #invalidate()}.
   16337      */
   16338     @Deprecated
   16339     public void invalidate(Rect dirty) {
   16340         final int scrollX = mScrollX;
   16341         final int scrollY = mScrollY;
   16342         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
   16343                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
   16344     }
   16345 
   16346     /**
   16347      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
   16348      * coordinates of the dirty rect are relative to the view. If the view is
   16349      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   16350      * point in the future.
   16351      * <p>
   16352      * This must be called from a UI thread. To call from a non-UI thread, call
   16353      * {@link #postInvalidate()}.
   16354      *
   16355      * @param l the left position of the dirty region
   16356      * @param t the top position of the dirty region
   16357      * @param r the right position of the dirty region
   16358      * @param b the bottom position of the dirty region
   16359      *
   16360      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
   16361      * the importance of the dirty rectangle. In API 21 the given rectangle is
   16362      * ignored entirely in favor of an internally-calculated area instead.
   16363      * Because of this, clients are encouraged to just call {@link #invalidate()}.
   16364      */
   16365     @Deprecated
   16366     public void invalidate(int l, int t, int r, int b) {
   16367         final int scrollX = mScrollX;
   16368         final int scrollY = mScrollY;
   16369         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
   16370     }
   16371 
   16372     /**
   16373      * Invalidate the whole view. If the view is visible,
   16374      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
   16375      * the future.
   16376      * <p>
   16377      * This must be called from a UI thread. To call from a non-UI thread, call
   16378      * {@link #postInvalidate()}.
   16379      */
   16380     public void invalidate() {
   16381         invalidate(true);
   16382     }
   16383 
   16384     /**
   16385      * This is where the invalidate() work actually happens. A full invalidate()
   16386      * causes the drawing cache to be invalidated, but this function can be
   16387      * called with invalidateCache set to false to skip that invalidation step
   16388      * for cases that do not need it (for example, a component that remains at
   16389      * the same dimensions with the same content).
   16390      *
   16391      * @param invalidateCache Whether the drawing cache for this view should be
   16392      *            invalidated as well. This is usually true for a full
   16393      *            invalidate, but may be set to false if the View's contents or
   16394      *            dimensions have not changed.
   16395      * @hide
   16396      */
   16397     public void invalidate(boolean invalidateCache) {
   16398         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
   16399     }
   16400 
   16401     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
   16402             boolean fullInvalidate) {
   16403         if (mGhostView != null) {
   16404             mGhostView.invalidate(true);
   16405             return;
   16406         }
   16407 
   16408         if (skipInvalidate()) {
   16409             return;
   16410         }
   16411 
   16412         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
   16413                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
   16414                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
   16415                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
   16416             if (fullInvalidate) {
   16417                 mLastIsOpaque = isOpaque();
   16418                 mPrivateFlags &= ~PFLAG_DRAWN;
   16419             }
   16420 
   16421             mPrivateFlags |= PFLAG_DIRTY;
   16422 
   16423             if (invalidateCache) {
   16424                 mPrivateFlags |= PFLAG_INVALIDATED;
   16425                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   16426             }
   16427 
   16428             // Propagate the damage rectangle to the parent view.
   16429             final AttachInfo ai = mAttachInfo;
   16430             final ViewParent p = mParent;
   16431             if (p != null && ai != null && l < r && t < b) {
   16432                 final Rect damage = ai.mTmpInvalRect;
   16433                 damage.set(l, t, r, b);
   16434                 p.invalidateChild(this, damage);
   16435             }
   16436 
   16437             // Damage the entire projection receiver, if necessary.
   16438             if (mBackground != null && mBackground.isProjected()) {
   16439                 final View receiver = getProjectionReceiver();
   16440                 if (receiver != null) {
   16441                     receiver.damageInParent();
   16442                 }
   16443             }
   16444         }
   16445     }
   16446 
   16447     /**
   16448      * @return this view's projection receiver, or {@code null} if none exists
   16449      */
   16450     private View getProjectionReceiver() {
   16451         ViewParent p = getParent();
   16452         while (p != null && p instanceof View) {
   16453             final View v = (View) p;
   16454             if (v.isProjectionReceiver()) {
   16455                 return v;
   16456             }
   16457             p = p.getParent();
   16458         }
   16459 
   16460         return null;
   16461     }
   16462 
   16463     /**
   16464      * @return whether the view is a projection receiver
   16465      */
   16466     private boolean isProjectionReceiver() {
   16467         return mBackground != null;
   16468     }
   16469 
   16470     /**
   16471      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
   16472      * set any flags or handle all of the cases handled by the default invalidation methods.
   16473      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
   16474      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
   16475      * walk up the hierarchy, transforming the dirty rect as necessary.
   16476      *
   16477      * The method also handles normal invalidation logic if display list properties are not
   16478      * being used in this view. The invalidateParent and forceRedraw flags are used by that
   16479      * backup approach, to handle these cases used in the various property-setting methods.
   16480      *
   16481      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
   16482      * are not being used in this view
   16483      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
   16484      * list properties are not being used in this view
   16485      */
   16486     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
   16487         if (!isHardwareAccelerated()
   16488                 || !mRenderNode.isValid()
   16489                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
   16490             if (invalidateParent) {
   16491                 invalidateParentCaches();
   16492             }
   16493             if (forceRedraw) {
   16494                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   16495             }
   16496             invalidate(false);
   16497         } else {
   16498             damageInParent();
   16499         }
   16500     }
   16501 
   16502     /**
   16503      * Tells the parent view to damage this view's bounds.
   16504      *
   16505      * @hide
   16506      */
   16507     protected void damageInParent() {
   16508         if (mParent != null && mAttachInfo != null) {
   16509             mParent.onDescendantInvalidated(this, this);
   16510         }
   16511     }
   16512 
   16513     /**
   16514      * Utility method to transform a given Rect by the current matrix of this view.
   16515      */
   16516     void transformRect(final Rect rect) {
   16517         if (!getMatrix().isIdentity()) {
   16518             RectF boundingRect = mAttachInfo.mTmpTransformRect;
   16519             boundingRect.set(rect);
   16520             getMatrix().mapRect(boundingRect);
   16521             rect.set((int) Math.floor(boundingRect.left),
   16522                     (int) Math.floor(boundingRect.top),
   16523                     (int) Math.ceil(boundingRect.right),
   16524                     (int) Math.ceil(boundingRect.bottom));
   16525         }
   16526     }
   16527 
   16528     /**
   16529      * Used to indicate that the parent of this view should clear its caches. This functionality
   16530      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   16531      * which is necessary when various parent-managed properties of the view change, such as
   16532      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
   16533      * clears the parent caches and does not causes an invalidate event.
   16534      *
   16535      * @hide
   16536      */
   16537     protected void invalidateParentCaches() {
   16538         if (mParent instanceof View) {
   16539             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
   16540         }
   16541     }
   16542 
   16543     /**
   16544      * Used to indicate that the parent of this view should be invalidated. This functionality
   16545      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   16546      * which is necessary when various parent-managed properties of the view change, such as
   16547      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
   16548      * an invalidation event to the parent.
   16549      *
   16550      * @hide
   16551      */
   16552     protected void invalidateParentIfNeeded() {
   16553         if (isHardwareAccelerated() && mParent instanceof View) {
   16554             ((View) mParent).invalidate(true);
   16555         }
   16556     }
   16557 
   16558     /**
   16559      * @hide
   16560      */
   16561     protected void invalidateParentIfNeededAndWasQuickRejected() {
   16562         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
   16563             // View was rejected last time it was drawn by its parent; this may have changed
   16564             invalidateParentIfNeeded();
   16565         }
   16566     }
   16567 
   16568     /**
   16569      * Indicates whether this View is opaque. An opaque View guarantees that it will
   16570      * draw all the pixels overlapping its bounds using a fully opaque color.
   16571      *
   16572      * Subclasses of View should override this method whenever possible to indicate
   16573      * whether an instance is opaque. Opaque Views are treated in a special way by
   16574      * the View hierarchy, possibly allowing it to perform optimizations during
   16575      * invalidate/draw passes.
   16576      *
   16577      * @return True if this View is guaranteed to be fully opaque, false otherwise.
   16578      */
   16579     @ViewDebug.ExportedProperty(category = "drawing")
   16580     public boolean isOpaque() {
   16581         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
   16582                 getFinalAlpha() >= 1.0f;
   16583     }
   16584 
   16585     /**
   16586      * @hide
   16587      */
   16588     protected void computeOpaqueFlags() {
   16589         // Opaque if:
   16590         //   - Has a background
   16591         //   - Background is opaque
   16592         //   - Doesn't have scrollbars or scrollbars overlay
   16593 
   16594         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
   16595             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
   16596         } else {
   16597             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
   16598         }
   16599 
   16600         final int flags = mViewFlags;
   16601         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
   16602                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
   16603                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
   16604             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
   16605         } else {
   16606             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
   16607         }
   16608     }
   16609 
   16610     /**
   16611      * @hide
   16612      */
   16613     protected boolean hasOpaqueScrollbars() {
   16614         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
   16615     }
   16616 
   16617     /**
   16618      * @return A handler associated with the thread running the View. This
   16619      * handler can be used to pump events in the UI events queue.
   16620      */
   16621     public Handler getHandler() {
   16622         final AttachInfo attachInfo = mAttachInfo;
   16623         if (attachInfo != null) {
   16624             return attachInfo.mHandler;
   16625         }
   16626         return null;
   16627     }
   16628 
   16629     /**
   16630      * Returns the queue of runnable for this view.
   16631      *
   16632      * @return the queue of runnables for this view
   16633      */
   16634     private HandlerActionQueue getRunQueue() {
   16635         if (mRunQueue == null) {
   16636             mRunQueue = new HandlerActionQueue();
   16637         }
   16638         return mRunQueue;
   16639     }
   16640 
   16641     /**
   16642      * Gets the view root associated with the View.
   16643      * @return The view root, or null if none.
   16644      * @hide
   16645      */
   16646     public ViewRootImpl getViewRootImpl() {
   16647         if (mAttachInfo != null) {
   16648             return mAttachInfo.mViewRootImpl;
   16649         }
   16650         return null;
   16651     }
   16652 
   16653     /**
   16654      * @hide
   16655      */
   16656     public ThreadedRenderer getThreadedRenderer() {
   16657         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
   16658     }
   16659 
   16660     /**
   16661      * <p>Causes the Runnable to be added to the message queue.
   16662      * The runnable will be run on the user interface thread.</p>
   16663      *
   16664      * @param action The Runnable that will be executed.
   16665      *
   16666      * @return Returns true if the Runnable was successfully placed in to the
   16667      *         message queue.  Returns false on failure, usually because the
   16668      *         looper processing the message queue is exiting.
   16669      *
   16670      * @see #postDelayed
   16671      * @see #removeCallbacks
   16672      */
   16673     public boolean post(Runnable action) {
   16674         final AttachInfo attachInfo = mAttachInfo;
   16675         if (attachInfo != null) {
   16676             return attachInfo.mHandler.post(action);
   16677         }
   16678 
   16679         // Postpone the runnable until we know on which thread it needs to run.
   16680         // Assume that the runnable will be successfully placed after attach.
   16681         getRunQueue().post(action);
   16682         return true;
   16683     }
   16684 
   16685     /**
   16686      * <p>Causes the Runnable to be added to the message queue, to be run
   16687      * after the specified amount of time elapses.
   16688      * The runnable will be run on the user interface thread.</p>
   16689      *
   16690      * @param action The Runnable that will be executed.
   16691      * @param delayMillis The delay (in milliseconds) until the Runnable
   16692      *        will be executed.
   16693      *
   16694      * @return true if the Runnable was successfully placed in to the
   16695      *         message queue.  Returns false on failure, usually because the
   16696      *         looper processing the message queue is exiting.  Note that a
   16697      *         result of true does not mean the Runnable will be processed --
   16698      *         if the looper is quit before the delivery time of the message
   16699      *         occurs then the message will be dropped.
   16700      *
   16701      * @see #post
   16702      * @see #removeCallbacks
   16703      */
   16704     public boolean postDelayed(Runnable action, long delayMillis) {
   16705         final AttachInfo attachInfo = mAttachInfo;
   16706         if (attachInfo != null) {
   16707             return attachInfo.mHandler.postDelayed(action, delayMillis);
   16708         }
   16709 
   16710         // Postpone the runnable until we know on which thread it needs to run.
   16711         // Assume that the runnable will be successfully placed after attach.
   16712         getRunQueue().postDelayed(action, delayMillis);
   16713         return true;
   16714     }
   16715 
   16716     /**
   16717      * <p>Causes the Runnable to execute on the next animation time step.
   16718      * The runnable will be run on the user interface thread.</p>
   16719      *
   16720      * @param action The Runnable that will be executed.
   16721      *
   16722      * @see #postOnAnimationDelayed
   16723      * @see #removeCallbacks
   16724      */
   16725     public void postOnAnimation(Runnable action) {
   16726         final AttachInfo attachInfo = mAttachInfo;
   16727         if (attachInfo != null) {
   16728             attachInfo.mViewRootImpl.mChoreographer.postCallback(
   16729                     Choreographer.CALLBACK_ANIMATION, action, null);
   16730         } else {
   16731             // Postpone the runnable until we know
   16732             // on which thread it needs to run.
   16733             getRunQueue().post(action);
   16734         }
   16735     }
   16736 
   16737     /**
   16738      * <p>Causes the Runnable to execute on the next animation time step,
   16739      * after the specified amount of time elapses.
   16740      * The runnable will be run on the user interface thread.</p>
   16741      *
   16742      * @param action The Runnable that will be executed.
   16743      * @param delayMillis The delay (in milliseconds) until the Runnable
   16744      *        will be executed.
   16745      *
   16746      * @see #postOnAnimation
   16747      * @see #removeCallbacks
   16748      */
   16749     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
   16750         final AttachInfo attachInfo = mAttachInfo;
   16751         if (attachInfo != null) {
   16752             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   16753                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
   16754         } else {
   16755             // Postpone the runnable until we know
   16756             // on which thread it needs to run.
   16757             getRunQueue().postDelayed(action, delayMillis);
   16758         }
   16759     }
   16760 
   16761     /**
   16762      * <p>Removes the specified Runnable from the message queue.</p>
   16763      *
   16764      * @param action The Runnable to remove from the message handling queue
   16765      *
   16766      * @return true if this view could ask the Handler to remove the Runnable,
   16767      *         false otherwise. When the returned value is true, the Runnable
   16768      *         may or may not have been actually removed from the message queue
   16769      *         (for instance, if the Runnable was not in the queue already.)
   16770      *
   16771      * @see #post
   16772      * @see #postDelayed
   16773      * @see #postOnAnimation
   16774      * @see #postOnAnimationDelayed
   16775      */
   16776     public boolean removeCallbacks(Runnable action) {
   16777         if (action != null) {
   16778             final AttachInfo attachInfo = mAttachInfo;
   16779             if (attachInfo != null) {
   16780                 attachInfo.mHandler.removeCallbacks(action);
   16781                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   16782                         Choreographer.CALLBACK_ANIMATION, action, null);
   16783             }
   16784             getRunQueue().removeCallbacks(action);
   16785         }
   16786         return true;
   16787     }
   16788 
   16789     /**
   16790      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
   16791      * Use this to invalidate the View from a non-UI thread.</p>
   16792      *
   16793      * <p>This method can be invoked from outside of the UI thread
   16794      * only when this View is attached to a window.</p>
   16795      *
   16796      * @see #invalidate()
   16797      * @see #postInvalidateDelayed(long)
   16798      */
   16799     public void postInvalidate() {
   16800         postInvalidateDelayed(0);
   16801     }
   16802 
   16803     /**
   16804      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   16805      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
   16806      *
   16807      * <p>This method can be invoked from outside of the UI thread
   16808      * only when this View is attached to a window.</p>
   16809      *
   16810      * @param left The left coordinate of the rectangle to invalidate.
   16811      * @param top The top coordinate of the rectangle to invalidate.
   16812      * @param right The right coordinate of the rectangle to invalidate.
   16813      * @param bottom The bottom coordinate of the rectangle to invalidate.
   16814      *
   16815      * @see #invalidate(int, int, int, int)
   16816      * @see #invalidate(Rect)
   16817      * @see #postInvalidateDelayed(long, int, int, int, int)
   16818      */
   16819     public void postInvalidate(int left, int top, int right, int bottom) {
   16820         postInvalidateDelayed(0, left, top, right, bottom);
   16821     }
   16822 
   16823     /**
   16824      * <p>Cause an invalidate to happen on a subsequent cycle through the event
   16825      * loop. Waits for the specified amount of time.</p>
   16826      *
   16827      * <p>This method can be invoked from outside of the UI thread
   16828      * only when this View is attached to a window.</p>
   16829      *
   16830      * @param delayMilliseconds the duration in milliseconds to delay the
   16831      *         invalidation by
   16832      *
   16833      * @see #invalidate()
   16834      * @see #postInvalidate()
   16835      */
   16836     public void postInvalidateDelayed(long delayMilliseconds) {
   16837         // We try only with the AttachInfo because there's no point in invalidating
   16838         // if we are not attached to our window
   16839         final AttachInfo attachInfo = mAttachInfo;
   16840         if (attachInfo != null) {
   16841             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
   16842         }
   16843     }
   16844 
   16845     /**
   16846      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   16847      * through the event loop. Waits for the specified amount of time.</p>
   16848      *
   16849      * <p>This method can be invoked from outside of the UI thread
   16850      * only when this View is attached to a window.</p>
   16851      *
   16852      * @param delayMilliseconds the duration in milliseconds to delay the
   16853      *         invalidation by
   16854      * @param left The left coordinate of the rectangle to invalidate.
   16855      * @param top The top coordinate of the rectangle to invalidate.
   16856      * @param right The right coordinate of the rectangle to invalidate.
   16857      * @param bottom The bottom coordinate of the rectangle to invalidate.
   16858      *
   16859      * @see #invalidate(int, int, int, int)
   16860      * @see #invalidate(Rect)
   16861      * @see #postInvalidate(int, int, int, int)
   16862      */
   16863     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
   16864             int right, int bottom) {
   16865 
   16866         // We try only with the AttachInfo because there's no point in invalidating
   16867         // if we are not attached to our window
   16868         final AttachInfo attachInfo = mAttachInfo;
   16869         if (attachInfo != null) {
   16870             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   16871             info.target = this;
   16872             info.left = left;
   16873             info.top = top;
   16874             info.right = right;
   16875             info.bottom = bottom;
   16876 
   16877             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
   16878         }
   16879     }
   16880 
   16881     /**
   16882      * <p>Cause an invalidate to happen on the next animation time step, typically the
   16883      * next display frame.</p>
   16884      *
   16885      * <p>This method can be invoked from outside of the UI thread
   16886      * only when this View is attached to a window.</p>
   16887      *
   16888      * @see #invalidate()
   16889      */
   16890     public void postInvalidateOnAnimation() {
   16891         // We try only with the AttachInfo because there's no point in invalidating
   16892         // if we are not attached to our window
   16893         final AttachInfo attachInfo = mAttachInfo;
   16894         if (attachInfo != null) {
   16895             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
   16896         }
   16897     }
   16898 
   16899     /**
   16900      * <p>Cause an invalidate of the specified area to happen on the next animation
   16901      * time step, typically the next display frame.</p>
   16902      *
   16903      * <p>This method can be invoked from outside of the UI thread
   16904      * only when this View is attached to a window.</p>
   16905      *
   16906      * @param left The left coordinate of the rectangle to invalidate.
   16907      * @param top The top coordinate of the rectangle to invalidate.
   16908      * @param right The right coordinate of the rectangle to invalidate.
   16909      * @param bottom The bottom coordinate of the rectangle to invalidate.
   16910      *
   16911      * @see #invalidate(int, int, int, int)
   16912      * @see #invalidate(Rect)
   16913      */
   16914     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
   16915         // We try only with the AttachInfo because there's no point in invalidating
   16916         // if we are not attached to our window
   16917         final AttachInfo attachInfo = mAttachInfo;
   16918         if (attachInfo != null) {
   16919             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   16920             info.target = this;
   16921             info.left = left;
   16922             info.top = top;
   16923             info.right = right;
   16924             info.bottom = bottom;
   16925 
   16926             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
   16927         }
   16928     }
   16929 
   16930     /**
   16931      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
   16932      * This event is sent at most once every
   16933      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
   16934      */
   16935     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
   16936         if (mSendViewScrolledAccessibilityEvent == null) {
   16937             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
   16938         }
   16939         mSendViewScrolledAccessibilityEvent.post(dx, dy);
   16940     }
   16941 
   16942     /**
   16943      * Called by a parent to request that a child update its values for mScrollX
   16944      * and mScrollY if necessary. This will typically be done if the child is
   16945      * animating a scroll using a {@link android.widget.Scroller Scroller}
   16946      * object.
   16947      */
   16948     public void computeScroll() {
   16949     }
   16950 
   16951     /**
   16952      * <p>Indicate whether the horizontal edges are faded when the view is
   16953      * scrolled horizontally.</p>
   16954      *
   16955      * @return true if the horizontal edges should are faded on scroll, false
   16956      *         otherwise
   16957      *
   16958      * @see #setHorizontalFadingEdgeEnabled(boolean)
   16959      *
   16960      * @attr ref android.R.styleable#View_requiresFadingEdge
   16961      */
   16962     public boolean isHorizontalFadingEdgeEnabled() {
   16963         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
   16964     }
   16965 
   16966     /**
   16967      * <p>Define whether the horizontal edges should be faded when this view
   16968      * is scrolled horizontally.</p>
   16969      *
   16970      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
   16971      *                                    be faded when the view is scrolled
   16972      *                                    horizontally
   16973      *
   16974      * @see #isHorizontalFadingEdgeEnabled()
   16975      *
   16976      * @attr ref android.R.styleable#View_requiresFadingEdge
   16977      */
   16978     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
   16979         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
   16980             if (horizontalFadingEdgeEnabled) {
   16981                 initScrollCache();
   16982             }
   16983 
   16984             mViewFlags ^= FADING_EDGE_HORIZONTAL;
   16985         }
   16986     }
   16987 
   16988     /**
   16989      * <p>Indicate whether the vertical edges are faded when the view is
   16990      * scrolled horizontally.</p>
   16991      *
   16992      * @return true if the vertical edges should are faded on scroll, false
   16993      *         otherwise
   16994      *
   16995      * @see #setVerticalFadingEdgeEnabled(boolean)
   16996      *
   16997      * @attr ref android.R.styleable#View_requiresFadingEdge
   16998      */
   16999     public boolean isVerticalFadingEdgeEnabled() {
   17000         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
   17001     }
   17002 
   17003     /**
   17004      * <p>Define whether the vertical edges should be faded when this view
   17005      * is scrolled vertically.</p>
   17006      *
   17007      * @param verticalFadingEdgeEnabled true if the vertical edges should
   17008      *                                  be faded when the view is scrolled
   17009      *                                  vertically
   17010      *
   17011      * @see #isVerticalFadingEdgeEnabled()
   17012      *
   17013      * @attr ref android.R.styleable#View_requiresFadingEdge
   17014      */
   17015     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
   17016         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
   17017             if (verticalFadingEdgeEnabled) {
   17018                 initScrollCache();
   17019             }
   17020 
   17021             mViewFlags ^= FADING_EDGE_VERTICAL;
   17022         }
   17023     }
   17024 
   17025     /**
   17026      * Returns the strength, or intensity, of the top faded edge. The strength is
   17027      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   17028      * returns 0.0 or 1.0 but no value in between.
   17029      *
   17030      * Subclasses should override this method to provide a smoother fade transition
   17031      * when scrolling occurs.
   17032      *
   17033      * @return the intensity of the top fade as a float between 0.0f and 1.0f
   17034      */
   17035     protected float getTopFadingEdgeStrength() {
   17036         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
   17037     }
   17038 
   17039     /**
   17040      * Returns the strength, or intensity, of the bottom faded edge. The strength is
   17041      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   17042      * returns 0.0 or 1.0 but no value in between.
   17043      *
   17044      * Subclasses should override this method to provide a smoother fade transition
   17045      * when scrolling occurs.
   17046      *
   17047      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
   17048      */
   17049     protected float getBottomFadingEdgeStrength() {
   17050         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
   17051                 computeVerticalScrollRange() ? 1.0f : 0.0f;
   17052     }
   17053 
   17054     /**
   17055      * Returns the strength, or intensity, of the left faded edge. The strength is
   17056      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   17057      * returns 0.0 or 1.0 but no value in between.
   17058      *
   17059      * Subclasses should override this method to provide a smoother fade transition
   17060      * when scrolling occurs.
   17061      *
   17062      * @return the intensity of the left fade as a float between 0.0f and 1.0f
   17063      */
   17064     protected float getLeftFadingEdgeStrength() {
   17065         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
   17066     }
   17067 
   17068     /**
   17069      * Returns the strength, or intensity, of the right faded edge. The strength is
   17070      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   17071      * returns 0.0 or 1.0 but no value in between.
   17072      *
   17073      * Subclasses should override this method to provide a smoother fade transition
   17074      * when scrolling occurs.
   17075      *
   17076      * @return the intensity of the right fade as a float between 0.0f and 1.0f
   17077      */
   17078     protected float getRightFadingEdgeStrength() {
   17079         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
   17080                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
   17081     }
   17082 
   17083     /**
   17084      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
   17085      * scrollbar is not drawn by default.</p>
   17086      *
   17087      * @return true if the horizontal scrollbar should be painted, false
   17088      *         otherwise
   17089      *
   17090      * @see #setHorizontalScrollBarEnabled(boolean)
   17091      */
   17092     public boolean isHorizontalScrollBarEnabled() {
   17093         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   17094     }
   17095 
   17096     /**
   17097      * <p>Define whether the horizontal scrollbar should be drawn or not. The
   17098      * scrollbar is not drawn by default.</p>
   17099      *
   17100      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
   17101      *                                   be painted
   17102      *
   17103      * @see #isHorizontalScrollBarEnabled()
   17104      */
   17105     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
   17106         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
   17107             mViewFlags ^= SCROLLBARS_HORIZONTAL;
   17108             computeOpaqueFlags();
   17109             resolvePadding();
   17110         }
   17111     }
   17112 
   17113     /**
   17114      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
   17115      * scrollbar is not drawn by default.</p>
   17116      *
   17117      * @return true if the vertical scrollbar should be painted, false
   17118      *         otherwise
   17119      *
   17120      * @see #setVerticalScrollBarEnabled(boolean)
   17121      */
   17122     public boolean isVerticalScrollBarEnabled() {
   17123         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
   17124     }
   17125 
   17126     /**
   17127      * <p>Define whether the vertical scrollbar should be drawn or not. The
   17128      * scrollbar is not drawn by default.</p>
   17129      *
   17130      * @param verticalScrollBarEnabled true if the vertical scrollbar should
   17131      *                                 be painted
   17132      *
   17133      * @see #isVerticalScrollBarEnabled()
   17134      */
   17135     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
   17136         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
   17137             mViewFlags ^= SCROLLBARS_VERTICAL;
   17138             computeOpaqueFlags();
   17139             resolvePadding();
   17140         }
   17141     }
   17142 
   17143     /**
   17144      * @hide
   17145      */
   17146     protected void recomputePadding() {
   17147         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   17148     }
   17149 
   17150     /**
   17151      * Define whether scrollbars will fade when the view is not scrolling.
   17152      *
   17153      * @param fadeScrollbars whether to enable fading
   17154      *
   17155      * @attr ref android.R.styleable#View_fadeScrollbars
   17156      */
   17157     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
   17158         initScrollCache();
   17159         final ScrollabilityCache scrollabilityCache = mScrollCache;
   17160         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   17161         if (fadeScrollbars) {
   17162             scrollabilityCache.state = ScrollabilityCache.OFF;
   17163         } else {
   17164             scrollabilityCache.state = ScrollabilityCache.ON;
   17165         }
   17166     }
   17167 
   17168     /**
   17169      *
   17170      * Returns true if scrollbars will fade when this view is not scrolling
   17171      *
   17172      * @return true if scrollbar fading is enabled
   17173      *
   17174      * @attr ref android.R.styleable#View_fadeScrollbars
   17175      */
   17176     public boolean isScrollbarFadingEnabled() {
   17177         return mScrollCache != null && mScrollCache.fadeScrollBars;
   17178     }
   17179 
   17180     /**
   17181      *
   17182      * Returns the delay before scrollbars fade.
   17183      *
   17184      * @return the delay before scrollbars fade
   17185      *
   17186      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   17187      */
   17188     public int getScrollBarDefaultDelayBeforeFade() {
   17189         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
   17190                 mScrollCache.scrollBarDefaultDelayBeforeFade;
   17191     }
   17192 
   17193     /**
   17194      * Define the delay before scrollbars fade.
   17195      *
   17196      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
   17197      *
   17198      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   17199      */
   17200     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
   17201         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
   17202     }
   17203 
   17204     /**
   17205      *
   17206      * Returns the scrollbar fade duration.
   17207      *
   17208      * @return the scrollbar fade duration, in milliseconds
   17209      *
   17210      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   17211      */
   17212     public int getScrollBarFadeDuration() {
   17213         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
   17214                 mScrollCache.scrollBarFadeDuration;
   17215     }
   17216 
   17217     /**
   17218      * Define the scrollbar fade duration.
   17219      *
   17220      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
   17221      *
   17222      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   17223      */
   17224     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
   17225         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
   17226     }
   17227 
   17228     /**
   17229      *
   17230      * Returns the scrollbar size.
   17231      *
   17232      * @return the scrollbar size
   17233      *
   17234      * @attr ref android.R.styleable#View_scrollbarSize
   17235      */
   17236     public int getScrollBarSize() {
   17237         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
   17238                 mScrollCache.scrollBarSize;
   17239     }
   17240 
   17241     /**
   17242      * Define the scrollbar size.
   17243      *
   17244      * @param scrollBarSize - the scrollbar size
   17245      *
   17246      * @attr ref android.R.styleable#View_scrollbarSize
   17247      */
   17248     public void setScrollBarSize(int scrollBarSize) {
   17249         getScrollCache().scrollBarSize = scrollBarSize;
   17250     }
   17251 
   17252     /**
   17253      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
   17254      * inset. When inset, they add to the padding of the view. And the scrollbars
   17255      * can be drawn inside the padding area or on the edge of the view. For example,
   17256      * if a view has a background drawable and you want to draw the scrollbars
   17257      * inside the padding specified by the drawable, you can use
   17258      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
   17259      * appear at the edge of the view, ignoring the padding, then you can use
   17260      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
   17261      * @param style the style of the scrollbars. Should be one of
   17262      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
   17263      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
   17264      * @see #SCROLLBARS_INSIDE_OVERLAY
   17265      * @see #SCROLLBARS_INSIDE_INSET
   17266      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   17267      * @see #SCROLLBARS_OUTSIDE_INSET
   17268      *
   17269      * @attr ref android.R.styleable#View_scrollbarStyle
   17270      */
   17271     public void setScrollBarStyle(@ScrollBarStyle int style) {
   17272         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
   17273             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
   17274             computeOpaqueFlags();
   17275             resolvePadding();
   17276         }
   17277     }
   17278 
   17279     /**
   17280      * <p>Returns the current scrollbar style.</p>
   17281      * @return the current scrollbar style
   17282      * @see #SCROLLBARS_INSIDE_OVERLAY
   17283      * @see #SCROLLBARS_INSIDE_INSET
   17284      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   17285      * @see #SCROLLBARS_OUTSIDE_INSET
   17286      *
   17287      * @attr ref android.R.styleable#View_scrollbarStyle
   17288      */
   17289     @ViewDebug.ExportedProperty(mapping = {
   17290             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
   17291             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
   17292             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
   17293             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
   17294     })
   17295     @ScrollBarStyle
   17296     public int getScrollBarStyle() {
   17297         return mViewFlags & SCROLLBARS_STYLE_MASK;
   17298     }
   17299 
   17300     /**
   17301      * <p>Compute the horizontal range that the horizontal scrollbar
   17302      * represents.</p>
   17303      *
   17304      * <p>The range is expressed in arbitrary units that must be the same as the
   17305      * units used by {@link #computeHorizontalScrollExtent()} and
   17306      * {@link #computeHorizontalScrollOffset()}.</p>
   17307      *
   17308      * <p>The default range is the drawing width of this view.</p>
   17309      *
   17310      * @return the total horizontal range represented by the horizontal
   17311      *         scrollbar
   17312      *
   17313      * @see #computeHorizontalScrollExtent()
   17314      * @see #computeHorizontalScrollOffset()
   17315      * @see android.widget.ScrollBarDrawable
   17316      */
   17317     protected int computeHorizontalScrollRange() {
   17318         return getWidth();
   17319     }
   17320 
   17321     /**
   17322      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
   17323      * within the horizontal range. This value is used to compute the position
   17324      * of the thumb within the scrollbar's track.</p>
   17325      *
   17326      * <p>The range is expressed in arbitrary units that must be the same as the
   17327      * units used by {@link #computeHorizontalScrollRange()} and
   17328      * {@link #computeHorizontalScrollExtent()}.</p>
   17329      *
   17330      * <p>The default offset is the scroll offset of this view.</p>
   17331      *
   17332      * @return the horizontal offset of the scrollbar's thumb
   17333      *
   17334      * @see #computeHorizontalScrollRange()
   17335      * @see #computeHorizontalScrollExtent()
   17336      * @see android.widget.ScrollBarDrawable
   17337      */
   17338     protected int computeHorizontalScrollOffset() {
   17339         return mScrollX;
   17340     }
   17341 
   17342     /**
   17343      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
   17344      * within the horizontal range. This value is used to compute the length
   17345      * of the thumb within the scrollbar's track.</p>
   17346      *
   17347      * <p>The range is expressed in arbitrary units that must be the same as the
   17348      * units used by {@link #computeHorizontalScrollRange()} and
   17349      * {@link #computeHorizontalScrollOffset()}.</p>
   17350      *
   17351      * <p>The default extent is the drawing width of this view.</p>
   17352      *
   17353      * @return the horizontal extent of the scrollbar's thumb
   17354      *
   17355      * @see #computeHorizontalScrollRange()
   17356      * @see #computeHorizontalScrollOffset()
   17357      * @see android.widget.ScrollBarDrawable
   17358      */
   17359     protected int computeHorizontalScrollExtent() {
   17360         return getWidth();
   17361     }
   17362 
   17363     /**
   17364      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
   17365      *
   17366      * <p>The range is expressed in arbitrary units that must be the same as the
   17367      * units used by {@link #computeVerticalScrollExtent()} and
   17368      * {@link #computeVerticalScrollOffset()}.</p>
   17369      *
   17370      * @return the total vertical range represented by the vertical scrollbar
   17371      *
   17372      * <p>The default range is the drawing height of this view.</p>
   17373      *
   17374      * @see #computeVerticalScrollExtent()
   17375      * @see #computeVerticalScrollOffset()
   17376      * @see android.widget.ScrollBarDrawable
   17377      */
   17378     protected int computeVerticalScrollRange() {
   17379         return getHeight();
   17380     }
   17381 
   17382     /**
   17383      * <p>Compute the vertical offset of the vertical scrollbar's thumb
   17384      * within the horizontal range. This value is used to compute the position
   17385      * of the thumb within the scrollbar's track.</p>
   17386      *
   17387      * <p>The range is expressed in arbitrary units that must be the same as the
   17388      * units used by {@link #computeVerticalScrollRange()} and
   17389      * {@link #computeVerticalScrollExtent()}.</p>
   17390      *
   17391      * <p>The default offset is the scroll offset of this view.</p>
   17392      *
   17393      * @return the vertical offset of the scrollbar's thumb
   17394      *
   17395      * @see #computeVerticalScrollRange()
   17396      * @see #computeVerticalScrollExtent()
   17397      * @see android.widget.ScrollBarDrawable
   17398      */
   17399     protected int computeVerticalScrollOffset() {
   17400         return mScrollY;
   17401     }
   17402 
   17403     /**
   17404      * <p>Compute the vertical extent of the vertical scrollbar's thumb
   17405      * within the vertical range. This value is used to compute the length
   17406      * of the thumb within the scrollbar's track.</p>
   17407      *
   17408      * <p>The range is expressed in arbitrary units that must be the same as the
   17409      * units used by {@link #computeVerticalScrollRange()} and
   17410      * {@link #computeVerticalScrollOffset()}.</p>
   17411      *
   17412      * <p>The default extent is the drawing height of this view.</p>
   17413      *
   17414      * @return the vertical extent of the scrollbar's thumb
   17415      *
   17416      * @see #computeVerticalScrollRange()
   17417      * @see #computeVerticalScrollOffset()
   17418      * @see android.widget.ScrollBarDrawable
   17419      */
   17420     protected int computeVerticalScrollExtent() {
   17421         return getHeight();
   17422     }
   17423 
   17424     /**
   17425      * Check if this view can be scrolled horizontally in a certain direction.
   17426      *
   17427      * @param direction Negative to check scrolling left, positive to check scrolling right.
   17428      * @return true if this view can be scrolled in the specified direction, false otherwise.
   17429      */
   17430     public boolean canScrollHorizontally(int direction) {
   17431         final int offset = computeHorizontalScrollOffset();
   17432         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
   17433         if (range == 0) return false;
   17434         if (direction < 0) {
   17435             return offset > 0;
   17436         } else {
   17437             return offset < range - 1;
   17438         }
   17439     }
   17440 
   17441     /**
   17442      * Check if this view can be scrolled vertically in a certain direction.
   17443      *
   17444      * @param direction Negative to check scrolling up, positive to check scrolling down.
   17445      * @return true if this view can be scrolled in the specified direction, false otherwise.
   17446      */
   17447     public boolean canScrollVertically(int direction) {
   17448         final int offset = computeVerticalScrollOffset();
   17449         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
   17450         if (range == 0) return false;
   17451         if (direction < 0) {
   17452             return offset > 0;
   17453         } else {
   17454             return offset < range - 1;
   17455         }
   17456     }
   17457 
   17458     void getScrollIndicatorBounds(@NonNull Rect out) {
   17459         out.left = mScrollX;
   17460         out.right = mScrollX + mRight - mLeft;
   17461         out.top = mScrollY;
   17462         out.bottom = mScrollY + mBottom - mTop;
   17463     }
   17464 
   17465     private void onDrawScrollIndicators(Canvas c) {
   17466         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
   17467             // No scroll indicators enabled.
   17468             return;
   17469         }
   17470 
   17471         final Drawable dr = mScrollIndicatorDrawable;
   17472         if (dr == null) {
   17473             // Scroll indicators aren't supported here.
   17474             return;
   17475         }
   17476 
   17477         final int h = dr.getIntrinsicHeight();
   17478         final int w = dr.getIntrinsicWidth();
   17479         final Rect rect = mAttachInfo.mTmpInvalRect;
   17480         getScrollIndicatorBounds(rect);
   17481 
   17482         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
   17483             final boolean canScrollUp = canScrollVertically(-1);
   17484             if (canScrollUp) {
   17485                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
   17486                 dr.draw(c);
   17487             }
   17488         }
   17489 
   17490         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
   17491             final boolean canScrollDown = canScrollVertically(1);
   17492             if (canScrollDown) {
   17493                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
   17494                 dr.draw(c);
   17495             }
   17496         }
   17497 
   17498         final int leftRtl;
   17499         final int rightRtl;
   17500         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   17501             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
   17502             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
   17503         } else {
   17504             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
   17505             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
   17506         }
   17507 
   17508         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
   17509         if ((mPrivateFlags3 & leftMask) != 0) {
   17510             final boolean canScrollLeft = canScrollHorizontally(-1);
   17511             if (canScrollLeft) {
   17512                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
   17513                 dr.draw(c);
   17514             }
   17515         }
   17516 
   17517         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
   17518         if ((mPrivateFlags3 & rightMask) != 0) {
   17519             final boolean canScrollRight = canScrollHorizontally(1);
   17520             if (canScrollRight) {
   17521                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
   17522                 dr.draw(c);
   17523             }
   17524         }
   17525     }
   17526 
   17527     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
   17528             @Nullable Rect touchBounds) {
   17529         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
   17530         if (bounds == null) {
   17531             return;
   17532         }
   17533         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   17534         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
   17535                 && !isVerticalScrollBarHidden();
   17536         final int size = getHorizontalScrollbarHeight();
   17537         final int verticalScrollBarGap = drawVerticalScrollBar ?
   17538                 getVerticalScrollbarWidth() : 0;
   17539         final int width = mRight - mLeft;
   17540         final int height = mBottom - mTop;
   17541         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
   17542         bounds.left = mScrollX + (mPaddingLeft & inside);
   17543         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
   17544         bounds.bottom = bounds.top + size;
   17545 
   17546         if (touchBounds == null) {
   17547             return;
   17548         }
   17549         if (touchBounds != bounds) {
   17550             touchBounds.set(bounds);
   17551         }
   17552         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
   17553         if (touchBounds.height() < minTouchTarget) {
   17554             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
   17555             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
   17556             touchBounds.top = touchBounds.bottom - minTouchTarget;
   17557         }
   17558         if (touchBounds.width() < minTouchTarget) {
   17559             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
   17560             touchBounds.left -= adjust;
   17561             touchBounds.right = touchBounds.left + minTouchTarget;
   17562         }
   17563     }
   17564 
   17565     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
   17566         if (mRoundScrollbarRenderer == null) {
   17567             getStraightVerticalScrollBarBounds(bounds, touchBounds);
   17568         } else {
   17569             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
   17570         }
   17571     }
   17572 
   17573     private void getRoundVerticalScrollBarBounds(Rect bounds) {
   17574         final int width = mRight - mLeft;
   17575         final int height = mBottom - mTop;
   17576         // Do not take padding into account as we always want the scrollbars
   17577         // to hug the screen for round wearable devices.
   17578         bounds.left = mScrollX;
   17579         bounds.top = mScrollY;
   17580         bounds.right = bounds.left + width;
   17581         bounds.bottom = mScrollY + height;
   17582     }
   17583 
   17584     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
   17585             @Nullable Rect touchBounds) {
   17586         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
   17587         if (bounds == null) {
   17588             return;
   17589         }
   17590         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   17591         final int size = getVerticalScrollbarWidth();
   17592         int verticalScrollbarPosition = mVerticalScrollbarPosition;
   17593         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
   17594             verticalScrollbarPosition = isLayoutRtl() ?
   17595                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
   17596         }
   17597         final int width = mRight - mLeft;
   17598         final int height = mBottom - mTop;
   17599         switch (verticalScrollbarPosition) {
   17600             default:
   17601             case SCROLLBAR_POSITION_RIGHT:
   17602                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
   17603                 break;
   17604             case SCROLLBAR_POSITION_LEFT:
   17605                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
   17606                 break;
   17607         }
   17608         bounds.top = mScrollY + (mPaddingTop & inside);
   17609         bounds.right = bounds.left + size;
   17610         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
   17611 
   17612         if (touchBounds == null) {
   17613             return;
   17614         }
   17615         if (touchBounds != bounds) {
   17616             touchBounds.set(bounds);
   17617         }
   17618         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
   17619         if (touchBounds.width() < minTouchTarget) {
   17620             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
   17621             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
   17622                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
   17623                 touchBounds.left = touchBounds.right - minTouchTarget;
   17624             } else {
   17625                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
   17626                 touchBounds.right = touchBounds.left + minTouchTarget;
   17627             }
   17628         }
   17629         if (touchBounds.height() < minTouchTarget) {
   17630             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
   17631             touchBounds.top -= adjust;
   17632             touchBounds.bottom = touchBounds.top + minTouchTarget;
   17633         }
   17634     }
   17635 
   17636     /**
   17637      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
   17638      * scrollbars are painted only if they have been awakened first.</p>
   17639      *
   17640      * @param canvas the canvas on which to draw the scrollbars
   17641      *
   17642      * @see #awakenScrollBars(int)
   17643      */
   17644     protected final void onDrawScrollBars(Canvas canvas) {
   17645         // scrollbars are drawn only when the animation is running
   17646         final ScrollabilityCache cache = mScrollCache;
   17647 
   17648         if (cache != null) {
   17649 
   17650             int state = cache.state;
   17651 
   17652             if (state == ScrollabilityCache.OFF) {
   17653                 return;
   17654             }
   17655 
   17656             boolean invalidate = false;
   17657 
   17658             if (state == ScrollabilityCache.FADING) {
   17659                 // We're fading -- get our fade interpolation
   17660                 if (cache.interpolatorValues == null) {
   17661                     cache.interpolatorValues = new float[1];
   17662                 }
   17663 
   17664                 float[] values = cache.interpolatorValues;
   17665 
   17666                 // Stops the animation if we're done
   17667                 if (cache.scrollBarInterpolator.timeToValues(values) ==
   17668                         Interpolator.Result.FREEZE_END) {
   17669                     cache.state = ScrollabilityCache.OFF;
   17670                 } else {
   17671                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
   17672                 }
   17673 
   17674                 // This will make the scroll bars inval themselves after
   17675                 // drawing. We only want this when we're fading so that
   17676                 // we prevent excessive redraws
   17677                 invalidate = true;
   17678             } else {
   17679                 // We're just on -- but we may have been fading before so
   17680                 // reset alpha
   17681                 cache.scrollBar.mutate().setAlpha(255);
   17682             }
   17683 
   17684             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
   17685             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
   17686                     && !isVerticalScrollBarHidden();
   17687 
   17688             // Fork out the scroll bar drawing for round wearable devices.
   17689             if (mRoundScrollbarRenderer != null) {
   17690                 if (drawVerticalScrollBar) {
   17691                     final Rect bounds = cache.mScrollBarBounds;
   17692                     getVerticalScrollBarBounds(bounds, null);
   17693                     mRoundScrollbarRenderer.drawRoundScrollbars(
   17694                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
   17695                     if (invalidate) {
   17696                         invalidate();
   17697                     }
   17698                 }
   17699                 // Do not draw horizontal scroll bars for round wearable devices.
   17700             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
   17701                 final ScrollBarDrawable scrollBar = cache.scrollBar;
   17702 
   17703                 if (drawHorizontalScrollBar) {
   17704                     scrollBar.setParameters(computeHorizontalScrollRange(),
   17705                             computeHorizontalScrollOffset(),
   17706                             computeHorizontalScrollExtent(), false);
   17707                     final Rect bounds = cache.mScrollBarBounds;
   17708                     getHorizontalScrollBarBounds(bounds, null);
   17709                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
   17710                             bounds.right, bounds.bottom);
   17711                     if (invalidate) {
   17712                         invalidate(bounds);
   17713                     }
   17714                 }
   17715 
   17716                 if (drawVerticalScrollBar) {
   17717                     scrollBar.setParameters(computeVerticalScrollRange(),
   17718                             computeVerticalScrollOffset(),
   17719                             computeVerticalScrollExtent(), true);
   17720                     final Rect bounds = cache.mScrollBarBounds;
   17721                     getVerticalScrollBarBounds(bounds, null);
   17722                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
   17723                             bounds.right, bounds.bottom);
   17724                     if (invalidate) {
   17725                         invalidate(bounds);
   17726                     }
   17727                 }
   17728             }
   17729         }
   17730     }
   17731 
   17732     /**
   17733      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
   17734      * FastScroller is visible.
   17735      * @return whether to temporarily hide the vertical scrollbar
   17736      * @hide
   17737      */
   17738     protected boolean isVerticalScrollBarHidden() {
   17739         return false;
   17740     }
   17741 
   17742     /**
   17743      * <p>Draw the horizontal scrollbar if
   17744      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
   17745      *
   17746      * @param canvas the canvas on which to draw the scrollbar
   17747      * @param scrollBar the scrollbar's drawable
   17748      *
   17749      * @see #isHorizontalScrollBarEnabled()
   17750      * @see #computeHorizontalScrollRange()
   17751      * @see #computeHorizontalScrollExtent()
   17752      * @see #computeHorizontalScrollOffset()
   17753      * @see android.widget.ScrollBarDrawable
   17754      * @hide
   17755      */
   17756     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
   17757             int l, int t, int r, int b) {
   17758         scrollBar.setBounds(l, t, r, b);
   17759         scrollBar.draw(canvas);
   17760     }
   17761 
   17762     /**
   17763      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
   17764      * returns true.</p>
   17765      *
   17766      * @param canvas the canvas on which to draw the scrollbar
   17767      * @param scrollBar the scrollbar's drawable
   17768      *
   17769      * @see #isVerticalScrollBarEnabled()
   17770      * @see #computeVerticalScrollRange()
   17771      * @see #computeVerticalScrollExtent()
   17772      * @see #computeVerticalScrollOffset()
   17773      * @see android.widget.ScrollBarDrawable
   17774      * @hide
   17775      */
   17776     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
   17777             int l, int t, int r, int b) {
   17778         scrollBar.setBounds(l, t, r, b);
   17779         scrollBar.draw(canvas);
   17780     }
   17781 
   17782     /**
   17783      * Implement this to do your drawing.
   17784      *
   17785      * @param canvas the canvas on which the background will be drawn
   17786      */
   17787     protected void onDraw(Canvas canvas) {
   17788     }
   17789 
   17790     /*
   17791      * Caller is responsible for calling requestLayout if necessary.
   17792      * (This allows addViewInLayout to not request a new layout.)
   17793      */
   17794     void assignParent(ViewParent parent) {
   17795         if (mParent == null) {
   17796             mParent = parent;
   17797         } else if (parent == null) {
   17798             mParent = null;
   17799         } else {
   17800             throw new RuntimeException("view " + this + " being added, but"
   17801                     + " it already has a parent");
   17802         }
   17803     }
   17804 
   17805     /**
   17806      * This is called when the view is attached to a window.  At this point it
   17807      * has a Surface and will start drawing.  Note that this function is
   17808      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
   17809      * however it may be called any time before the first onDraw -- including
   17810      * before or after {@link #onMeasure(int, int)}.
   17811      *
   17812      * @see #onDetachedFromWindow()
   17813      */
   17814     @CallSuper
   17815     protected void onAttachedToWindow() {
   17816         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
   17817             mParent.requestTransparentRegion(this);
   17818         }
   17819 
   17820         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   17821 
   17822         jumpDrawablesToCurrentState();
   17823 
   17824         resetSubtreeAccessibilityStateChanged();
   17825 
   17826         // rebuild, since Outline not maintained while View is detached
   17827         rebuildOutline();
   17828 
   17829         if (isFocused()) {
   17830             InputMethodManager imm = InputMethodManager.peekInstance();
   17831             if (imm != null) {
   17832                 imm.focusIn(this);
   17833             }
   17834         }
   17835     }
   17836 
   17837     /**
   17838      * Resolve all RTL related properties.
   17839      *
   17840      * @return true if resolution of RTL properties has been done
   17841      *
   17842      * @hide
   17843      */
   17844     public boolean resolveRtlPropertiesIfNeeded() {
   17845         if (!needRtlPropertiesResolution()) return false;
   17846 
   17847         // Order is important here: LayoutDirection MUST be resolved first
   17848         if (!isLayoutDirectionResolved()) {
   17849             resolveLayoutDirection();
   17850             resolveLayoutParams();
   17851         }
   17852         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
   17853         if (!isTextDirectionResolved()) {
   17854             resolveTextDirection();
   17855         }
   17856         if (!isTextAlignmentResolved()) {
   17857             resolveTextAlignment();
   17858         }
   17859         // Should resolve Drawables before Padding because we need the layout direction of the
   17860         // Drawable to correctly resolve Padding.
   17861         if (!areDrawablesResolved()) {
   17862             resolveDrawables();
   17863         }
   17864         if (!isPaddingResolved()) {
   17865             resolvePadding();
   17866         }
   17867         onRtlPropertiesChanged(getLayoutDirection());
   17868         return true;
   17869     }
   17870 
   17871     /**
   17872      * Reset resolution of all RTL related properties.
   17873      *
   17874      * @hide
   17875      */
   17876     public void resetRtlProperties() {
   17877         resetResolvedLayoutDirection();
   17878         resetResolvedTextDirection();
   17879         resetResolvedTextAlignment();
   17880         resetResolvedPadding();
   17881         resetResolvedDrawables();
   17882     }
   17883 
   17884     /**
   17885      * @see #onScreenStateChanged(int)
   17886      */
   17887     void dispatchScreenStateChanged(int screenState) {
   17888         onScreenStateChanged(screenState);
   17889     }
   17890 
   17891     /**
   17892      * This method is called whenever the state of the screen this view is
   17893      * attached to changes. A state change will usually occurs when the screen
   17894      * turns on or off (whether it happens automatically or the user does it
   17895      * manually.)
   17896      *
   17897      * @param screenState The new state of the screen. Can be either
   17898      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
   17899      */
   17900     public void onScreenStateChanged(int screenState) {
   17901     }
   17902 
   17903     /**
   17904      * @see #onMovedToDisplay(int, Configuration)
   17905      */
   17906     void dispatchMovedToDisplay(Display display, Configuration config) {
   17907         mAttachInfo.mDisplay = display;
   17908         mAttachInfo.mDisplayState = display.getState();
   17909         onMovedToDisplay(display.getDisplayId(), config);
   17910     }
   17911 
   17912     /**
   17913      * Called by the system when the hosting activity is moved from one display to another without
   17914      * recreation. This means that the activity is declared to handle all changes to configuration
   17915      * that happened when it was switched to another display, so it wasn't destroyed and created
   17916      * again.
   17917      *
   17918      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
   17919      * applied configuration actually changed. It is up to app developer to choose whether to handle
   17920      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
   17921      * call.
   17922      *
   17923      * <p>Use this callback to track changes to the displays if some functionality relies on an
   17924      * association with some display properties.
   17925      *
   17926      * @param displayId The id of the display to which the view was moved.
   17927      * @param config Configuration of the resources on new display after move.
   17928      *
   17929      * @see #onConfigurationChanged(Configuration)
   17930      * @hide
   17931      */
   17932     public void onMovedToDisplay(int displayId, Configuration config) {
   17933     }
   17934 
   17935     /**
   17936      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
   17937      */
   17938     private boolean hasRtlSupport() {
   17939         return mContext.getApplicationInfo().hasRtlSupport();
   17940     }
   17941 
   17942     /**
   17943      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
   17944      * RTL not supported)
   17945      */
   17946     private boolean isRtlCompatibilityMode() {
   17947         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   17948         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
   17949     }
   17950 
   17951     /**
   17952      * @return true if RTL properties need resolution.
   17953      *
   17954      */
   17955     private boolean needRtlPropertiesResolution() {
   17956         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
   17957     }
   17958 
   17959     /**
   17960      * Called when any RTL property (layout direction or text direction or text alignment) has
   17961      * been changed.
   17962      *
   17963      * Subclasses need to override this method to take care of cached information that depends on the
   17964      * resolved layout direction, or to inform child views that inherit their layout direction.
   17965      *
   17966      * The default implementation does nothing.
   17967      *
   17968      * @param layoutDirection the direction of the layout
   17969      *
   17970      * @see #LAYOUT_DIRECTION_LTR
   17971      * @see #LAYOUT_DIRECTION_RTL
   17972      */
   17973     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
   17974     }
   17975 
   17976     /**
   17977      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
   17978      * that the parent directionality can and will be resolved before its children.
   17979      *
   17980      * @return true if resolution has been done, false otherwise.
   17981      *
   17982      * @hide
   17983      */
   17984     public boolean resolveLayoutDirection() {
   17985         // Clear any previous layout direction resolution
   17986         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   17987 
   17988         if (hasRtlSupport()) {
   17989             // Set resolved depending on layout direction
   17990             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
   17991                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
   17992                 case LAYOUT_DIRECTION_INHERIT:
   17993                     // We cannot resolve yet. LTR is by default and let the resolution happen again
   17994                     // later to get the correct resolved value
   17995                     if (!canResolveLayoutDirection()) return false;
   17996 
   17997                     // Parent has not yet resolved, LTR is still the default
   17998                     try {
   17999                         if (!mParent.isLayoutDirectionResolved()) return false;
   18000 
   18001                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   18002                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   18003                         }
   18004                     } catch (AbstractMethodError e) {
   18005                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   18006                                 " does not fully implement ViewParent", e);
   18007                     }
   18008                     break;
   18009                 case LAYOUT_DIRECTION_RTL:
   18010                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   18011                     break;
   18012                 case LAYOUT_DIRECTION_LOCALE:
   18013                     if((LAYOUT_DIRECTION_RTL ==
   18014                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
   18015                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   18016                     }
   18017                     break;
   18018                 default:
   18019                     // Nothing to do, LTR by default
   18020             }
   18021         }
   18022 
   18023         // Set to resolved
   18024         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   18025         return true;
   18026     }
   18027 
   18028     /**
   18029      * Check if layout direction resolution can be done.
   18030      *
   18031      * @return true if layout direction resolution can be done otherwise return false.
   18032      */
   18033     public boolean canResolveLayoutDirection() {
   18034         switch (getRawLayoutDirection()) {
   18035             case LAYOUT_DIRECTION_INHERIT:
   18036                 if (mParent != null) {
   18037                     try {
   18038                         return mParent.canResolveLayoutDirection();
   18039                     } catch (AbstractMethodError e) {
   18040                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   18041                                 " does not fully implement ViewParent", e);
   18042                     }
   18043                 }
   18044                 return false;
   18045 
   18046             default:
   18047                 return true;
   18048         }
   18049     }
   18050 
   18051     /**
   18052      * Reset the resolved layout direction. Layout direction will be resolved during a call to
   18053      * {@link #onMeasure(int, int)}.
   18054      *
   18055      * @hide
   18056      */
   18057     public void resetResolvedLayoutDirection() {
   18058         // Reset the current resolved bits
   18059         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   18060     }
   18061 
   18062     /**
   18063      * @return true if the layout direction is inherited.
   18064      *
   18065      * @hide
   18066      */
   18067     public boolean isLayoutDirectionInherited() {
   18068         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
   18069     }
   18070 
   18071     /**
   18072      * @return true if layout direction has been resolved.
   18073      */
   18074     public boolean isLayoutDirectionResolved() {
   18075         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   18076     }
   18077 
   18078     /**
   18079      * Return if padding has been resolved
   18080      *
   18081      * @hide
   18082      */
   18083     boolean isPaddingResolved() {
   18084         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
   18085     }
   18086 
   18087     /**
   18088      * Resolves padding depending on layout direction, if applicable, and
   18089      * recomputes internal padding values to adjust for scroll bars.
   18090      *
   18091      * @hide
   18092      */
   18093     public void resolvePadding() {
   18094         final int resolvedLayoutDirection = getLayoutDirection();
   18095 
   18096         if (!isRtlCompatibilityMode()) {
   18097             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
   18098             // If start / end padding are defined, they will be resolved (hence overriding) to
   18099             // left / right or right / left depending on the resolved layout direction.
   18100             // If start / end padding are not defined, use the left / right ones.
   18101             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
   18102                 Rect padding = sThreadLocal.get();
   18103                 if (padding == null) {
   18104                     padding = new Rect();
   18105                     sThreadLocal.set(padding);
   18106                 }
   18107                 mBackground.getPadding(padding);
   18108                 if (!mLeftPaddingDefined) {
   18109                     mUserPaddingLeftInitial = padding.left;
   18110                 }
   18111                 if (!mRightPaddingDefined) {
   18112                     mUserPaddingRightInitial = padding.right;
   18113                 }
   18114             }
   18115             switch (resolvedLayoutDirection) {
   18116                 case LAYOUT_DIRECTION_RTL:
   18117                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   18118                         mUserPaddingRight = mUserPaddingStart;
   18119                     } else {
   18120                         mUserPaddingRight = mUserPaddingRightInitial;
   18121                     }
   18122                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   18123                         mUserPaddingLeft = mUserPaddingEnd;
   18124                     } else {
   18125                         mUserPaddingLeft = mUserPaddingLeftInitial;
   18126                     }
   18127                     break;
   18128                 case LAYOUT_DIRECTION_LTR:
   18129                 default:
   18130                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   18131                         mUserPaddingLeft = mUserPaddingStart;
   18132                     } else {
   18133                         mUserPaddingLeft = mUserPaddingLeftInitial;
   18134                     }
   18135                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   18136                         mUserPaddingRight = mUserPaddingEnd;
   18137                     } else {
   18138                         mUserPaddingRight = mUserPaddingRightInitial;
   18139                     }
   18140             }
   18141 
   18142             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
   18143         }
   18144 
   18145         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   18146         onRtlPropertiesChanged(resolvedLayoutDirection);
   18147 
   18148         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
   18149     }
   18150 
   18151     /**
   18152      * Reset the resolved layout direction.
   18153      *
   18154      * @hide
   18155      */
   18156     public void resetResolvedPadding() {
   18157         resetResolvedPaddingInternal();
   18158     }
   18159 
   18160     /**
   18161      * Used when we only want to reset *this* view's padding and not trigger overrides
   18162      * in ViewGroup that reset children too.
   18163      */
   18164     void resetResolvedPaddingInternal() {
   18165         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
   18166     }
   18167 
   18168     /**
   18169      * This is called when the view is detached from a window.  At this point it
   18170      * no longer has a surface for drawing.
   18171      *
   18172      * @see #onAttachedToWindow()
   18173      */
   18174     @CallSuper
   18175     protected void onDetachedFromWindow() {
   18176     }
   18177 
   18178     /**
   18179      * This is a framework-internal mirror of onDetachedFromWindow() that's called
   18180      * after onDetachedFromWindow().
   18181      *
   18182      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
   18183      * The super method should be called at the end of the overridden method to ensure
   18184      * subclasses are destroyed first
   18185      *
   18186      * @hide
   18187      */
   18188     @CallSuper
   18189     protected void onDetachedFromWindowInternal() {
   18190         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
   18191         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   18192         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
   18193 
   18194         removeUnsetPressCallback();
   18195         removeLongPressCallback();
   18196         removePerformClickCallback();
   18197         cancel(mSendViewScrolledAccessibilityEvent);
   18198         stopNestedScroll();
   18199 
   18200         // Anything that started animating right before detach should already
   18201         // be in its final state when re-attached.
   18202         jumpDrawablesToCurrentState();
   18203 
   18204         destroyDrawingCache();
   18205 
   18206         cleanupDraw();
   18207         mCurrentAnimation = null;
   18208 
   18209         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
   18210             hideTooltip();
   18211         }
   18212     }
   18213 
   18214     private void cleanupDraw() {
   18215         resetDisplayList();
   18216         if (mAttachInfo != null) {
   18217             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
   18218         }
   18219     }
   18220 
   18221     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
   18222     }
   18223 
   18224     /**
   18225      * @return The number of times this view has been attached to a window
   18226      */
   18227     protected int getWindowAttachCount() {
   18228         return mWindowAttachCount;
   18229     }
   18230 
   18231     /**
   18232      * Retrieve a unique token identifying the window this view is attached to.
   18233      * @return Return the window's token for use in
   18234      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
   18235      */
   18236     public IBinder getWindowToken() {
   18237         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
   18238     }
   18239 
   18240     /**
   18241      * Retrieve the {@link WindowId} for the window this view is
   18242      * currently attached to.
   18243      */
   18244     public WindowId getWindowId() {
   18245         AttachInfo ai = mAttachInfo;
   18246         if (ai == null) {
   18247             return null;
   18248         }
   18249         if (ai.mWindowId == null) {
   18250             try {
   18251                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
   18252                 if (ai.mIWindowId != null) {
   18253                     ai.mWindowId = new WindowId(ai.mIWindowId);
   18254                 }
   18255             } catch (RemoteException e) {
   18256             }
   18257         }
   18258         return ai.mWindowId;
   18259     }
   18260 
   18261     /**
   18262      * Retrieve a unique token identifying the top-level "real" window of
   18263      * the window that this view is attached to.  That is, this is like
   18264      * {@link #getWindowToken}, except if the window this view in is a panel
   18265      * window (attached to another containing window), then the token of
   18266      * the containing window is returned instead.
   18267      *
   18268      * @return Returns the associated window token, either
   18269      * {@link #getWindowToken()} or the containing window's token.
   18270      */
   18271     public IBinder getApplicationWindowToken() {
   18272         AttachInfo ai = mAttachInfo;
   18273         if (ai != null) {
   18274             IBinder appWindowToken = ai.mPanelParentWindowToken;
   18275             if (appWindowToken == null) {
   18276                 appWindowToken = ai.mWindowToken;
   18277             }
   18278             return appWindowToken;
   18279         }
   18280         return null;
   18281     }
   18282 
   18283     /**
   18284      * Gets the logical display to which the view's window has been attached.
   18285      *
   18286      * @return The logical display, or null if the view is not currently attached to a window.
   18287      */
   18288     public Display getDisplay() {
   18289         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
   18290     }
   18291 
   18292     /**
   18293      * Retrieve private session object this view hierarchy is using to
   18294      * communicate with the window manager.
   18295      * @return the session object to communicate with the window manager
   18296      */
   18297     /*package*/ IWindowSession getWindowSession() {
   18298         return mAttachInfo != null ? mAttachInfo.mSession : null;
   18299     }
   18300 
   18301     /**
   18302      * Return the window this view is currently attached to. Used in
   18303      * {@link android.app.ActivityView} to communicate with WM.
   18304      * @hide
   18305      */
   18306     protected IWindow getWindow() {
   18307         return mAttachInfo != null ? mAttachInfo.mWindow : null;
   18308     }
   18309 
   18310     /**
   18311      * Return the visibility value of the least visible component passed.
   18312      */
   18313     int combineVisibility(int vis1, int vis2) {
   18314         // This works because VISIBLE < INVISIBLE < GONE.
   18315         return Math.max(vis1, vis2);
   18316     }
   18317 
   18318     /**
   18319      * @param info the {@link android.view.View.AttachInfo} to associated with
   18320      *        this view
   18321      */
   18322     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
   18323         mAttachInfo = info;
   18324         if (mOverlay != null) {
   18325             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
   18326         }
   18327         mWindowAttachCount++;
   18328         // We will need to evaluate the drawable state at least once.
   18329         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   18330         if (mFloatingTreeObserver != null) {
   18331             info.mTreeObserver.merge(mFloatingTreeObserver);
   18332             mFloatingTreeObserver = null;
   18333         }
   18334 
   18335         registerPendingFrameMetricsObservers();
   18336 
   18337         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
   18338             mAttachInfo.mScrollContainers.add(this);
   18339             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   18340         }
   18341         // Transfer all pending runnables.
   18342         if (mRunQueue != null) {
   18343             mRunQueue.executeActions(info.mHandler);
   18344             mRunQueue = null;
   18345         }
   18346         performCollectViewAttributes(mAttachInfo, visibility);
   18347         onAttachedToWindow();
   18348 
   18349         ListenerInfo li = mListenerInfo;
   18350         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   18351                 li != null ? li.mOnAttachStateChangeListeners : null;
   18352         if (listeners != null && listeners.size() > 0) {
   18353             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   18354             // perform the dispatching. The iterator is a safe guard against listeners that
   18355             // could mutate the list by calling the various add/remove methods. This prevents
   18356             // the array from being modified while we iterate it.
   18357             for (OnAttachStateChangeListener listener : listeners) {
   18358                 listener.onViewAttachedToWindow(this);
   18359             }
   18360         }
   18361 
   18362         int vis = info.mWindowVisibility;
   18363         if (vis != GONE) {
   18364             onWindowVisibilityChanged(vis);
   18365             if (isShown()) {
   18366                 // Calling onVisibilityAggregated directly here since the subtree will also
   18367                 // receive dispatchAttachedToWindow and this same call
   18368                 onVisibilityAggregated(vis == VISIBLE);
   18369             }
   18370         }
   18371 
   18372         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
   18373         // As all views in the subtree will already receive dispatchAttachedToWindow
   18374         // traversing the subtree again here is not desired.
   18375         onVisibilityChanged(this, visibility);
   18376 
   18377         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
   18378             // If nobody has evaluated the drawable state yet, then do it now.
   18379             refreshDrawableState();
   18380         }
   18381         needGlobalAttributesUpdate(false);
   18382 
   18383         notifyEnterOrExitForAutoFillIfNeeded(true);
   18384     }
   18385 
   18386     void dispatchDetachedFromWindow() {
   18387         AttachInfo info = mAttachInfo;
   18388         if (info != null) {
   18389             int vis = info.mWindowVisibility;
   18390             if (vis != GONE) {
   18391                 onWindowVisibilityChanged(GONE);
   18392                 if (isShown()) {
   18393                     // Invoking onVisibilityAggregated directly here since the subtree
   18394                     // will also receive detached from window
   18395                     onVisibilityAggregated(false);
   18396                 }
   18397             }
   18398         }
   18399 
   18400         onDetachedFromWindow();
   18401         onDetachedFromWindowInternal();
   18402 
   18403         InputMethodManager imm = InputMethodManager.peekInstance();
   18404         if (imm != null) {
   18405             imm.onViewDetachedFromWindow(this);
   18406         }
   18407 
   18408         ListenerInfo li = mListenerInfo;
   18409         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   18410                 li != null ? li.mOnAttachStateChangeListeners : null;
   18411         if (listeners != null && listeners.size() > 0) {
   18412             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   18413             // perform the dispatching. The iterator is a safe guard against listeners that
   18414             // could mutate the list by calling the various add/remove methods. This prevents
   18415             // the array from being modified while we iterate it.
   18416             for (OnAttachStateChangeListener listener : listeners) {
   18417                 listener.onViewDetachedFromWindow(this);
   18418             }
   18419         }
   18420 
   18421         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   18422             mAttachInfo.mScrollContainers.remove(this);
   18423             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
   18424         }
   18425 
   18426         mAttachInfo = null;
   18427         if (mOverlay != null) {
   18428             mOverlay.getOverlayView().dispatchDetachedFromWindow();
   18429         }
   18430 
   18431         notifyEnterOrExitForAutoFillIfNeeded(false);
   18432     }
   18433 
   18434     /**
   18435      * Cancel any deferred high-level input events that were previously posted to the event queue.
   18436      *
   18437      * <p>Many views post high-level events such as click handlers to the event queue
   18438      * to run deferred in order to preserve a desired user experience - clearing visible
   18439      * pressed states before executing, etc. This method will abort any events of this nature
   18440      * that are currently in flight.</p>
   18441      *
   18442      * <p>Custom views that generate their own high-level deferred input events should override
   18443      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
   18444      *
   18445      * <p>This will also cancel pending input events for any child views.</p>
   18446      *
   18447      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
   18448      * This will not impact newer events posted after this call that may occur as a result of
   18449      * lower-level input events still waiting in the queue. If you are trying to prevent
   18450      * double-submitted  events for the duration of some sort of asynchronous transaction
   18451      * you should also take other steps to protect against unexpected double inputs e.g. calling
   18452      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
   18453      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
   18454      */
   18455     public final void cancelPendingInputEvents() {
   18456         dispatchCancelPendingInputEvents();
   18457     }
   18458 
   18459     /**
   18460      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
   18461      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
   18462      */
   18463     void dispatchCancelPendingInputEvents() {
   18464         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
   18465         onCancelPendingInputEvents();
   18466         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
   18467             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
   18468                     " did not call through to super.onCancelPendingInputEvents()");
   18469         }
   18470     }
   18471 
   18472     /**
   18473      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
   18474      * a parent view.
   18475      *
   18476      * <p>This method is responsible for removing any pending high-level input events that were
   18477      * posted to the event queue to run later. Custom view classes that post their own deferred
   18478      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
   18479      * {@link android.os.Handler} should override this method, call
   18480      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
   18481      * </p>
   18482      */
   18483     public void onCancelPendingInputEvents() {
   18484         removePerformClickCallback();
   18485         cancelLongPress();
   18486         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
   18487     }
   18488 
   18489     /**
   18490      * Store this view hierarchy's frozen state into the given container.
   18491      *
   18492      * @param container The SparseArray in which to save the view's state.
   18493      *
   18494      * @see #restoreHierarchyState(android.util.SparseArray)
   18495      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   18496      * @see #onSaveInstanceState()
   18497      */
   18498     public void saveHierarchyState(SparseArray<Parcelable> container) {
   18499         dispatchSaveInstanceState(container);
   18500     }
   18501 
   18502     /**
   18503      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
   18504      * this view and its children. May be overridden to modify how freezing happens to a
   18505      * view's children; for example, some views may want to not store state for their children.
   18506      *
   18507      * @param container The SparseArray in which to save the view's state.
   18508      *
   18509      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   18510      * @see #saveHierarchyState(android.util.SparseArray)
   18511      * @see #onSaveInstanceState()
   18512      */
   18513     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
   18514         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
   18515             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   18516             Parcelable state = onSaveInstanceState();
   18517             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   18518                 throw new IllegalStateException(
   18519                         "Derived class did not call super.onSaveInstanceState()");
   18520             }
   18521             if (state != null) {
   18522                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
   18523                 // + ": " + state);
   18524                 container.put(mID, state);
   18525             }
   18526         }
   18527     }
   18528 
   18529     /**
   18530      * Hook allowing a view to generate a representation of its internal state
   18531      * that can later be used to create a new instance with that same state.
   18532      * This state should only contain information that is not persistent or can
   18533      * not be reconstructed later. For example, you will never store your
   18534      * current position on screen because that will be computed again when a
   18535      * new instance of the view is placed in its view hierarchy.
   18536      * <p>
   18537      * Some examples of things you may store here: the current cursor position
   18538      * in a text view (but usually not the text itself since that is stored in a
   18539      * content provider or other persistent storage), the currently selected
   18540      * item in a list view.
   18541      *
   18542      * @return Returns a Parcelable object containing the view's current dynamic
   18543      *         state, or null if there is nothing interesting to save.
   18544      * @see #onRestoreInstanceState(Parcelable)
   18545      * @see #saveHierarchyState(SparseArray)
   18546      * @see #dispatchSaveInstanceState(SparseArray)
   18547      * @see #setSaveEnabled(boolean)
   18548      */
   18549     @CallSuper
   18550     @Nullable protected Parcelable onSaveInstanceState() {
   18551         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   18552         if (mStartActivityRequestWho != null || isAutofilled()
   18553                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
   18554             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
   18555 
   18556             if (mStartActivityRequestWho != null) {
   18557                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
   18558             }
   18559 
   18560             if (isAutofilled()) {
   18561                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
   18562             }
   18563 
   18564             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
   18565                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
   18566             }
   18567 
   18568             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
   18569             state.mIsAutofilled = isAutofilled();
   18570             state.mAutofillViewId = mAutofillViewId;
   18571             return state;
   18572         }
   18573         return BaseSavedState.EMPTY_STATE;
   18574     }
   18575 
   18576     /**
   18577      * Restore this view hierarchy's frozen state from the given container.
   18578      *
   18579      * @param container The SparseArray which holds previously frozen states.
   18580      *
   18581      * @see #saveHierarchyState(android.util.SparseArray)
   18582      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   18583      * @see #onRestoreInstanceState(android.os.Parcelable)
   18584      */
   18585     public void restoreHierarchyState(SparseArray<Parcelable> container) {
   18586         dispatchRestoreInstanceState(container);
   18587     }
   18588 
   18589     /**
   18590      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
   18591      * state for this view and its children. May be overridden to modify how restoring
   18592      * happens to a view's children; for example, some views may want to not store state
   18593      * for their children.
   18594      *
   18595      * @param container The SparseArray which holds previously saved state.
   18596      *
   18597      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   18598      * @see #restoreHierarchyState(android.util.SparseArray)
   18599      * @see #onRestoreInstanceState(android.os.Parcelable)
   18600      */
   18601     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
   18602         if (mID != NO_ID) {
   18603             Parcelable state = container.get(mID);
   18604             if (state != null) {
   18605                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
   18606                 // + ": " + state);
   18607                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   18608                 onRestoreInstanceState(state);
   18609                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   18610                     throw new IllegalStateException(
   18611                             "Derived class did not call super.onRestoreInstanceState()");
   18612                 }
   18613             }
   18614         }
   18615     }
   18616 
   18617     /**
   18618      * Hook allowing a view to re-apply a representation of its internal state that had previously
   18619      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
   18620      * null state.
   18621      *
   18622      * @param state The frozen state that had previously been returned by
   18623      *        {@link #onSaveInstanceState}.
   18624      *
   18625      * @see #onSaveInstanceState()
   18626      * @see #restoreHierarchyState(android.util.SparseArray)
   18627      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   18628      */
   18629     @CallSuper
   18630     protected void onRestoreInstanceState(Parcelable state) {
   18631         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   18632         if (state != null && !(state instanceof AbsSavedState)) {
   18633             throw new IllegalArgumentException("Wrong state class, expecting View State but "
   18634                     + "received " + state.getClass().toString() + " instead. This usually happens "
   18635                     + "when two views of different type have the same id in the same hierarchy. "
   18636                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
   18637                     + "other views do not use the same id.");
   18638         }
   18639         if (state != null && state instanceof BaseSavedState) {
   18640             BaseSavedState baseState = (BaseSavedState) state;
   18641 
   18642             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
   18643                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
   18644             }
   18645             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
   18646                 setAutofilled(baseState.mIsAutofilled);
   18647             }
   18648             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
   18649                 // It can happen that views have the same view id and the restoration path will not
   18650                 // be able to distinguish between them. The autofill id needs to be unique though.
   18651                 // Hence prevent the same autofill view id from being restored multiple times.
   18652                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
   18653 
   18654                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
   18655                     // Ignore when view already set it through setAutofillId();
   18656                     if (android.view.autofill.Helper.sDebug) {
   18657                         Log.d(VIEW_LOG_TAG, "onRestoreInstanceState(): not setting autofillId to "
   18658                                 + baseState.mAutofillViewId + " because view explicitly set it to "
   18659                                 + mAutofillId);
   18660                     }
   18661                 } else {
   18662                     mAutofillViewId = baseState.mAutofillViewId;
   18663                     mAutofillId = null; // will be set on demand by getAutofillId()
   18664                 }
   18665             }
   18666         }
   18667     }
   18668 
   18669     /**
   18670      * <p>Return the time at which the drawing of the view hierarchy started.</p>
   18671      *
   18672      * @return the drawing start time in milliseconds
   18673      */
   18674     public long getDrawingTime() {
   18675         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
   18676     }
   18677 
   18678     /**
   18679      * <p>Enables or disables the duplication of the parent's state into this view. When
   18680      * duplication is enabled, this view gets its drawable state from its parent rather
   18681      * than from its own internal properties.</p>
   18682      *
   18683      * <p>Note: in the current implementation, setting this property to true after the
   18684      * view was added to a ViewGroup might have no effect at all. This property should
   18685      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
   18686      *
   18687      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
   18688      * property is enabled, an exception will be thrown.</p>
   18689      *
   18690      * <p>Note: if the child view uses and updates additional states which are unknown to the
   18691      * parent, these states should not be affected by this method.</p>
   18692      *
   18693      * @param enabled True to enable duplication of the parent's drawable state, false
   18694      *                to disable it.
   18695      *
   18696      * @see #getDrawableState()
   18697      * @see #isDuplicateParentStateEnabled()
   18698      */
   18699     public void setDuplicateParentStateEnabled(boolean enabled) {
   18700         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
   18701     }
   18702 
   18703     /**
   18704      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
   18705      *
   18706      * @return True if this view's drawable state is duplicated from the parent,
   18707      *         false otherwise
   18708      *
   18709      * @see #getDrawableState()
   18710      * @see #setDuplicateParentStateEnabled(boolean)
   18711      */
   18712     public boolean isDuplicateParentStateEnabled() {
   18713         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
   18714     }
   18715 
   18716     /**
   18717      * <p>Specifies the type of layer backing this view. The layer can be
   18718      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   18719      * {@link #LAYER_TYPE_HARDWARE}.</p>
   18720      *
   18721      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   18722      * instance that controls how the layer is composed on screen. The following
   18723      * properties of the paint are taken into account when composing the layer:</p>
   18724      * <ul>
   18725      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   18726      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   18727      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   18728      * </ul>
   18729      *
   18730      * <p>If this view has an alpha value set to < 1.0 by calling
   18731      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
   18732      * by this view's alpha value.</p>
   18733      *
   18734      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
   18735      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
   18736      * for more information on when and how to use layers.</p>
   18737      *
   18738      * @param layerType The type of layer to use with this view, must be one of
   18739      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   18740      *        {@link #LAYER_TYPE_HARDWARE}
   18741      * @param paint The paint used to compose the layer. This argument is optional
   18742      *        and can be null. It is ignored when the layer type is
   18743      *        {@link #LAYER_TYPE_NONE}
   18744      *
   18745      * @see #getLayerType()
   18746      * @see #LAYER_TYPE_NONE
   18747      * @see #LAYER_TYPE_SOFTWARE
   18748      * @see #LAYER_TYPE_HARDWARE
   18749      * @see #setAlpha(float)
   18750      *
   18751      * @attr ref android.R.styleable#View_layerType
   18752      */
   18753     public void setLayerType(int layerType, @Nullable Paint paint) {
   18754         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
   18755             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
   18756                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
   18757         }
   18758 
   18759         boolean typeChanged = mRenderNode.setLayerType(layerType);
   18760 
   18761         if (!typeChanged) {
   18762             setLayerPaint(paint);
   18763             return;
   18764         }
   18765 
   18766         if (layerType != LAYER_TYPE_SOFTWARE) {
   18767             // Destroy any previous software drawing cache if present
   18768             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
   18769             // drawing cache created in View#draw when drawing to a SW canvas.
   18770             destroyDrawingCache();
   18771         }
   18772 
   18773         mLayerType = layerType;
   18774         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
   18775         mRenderNode.setLayerPaint(mLayerPaint);
   18776 
   18777         // draw() behaves differently if we are on a layer, so we need to
   18778         // invalidate() here
   18779         invalidateParentCaches();
   18780         invalidate(true);
   18781     }
   18782 
   18783     /**
   18784      * Updates the {@link Paint} object used with the current layer (used only if the current
   18785      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
   18786      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
   18787      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
   18788      * ensure that the view gets redrawn immediately.
   18789      *
   18790      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   18791      * instance that controls how the layer is composed on screen. The following
   18792      * properties of the paint are taken into account when composing the layer:</p>
   18793      * <ul>
   18794      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   18795      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   18796      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   18797      * </ul>
   18798      *
   18799      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
   18800      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
   18801      *
   18802      * @param paint The paint used to compose the layer. This argument is optional
   18803      *        and can be null. It is ignored when the layer type is
   18804      *        {@link #LAYER_TYPE_NONE}
   18805      *
   18806      * @see #setLayerType(int, android.graphics.Paint)
   18807      */
   18808     public void setLayerPaint(@Nullable Paint paint) {
   18809         int layerType = getLayerType();
   18810         if (layerType != LAYER_TYPE_NONE) {
   18811             mLayerPaint = paint;
   18812             if (layerType == LAYER_TYPE_HARDWARE) {
   18813                 if (mRenderNode.setLayerPaint(paint)) {
   18814                     invalidateViewProperty(false, false);
   18815                 }
   18816             } else {
   18817                 invalidate();
   18818             }
   18819         }
   18820     }
   18821 
   18822     /**
   18823      * Indicates what type of layer is currently associated with this view. By default
   18824      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
   18825      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
   18826      * for more information on the different types of layers.
   18827      *
   18828      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   18829      *         {@link #LAYER_TYPE_HARDWARE}
   18830      *
   18831      * @see #setLayerType(int, android.graphics.Paint)
   18832      * @see #buildLayer()
   18833      * @see #LAYER_TYPE_NONE
   18834      * @see #LAYER_TYPE_SOFTWARE
   18835      * @see #LAYER_TYPE_HARDWARE
   18836      */
   18837     public int getLayerType() {
   18838         return mLayerType;
   18839     }
   18840 
   18841     /**
   18842      * Forces this view's layer to be created and this view to be rendered
   18843      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
   18844      * invoking this method will have no effect.
   18845      *
   18846      * This method can for instance be used to render a view into its layer before
   18847      * starting an animation. If this view is complex, rendering into the layer
   18848      * before starting the animation will avoid skipping frames.
   18849      *
   18850      * @throws IllegalStateException If this view is not attached to a window
   18851      *
   18852      * @see #setLayerType(int, android.graphics.Paint)
   18853      */
   18854     public void buildLayer() {
   18855         if (mLayerType == LAYER_TYPE_NONE) return;
   18856 
   18857         final AttachInfo attachInfo = mAttachInfo;
   18858         if (attachInfo == null) {
   18859             throw new IllegalStateException("This view must be attached to a window first");
   18860         }
   18861 
   18862         if (getWidth() == 0 || getHeight() == 0) {
   18863             return;
   18864         }
   18865 
   18866         switch (mLayerType) {
   18867             case LAYER_TYPE_HARDWARE:
   18868                 updateDisplayListIfDirty();
   18869                 if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
   18870                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
   18871                 }
   18872                 break;
   18873             case LAYER_TYPE_SOFTWARE:
   18874                 buildDrawingCache(true);
   18875                 break;
   18876         }
   18877     }
   18878 
   18879     /**
   18880      * Destroys all hardware rendering resources. This method is invoked
   18881      * when the system needs to reclaim resources. Upon execution of this
   18882      * method, you should free any OpenGL resources created by the view.
   18883      *
   18884      * Note: you <strong>must</strong> call
   18885      * <code>super.destroyHardwareResources()</code> when overriding
   18886      * this method.
   18887      *
   18888      * @hide
   18889      */
   18890     @CallSuper
   18891     protected void destroyHardwareResources() {
   18892         if (mOverlay != null) {
   18893             mOverlay.getOverlayView().destroyHardwareResources();
   18894         }
   18895         if (mGhostView != null) {
   18896             mGhostView.destroyHardwareResources();
   18897         }
   18898     }
   18899 
   18900     /**
   18901      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
   18902      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
   18903      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
   18904      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
   18905      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
   18906      * null.</p>
   18907      *
   18908      * <p>Enabling the drawing cache is similar to
   18909      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
   18910      * acceleration is turned off. When hardware acceleration is turned on, enabling the
   18911      * drawing cache has no effect on rendering because the system uses a different mechanism
   18912      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
   18913      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
   18914      * for information on how to enable software and hardware layers.</p>
   18915      *
   18916      * <p>This API can be used to manually generate
   18917      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
   18918      * {@link #getDrawingCache()}.</p>
   18919      *
   18920      * @param enabled true to enable the drawing cache, false otherwise
   18921      *
   18922      * @see #isDrawingCacheEnabled()
   18923      * @see #getDrawingCache()
   18924      * @see #buildDrawingCache()
   18925      * @see #setLayerType(int, android.graphics.Paint)
   18926      *
   18927      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   18928      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   18929      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   18930      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   18931      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   18932      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   18933      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   18934      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   18935      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   18936      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   18937      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   18938      * reports or unit testing the {@link PixelCopy} API is recommended.
   18939      */
   18940     @Deprecated
   18941     public void setDrawingCacheEnabled(boolean enabled) {
   18942         mCachingFailed = false;
   18943         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
   18944     }
   18945 
   18946     /**
   18947      * <p>Indicates whether the drawing cache is enabled for this view.</p>
   18948      *
   18949      * @return true if the drawing cache is enabled
   18950      *
   18951      * @see #setDrawingCacheEnabled(boolean)
   18952      * @see #getDrawingCache()
   18953      *
   18954      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   18955      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   18956      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   18957      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   18958      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   18959      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   18960      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   18961      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   18962      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   18963      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   18964      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   18965      * reports or unit testing the {@link PixelCopy} API is recommended.
   18966      */
   18967     @Deprecated
   18968     @ViewDebug.ExportedProperty(category = "drawing")
   18969     public boolean isDrawingCacheEnabled() {
   18970         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
   18971     }
   18972 
   18973     /**
   18974      * Debugging utility which recursively outputs the dirty state of a view and its
   18975      * descendants.
   18976      *
   18977      * @hide
   18978      */
   18979     @SuppressWarnings({"UnusedDeclaration"})
   18980     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
   18981         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
   18982                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
   18983                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
   18984                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
   18985                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
   18986         if (clear) {
   18987             mPrivateFlags &= clearMask;
   18988         }
   18989         if (this instanceof ViewGroup) {
   18990             ViewGroup parent = (ViewGroup) this;
   18991             final int count = parent.getChildCount();
   18992             for (int i = 0; i < count; i++) {
   18993                 final View child = parent.getChildAt(i);
   18994                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
   18995             }
   18996         }
   18997     }
   18998 
   18999     /**
   19000      * This method is used by ViewGroup to cause its children to restore or recreate their
   19001      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
   19002      * to recreate its own display list, which would happen if it went through the normal
   19003      * draw/dispatchDraw mechanisms.
   19004      *
   19005      * @hide
   19006      */
   19007     protected void dispatchGetDisplayList() {}
   19008 
   19009     /**
   19010      * A view that is not attached or hardware accelerated cannot create a display list.
   19011      * This method checks these conditions and returns the appropriate result.
   19012      *
   19013      * @return true if view has the ability to create a display list, false otherwise.
   19014      *
   19015      * @hide
   19016      */
   19017     public boolean canHaveDisplayList() {
   19018         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
   19019     }
   19020 
   19021     /**
   19022      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
   19023      * @hide
   19024      */
   19025     @NonNull
   19026     public RenderNode updateDisplayListIfDirty() {
   19027         final RenderNode renderNode = mRenderNode;
   19028         if (!canHaveDisplayList()) {
   19029             // can't populate RenderNode, don't try
   19030             return renderNode;
   19031         }
   19032 
   19033         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
   19034                 || !renderNode.isValid()
   19035                 || (mRecreateDisplayList)) {
   19036             // Don't need to recreate the display list, just need to tell our
   19037             // children to restore/recreate theirs
   19038             if (renderNode.isValid()
   19039                     && !mRecreateDisplayList) {
   19040                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   19041                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   19042                 dispatchGetDisplayList();
   19043 
   19044                 return renderNode; // no work needed
   19045             }
   19046 
   19047             // If we got here, we're recreating it. Mark it as such to ensure that
   19048             // we copy in child display lists into ours in drawChild()
   19049             mRecreateDisplayList = true;
   19050 
   19051             int width = mRight - mLeft;
   19052             int height = mBottom - mTop;
   19053             int layerType = getLayerType();
   19054 
   19055             final DisplayListCanvas canvas = renderNode.start(width, height);
   19056 
   19057             try {
   19058                 if (layerType == LAYER_TYPE_SOFTWARE) {
   19059                     buildDrawingCache(true);
   19060                     Bitmap cache = getDrawingCache(true);
   19061                     if (cache != null) {
   19062                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
   19063                     }
   19064                 } else {
   19065                     computeScroll();
   19066 
   19067                     canvas.translate(-mScrollX, -mScrollY);
   19068                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   19069                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   19070 
   19071                     // Fast path for layouts with no backgrounds
   19072                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   19073                         dispatchDraw(canvas);
   19074                         drawAutofilledHighlight(canvas);
   19075                         if (mOverlay != null && !mOverlay.isEmpty()) {
   19076                             mOverlay.getOverlayView().draw(canvas);
   19077                         }
   19078                         if (debugDraw()) {
   19079                             debugDrawFocus(canvas);
   19080                         }
   19081                     } else {
   19082                         draw(canvas);
   19083                     }
   19084                 }
   19085             } finally {
   19086                 renderNode.end(canvas);
   19087                 setDisplayListProperties(renderNode);
   19088             }
   19089         } else {
   19090             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   19091             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   19092         }
   19093         return renderNode;
   19094     }
   19095 
   19096     private void resetDisplayList() {
   19097         mRenderNode.discardDisplayList();
   19098         if (mBackgroundRenderNode != null) {
   19099             mBackgroundRenderNode.discardDisplayList();
   19100         }
   19101     }
   19102 
   19103     /**
   19104      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
   19105      *
   19106      * @return A non-scaled bitmap representing this view or null if cache is disabled.
   19107      *
   19108      * @see #getDrawingCache(boolean)
   19109      *
   19110      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   19111      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   19112      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   19113      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   19114      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   19115      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   19116      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   19117      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   19118      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   19119      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   19120      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   19121      * reports or unit testing the {@link PixelCopy} API is recommended.
   19122      */
   19123     @Deprecated
   19124     public Bitmap getDrawingCache() {
   19125         return getDrawingCache(false);
   19126     }
   19127 
   19128     /**
   19129      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
   19130      * is null when caching is disabled. If caching is enabled and the cache is not ready,
   19131      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
   19132      * draw from the cache when the cache is enabled. To benefit from the cache, you must
   19133      * request the drawing cache by calling this method and draw it on screen if the
   19134      * returned bitmap is not null.</p>
   19135      *
   19136      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   19137      * this method will create a bitmap of the same size as this view. Because this bitmap
   19138      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   19139      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   19140      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   19141      * size than the view. This implies that your application must be able to handle this
   19142      * size.</p>
   19143      *
   19144      * @param autoScale Indicates whether the generated bitmap should be scaled based on
   19145      *        the current density of the screen when the application is in compatibility
   19146      *        mode.
   19147      *
   19148      * @return A bitmap representing this view or null if cache is disabled.
   19149      *
   19150      * @see #setDrawingCacheEnabled(boolean)
   19151      * @see #isDrawingCacheEnabled()
   19152      * @see #buildDrawingCache(boolean)
   19153      * @see #destroyDrawingCache()
   19154      *
   19155      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   19156      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   19157      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   19158      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   19159      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   19160      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   19161      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   19162      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   19163      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   19164      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   19165      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   19166      * reports or unit testing the {@link PixelCopy} API is recommended.
   19167      */
   19168     @Deprecated
   19169     public Bitmap getDrawingCache(boolean autoScale) {
   19170         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
   19171             return null;
   19172         }
   19173         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
   19174             buildDrawingCache(autoScale);
   19175         }
   19176         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
   19177     }
   19178 
   19179     /**
   19180      * <p>Frees the resources used by the drawing cache. If you call
   19181      * {@link #buildDrawingCache()} manually without calling
   19182      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   19183      * should cleanup the cache with this method afterwards.</p>
   19184      *
   19185      * @see #setDrawingCacheEnabled(boolean)
   19186      * @see #buildDrawingCache()
   19187      * @see #getDrawingCache()
   19188      *
   19189      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   19190      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   19191      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   19192      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   19193      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   19194      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   19195      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   19196      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   19197      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   19198      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   19199      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   19200      * reports or unit testing the {@link PixelCopy} API is recommended.
   19201      */
   19202     @Deprecated
   19203     public void destroyDrawingCache() {
   19204         if (mDrawingCache != null) {
   19205             mDrawingCache.recycle();
   19206             mDrawingCache = null;
   19207         }
   19208         if (mUnscaledDrawingCache != null) {
   19209             mUnscaledDrawingCache.recycle();
   19210             mUnscaledDrawingCache = null;
   19211         }
   19212     }
   19213 
   19214     /**
   19215      * Setting a solid background color for the drawing cache's bitmaps will improve
   19216      * performance and memory usage. Note, though that this should only be used if this
   19217      * view will always be drawn on top of a solid color.
   19218      *
   19219      * @param color The background color to use for the drawing cache's bitmap
   19220      *
   19221      * @see #setDrawingCacheEnabled(boolean)
   19222      * @see #buildDrawingCache()
   19223      * @see #getDrawingCache()
   19224      *
   19225      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   19226      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   19227      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   19228      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   19229      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   19230      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   19231      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   19232      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   19233      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   19234      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   19235      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   19236      * reports or unit testing the {@link PixelCopy} API is recommended.
   19237      */
   19238     @Deprecated
   19239     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
   19240         if (color != mDrawingCacheBackgroundColor) {
   19241             mDrawingCacheBackgroundColor = color;
   19242             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   19243         }
   19244     }
   19245 
   19246     /**
   19247      * @see #setDrawingCacheBackgroundColor(int)
   19248      *
   19249      * @return The background color to used for the drawing cache's bitmap
   19250      *
   19251      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   19252      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   19253      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   19254      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   19255      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   19256      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   19257      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   19258      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   19259      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   19260      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   19261      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   19262      * reports or unit testing the {@link PixelCopy} API is recommended.
   19263      */
   19264     @Deprecated
   19265     @ColorInt
   19266     public int getDrawingCacheBackgroundColor() {
   19267         return mDrawingCacheBackgroundColor;
   19268     }
   19269 
   19270     /**
   19271      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
   19272      *
   19273      * @see #buildDrawingCache(boolean)
   19274      *
   19275      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   19276      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   19277      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   19278      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   19279      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   19280      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   19281      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   19282      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   19283      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   19284      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   19285      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   19286      * reports or unit testing the {@link PixelCopy} API is recommended.
   19287      */
   19288     @Deprecated
   19289     public void buildDrawingCache() {
   19290         buildDrawingCache(false);
   19291     }
   19292 
   19293     /**
   19294      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
   19295      *
   19296      * <p>If you call {@link #buildDrawingCache()} manually without calling
   19297      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   19298      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
   19299      *
   19300      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   19301      * this method will create a bitmap of the same size as this view. Because this bitmap
   19302      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   19303      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   19304      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   19305      * size than the view. This implies that your application must be able to handle this
   19306      * size.</p>
   19307      *
   19308      * <p>You should avoid calling this method when hardware acceleration is enabled. If
   19309      * you do not need the drawing cache bitmap, calling this method will increase memory
   19310      * usage and cause the view to be rendered in software once, thus negatively impacting
   19311      * performance.</p>
   19312      *
   19313      * @see #getDrawingCache()
   19314      * @see #destroyDrawingCache()
   19315      *
   19316      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   19317      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   19318      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   19319      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   19320      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   19321      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   19322      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   19323      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   19324      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   19325      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   19326      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   19327      * reports or unit testing the {@link PixelCopy} API is recommended.
   19328      */
   19329     @Deprecated
   19330     public void buildDrawingCache(boolean autoScale) {
   19331         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
   19332                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
   19333             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
   19334                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
   19335                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
   19336             }
   19337             try {
   19338                 buildDrawingCacheImpl(autoScale);
   19339             } finally {
   19340                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
   19341             }
   19342         }
   19343     }
   19344 
   19345     /**
   19346      * private, internal implementation of buildDrawingCache, used to enable tracing
   19347      */
   19348     private void buildDrawingCacheImpl(boolean autoScale) {
   19349         mCachingFailed = false;
   19350 
   19351         int width = mRight - mLeft;
   19352         int height = mBottom - mTop;
   19353 
   19354         final AttachInfo attachInfo = mAttachInfo;
   19355         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
   19356 
   19357         if (autoScale && scalingRequired) {
   19358             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
   19359             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
   19360         }
   19361 
   19362         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
   19363         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
   19364         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
   19365 
   19366         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
   19367         final long drawingCacheSize =
   19368                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
   19369         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
   19370             if (width > 0 && height > 0) {
   19371                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
   19372                         + " too large to fit into a software layer (or drawing cache), needs "
   19373                         + projectedBitmapSize + " bytes, only "
   19374                         + drawingCacheSize + " available");
   19375             }
   19376             destroyDrawingCache();
   19377             mCachingFailed = true;
   19378             return;
   19379         }
   19380 
   19381         boolean clear = true;
   19382         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
   19383 
   19384         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
   19385             Bitmap.Config quality;
   19386             if (!opaque) {
   19387                 // Never pick ARGB_4444 because it looks awful
   19388                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
   19389                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
   19390                     case DRAWING_CACHE_QUALITY_AUTO:
   19391                     case DRAWING_CACHE_QUALITY_LOW:
   19392                     case DRAWING_CACHE_QUALITY_HIGH:
   19393                     default:
   19394                         quality = Bitmap.Config.ARGB_8888;
   19395                         break;
   19396                 }
   19397             } else {
   19398                 // Optimization for translucent windows
   19399                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
   19400                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
   19401             }
   19402 
   19403             // Try to cleanup memory
   19404             if (bitmap != null) bitmap.recycle();
   19405 
   19406             try {
   19407                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
   19408                         width, height, quality);
   19409                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
   19410                 if (autoScale) {
   19411                     mDrawingCache = bitmap;
   19412                 } else {
   19413                     mUnscaledDrawingCache = bitmap;
   19414                 }
   19415                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
   19416             } catch (OutOfMemoryError e) {
   19417                 // If there is not enough memory to create the bitmap cache, just
   19418                 // ignore the issue as bitmap caches are not required to draw the
   19419                 // view hierarchy
   19420                 if (autoScale) {
   19421                     mDrawingCache = null;
   19422                 } else {
   19423                     mUnscaledDrawingCache = null;
   19424                 }
   19425                 mCachingFailed = true;
   19426                 return;
   19427             }
   19428 
   19429             clear = drawingCacheBackgroundColor != 0;
   19430         }
   19431 
   19432         Canvas canvas;
   19433         if (attachInfo != null) {
   19434             canvas = attachInfo.mCanvas;
   19435             if (canvas == null) {
   19436                 canvas = new Canvas();
   19437             }
   19438             canvas.setBitmap(bitmap);
   19439             // Temporarily clobber the cached Canvas in case one of our children
   19440             // is also using a drawing cache. Without this, the children would
   19441             // steal the canvas by attaching their own bitmap to it and bad, bad
   19442             // thing would happen (invisible views, corrupted drawings, etc.)
   19443             attachInfo.mCanvas = null;
   19444         } else {
   19445             // This case should hopefully never or seldom happen
   19446             canvas = new Canvas(bitmap);
   19447         }
   19448 
   19449         if (clear) {
   19450             bitmap.eraseColor(drawingCacheBackgroundColor);
   19451         }
   19452 
   19453         computeScroll();
   19454         final int restoreCount = canvas.save();
   19455 
   19456         if (autoScale && scalingRequired) {
   19457             final float scale = attachInfo.mApplicationScale;
   19458             canvas.scale(scale, scale);
   19459         }
   19460 
   19461         canvas.translate(-mScrollX, -mScrollY);
   19462 
   19463         mPrivateFlags |= PFLAG_DRAWN;
   19464         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
   19465                 mLayerType != LAYER_TYPE_NONE) {
   19466             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
   19467         }
   19468 
   19469         // Fast path for layouts with no backgrounds
   19470         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   19471             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   19472             dispatchDraw(canvas);
   19473             drawAutofilledHighlight(canvas);
   19474             if (mOverlay != null && !mOverlay.isEmpty()) {
   19475                 mOverlay.getOverlayView().draw(canvas);
   19476             }
   19477         } else {
   19478             draw(canvas);
   19479         }
   19480 
   19481         canvas.restoreToCount(restoreCount);
   19482         canvas.setBitmap(null);
   19483 
   19484         if (attachInfo != null) {
   19485             // Restore the cached Canvas for our siblings
   19486             attachInfo.mCanvas = canvas;
   19487         }
   19488     }
   19489 
   19490     /**
   19491      * Create a snapshot of the view into a bitmap.  We should probably make
   19492      * some form of this public, but should think about the API.
   19493      *
   19494      * @hide
   19495      */
   19496     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
   19497         int width = mRight - mLeft;
   19498         int height = mBottom - mTop;
   19499 
   19500         final AttachInfo attachInfo = mAttachInfo;
   19501         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
   19502         width = (int) ((width * scale) + 0.5f);
   19503         height = (int) ((height * scale) + 0.5f);
   19504 
   19505         Canvas oldCanvas = null;
   19506         try {
   19507             Canvas canvas = canvasProvider.getCanvas(this,
   19508                     width > 0 ? width : 1, height > 0 ? height : 1);
   19509 
   19510             if (attachInfo != null) {
   19511                 oldCanvas = attachInfo.mCanvas;
   19512                 // Temporarily clobber the cached Canvas in case one of our children
   19513                 // is also using a drawing cache. Without this, the children would
   19514                 // steal the canvas by attaching their own bitmap to it and bad, bad
   19515                 // things would happen (invisible views, corrupted drawings, etc.)
   19516                 attachInfo.mCanvas = null;
   19517             }
   19518 
   19519             computeScroll();
   19520             final int restoreCount = canvas.save();
   19521             canvas.scale(scale, scale);
   19522             canvas.translate(-mScrollX, -mScrollY);
   19523 
   19524             // Temporarily remove the dirty mask
   19525             int flags = mPrivateFlags;
   19526             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   19527 
   19528             // Fast path for layouts with no backgrounds
   19529             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   19530                 dispatchDraw(canvas);
   19531                 drawAutofilledHighlight(canvas);
   19532                 if (mOverlay != null && !mOverlay.isEmpty()) {
   19533                     mOverlay.getOverlayView().draw(canvas);
   19534                 }
   19535             } else {
   19536                 draw(canvas);
   19537             }
   19538 
   19539             mPrivateFlags = flags;
   19540             canvas.restoreToCount(restoreCount);
   19541             return canvasProvider.createBitmap();
   19542         } finally {
   19543             if (oldCanvas != null) {
   19544                 attachInfo.mCanvas = oldCanvas;
   19545             }
   19546         }
   19547     }
   19548 
   19549     /**
   19550      * Indicates whether this View is currently in edit mode. A View is usually
   19551      * in edit mode when displayed within a developer tool. For instance, if
   19552      * this View is being drawn by a visual user interface builder, this method
   19553      * should return true.
   19554      *
   19555      * Subclasses should check the return value of this method to provide
   19556      * different behaviors if their normal behavior might interfere with the
   19557      * host environment. For instance: the class spawns a thread in its
   19558      * constructor, the drawing code relies on device-specific features, etc.
   19559      *
   19560      * This method is usually checked in the drawing code of custom widgets.
   19561      *
   19562      * @return True if this View is in edit mode, false otherwise.
   19563      */
   19564     public boolean isInEditMode() {
   19565         return false;
   19566     }
   19567 
   19568     /**
   19569      * If the View draws content inside its padding and enables fading edges,
   19570      * it needs to support padding offsets. Padding offsets are added to the
   19571      * fading edges to extend the length of the fade so that it covers pixels
   19572      * drawn inside the padding.
   19573      *
   19574      * Subclasses of this class should override this method if they need
   19575      * to draw content inside the padding.
   19576      *
   19577      * @return True if padding offset must be applied, false otherwise.
   19578      *
   19579      * @see #getLeftPaddingOffset()
   19580      * @see #getRightPaddingOffset()
   19581      * @see #getTopPaddingOffset()
   19582      * @see #getBottomPaddingOffset()
   19583      *
   19584      * @since CURRENT
   19585      */
   19586     protected boolean isPaddingOffsetRequired() {
   19587         return false;
   19588     }
   19589 
   19590     /**
   19591      * Amount by which to extend the left fading region. Called only when
   19592      * {@link #isPaddingOffsetRequired()} returns true.
   19593      *
   19594      * @return The left padding offset in pixels.
   19595      *
   19596      * @see #isPaddingOffsetRequired()
   19597      *
   19598      * @since CURRENT
   19599      */
   19600     protected int getLeftPaddingOffset() {
   19601         return 0;
   19602     }
   19603 
   19604     /**
   19605      * Amount by which to extend the right fading region. Called only when
   19606      * {@link #isPaddingOffsetRequired()} returns true.
   19607      *
   19608      * @return The right padding offset in pixels.
   19609      *
   19610      * @see #isPaddingOffsetRequired()
   19611      *
   19612      * @since CURRENT
   19613      */
   19614     protected int getRightPaddingOffset() {
   19615         return 0;
   19616     }
   19617 
   19618     /**
   19619      * Amount by which to extend the top fading region. Called only when
   19620      * {@link #isPaddingOffsetRequired()} returns true.
   19621      *
   19622      * @return The top padding offset in pixels.
   19623      *
   19624      * @see #isPaddingOffsetRequired()
   19625      *
   19626      * @since CURRENT
   19627      */
   19628     protected int getTopPaddingOffset() {
   19629         return 0;
   19630     }
   19631 
   19632     /**
   19633      * Amount by which to extend the bottom fading region. Called only when
   19634      * {@link #isPaddingOffsetRequired()} returns true.
   19635      *
   19636      * @return The bottom padding offset in pixels.
   19637      *
   19638      * @see #isPaddingOffsetRequired()
   19639      *
   19640      * @since CURRENT
   19641      */
   19642     protected int getBottomPaddingOffset() {
   19643         return 0;
   19644     }
   19645 
   19646     /**
   19647      * @hide
   19648      * @param offsetRequired
   19649      */
   19650     protected int getFadeTop(boolean offsetRequired) {
   19651         int top = mPaddingTop;
   19652         if (offsetRequired) top += getTopPaddingOffset();
   19653         return top;
   19654     }
   19655 
   19656     /**
   19657      * @hide
   19658      * @param offsetRequired
   19659      */
   19660     protected int getFadeHeight(boolean offsetRequired) {
   19661         int padding = mPaddingTop;
   19662         if (offsetRequired) padding += getTopPaddingOffset();
   19663         return mBottom - mTop - mPaddingBottom - padding;
   19664     }
   19665 
   19666     /**
   19667      * <p>Indicates whether this view is attached to a hardware accelerated
   19668      * window or not.</p>
   19669      *
   19670      * <p>Even if this method returns true, it does not mean that every call
   19671      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
   19672      * accelerated {@link android.graphics.Canvas}. For instance, if this view
   19673      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
   19674      * window is hardware accelerated,
   19675      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
   19676      * return false, and this method will return true.</p>
   19677      *
   19678      * @return True if the view is attached to a window and the window is
   19679      *         hardware accelerated; false in any other case.
   19680      */
   19681     @ViewDebug.ExportedProperty(category = "drawing")
   19682     public boolean isHardwareAccelerated() {
   19683         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
   19684     }
   19685 
   19686     /**
   19687      * Sets a rectangular area on this view to which the view will be clipped
   19688      * when it is drawn. Setting the value to null will remove the clip bounds
   19689      * and the view will draw normally, using its full bounds.
   19690      *
   19691      * @param clipBounds The rectangular area, in the local coordinates of
   19692      * this view, to which future drawing operations will be clipped.
   19693      */
   19694     public void setClipBounds(Rect clipBounds) {
   19695         if (clipBounds == mClipBounds
   19696                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
   19697             return;
   19698         }
   19699         if (clipBounds != null) {
   19700             if (mClipBounds == null) {
   19701                 mClipBounds = new Rect(clipBounds);
   19702             } else {
   19703                 mClipBounds.set(clipBounds);
   19704             }
   19705         } else {
   19706             mClipBounds = null;
   19707         }
   19708         mRenderNode.setClipBounds(mClipBounds);
   19709         invalidateViewProperty(false, false);
   19710     }
   19711 
   19712     /**
   19713      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
   19714      *
   19715      * @return A copy of the current clip bounds if clip bounds are set,
   19716      * otherwise null.
   19717      */
   19718     public Rect getClipBounds() {
   19719         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
   19720     }
   19721 
   19722 
   19723     /**
   19724      * Populates an output rectangle with the clip bounds of the view,
   19725      * returning {@code true} if successful or {@code false} if the view's
   19726      * clip bounds are {@code null}.
   19727      *
   19728      * @param outRect rectangle in which to place the clip bounds of the view
   19729      * @return {@code true} if successful or {@code false} if the view's
   19730      *         clip bounds are {@code null}
   19731      */
   19732     public boolean getClipBounds(Rect outRect) {
   19733         if (mClipBounds != null) {
   19734             outRect.set(mClipBounds);
   19735             return true;
   19736         }
   19737         return false;
   19738     }
   19739 
   19740     /**
   19741      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
   19742      * case of an active Animation being run on the view.
   19743      */
   19744     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
   19745             Animation a, boolean scalingRequired) {
   19746         Transformation invalidationTransform;
   19747         final int flags = parent.mGroupFlags;
   19748         final boolean initialized = a.isInitialized();
   19749         if (!initialized) {
   19750             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
   19751             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
   19752             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
   19753             onAnimationStart();
   19754         }
   19755 
   19756         final Transformation t = parent.getChildTransformation();
   19757         boolean more = a.getTransformation(drawingTime, t, 1f);
   19758         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
   19759             if (parent.mInvalidationTransformation == null) {
   19760                 parent.mInvalidationTransformation = new Transformation();
   19761             }
   19762             invalidationTransform = parent.mInvalidationTransformation;
   19763             a.getTransformation(drawingTime, invalidationTransform, 1f);
   19764         } else {
   19765             invalidationTransform = t;
   19766         }
   19767 
   19768         if (more) {
   19769             if (!a.willChangeBounds()) {
   19770                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
   19771                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
   19772                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
   19773                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
   19774                     // The child need to draw an animation, potentially offscreen, so
   19775                     // make sure we do not cancel invalidate requests
   19776                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   19777                     parent.invalidate(mLeft, mTop, mRight, mBottom);
   19778                 }
   19779             } else {
   19780                 if (parent.mInvalidateRegion == null) {
   19781                     parent.mInvalidateRegion = new RectF();
   19782                 }
   19783                 final RectF region = parent.mInvalidateRegion;
   19784                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
   19785                         invalidationTransform);
   19786 
   19787                 // The child need to draw an animation, potentially offscreen, so
   19788                 // make sure we do not cancel invalidate requests
   19789                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   19790 
   19791                 final int left = mLeft + (int) region.left;
   19792                 final int top = mTop + (int) region.top;
   19793                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
   19794                         top + (int) (region.height() + .5f));
   19795             }
   19796         }
   19797         return more;
   19798     }
   19799 
   19800     /**
   19801      * This method is called by getDisplayList() when a display list is recorded for a View.
   19802      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
   19803      */
   19804     void setDisplayListProperties(RenderNode renderNode) {
   19805         if (renderNode != null) {
   19806             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
   19807             renderNode.setClipToBounds(mParent instanceof ViewGroup
   19808                     && ((ViewGroup) mParent).getClipChildren());
   19809 
   19810             float alpha = 1;
   19811             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
   19812                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   19813                 ViewGroup parentVG = (ViewGroup) mParent;
   19814                 final Transformation t = parentVG.getChildTransformation();
   19815                 if (parentVG.getChildStaticTransformation(this, t)) {
   19816                     final int transformType = t.getTransformationType();
   19817                     if (transformType != Transformation.TYPE_IDENTITY) {
   19818                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
   19819                             alpha = t.getAlpha();
   19820                         }
   19821                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
   19822                             renderNode.setStaticMatrix(t.getMatrix());
   19823                         }
   19824                     }
   19825                 }
   19826             }
   19827             if (mTransformationInfo != null) {
   19828                 alpha *= getFinalAlpha();
   19829                 if (alpha < 1) {
   19830                     final int multipliedAlpha = (int) (255 * alpha);
   19831                     if (onSetAlpha(multipliedAlpha)) {
   19832                         alpha = 1;
   19833                     }
   19834                 }
   19835                 renderNode.setAlpha(alpha);
   19836             } else if (alpha < 1) {
   19837                 renderNode.setAlpha(alpha);
   19838             }
   19839         }
   19840     }
   19841 
   19842     /**
   19843      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
   19844      *
   19845      * This is where the View specializes rendering behavior based on layer type,
   19846      * and hardware acceleration.
   19847      */
   19848     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
   19849         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
   19850         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
   19851          *
   19852          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
   19853          * HW accelerated, it can't handle drawing RenderNodes.
   19854          */
   19855         boolean drawingWithRenderNode = mAttachInfo != null
   19856                 && mAttachInfo.mHardwareAccelerated
   19857                 && hardwareAcceleratedCanvas;
   19858 
   19859         boolean more = false;
   19860         final boolean childHasIdentityMatrix = hasIdentityMatrix();
   19861         final int parentFlags = parent.mGroupFlags;
   19862 
   19863         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
   19864             parent.getChildTransformation().clear();
   19865             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   19866         }
   19867 
   19868         Transformation transformToApply = null;
   19869         boolean concatMatrix = false;
   19870         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
   19871         final Animation a = getAnimation();
   19872         if (a != null) {
   19873             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
   19874             concatMatrix = a.willChangeTransformationMatrix();
   19875             if (concatMatrix) {
   19876                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   19877             }
   19878             transformToApply = parent.getChildTransformation();
   19879         } else {
   19880             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
   19881                 // No longer animating: clear out old animation matrix
   19882                 mRenderNode.setAnimationMatrix(null);
   19883                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   19884             }
   19885             if (!drawingWithRenderNode
   19886                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   19887                 final Transformation t = parent.getChildTransformation();
   19888                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
   19889                 if (hasTransform) {
   19890                     final int transformType = t.getTransformationType();
   19891                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
   19892                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
   19893                 }
   19894             }
   19895         }
   19896 
   19897         concatMatrix |= !childHasIdentityMatrix;
   19898 
   19899         // Sets the flag as early as possible to allow draw() implementations
   19900         // to call invalidate() successfully when doing animations
   19901         mPrivateFlags |= PFLAG_DRAWN;
   19902 
   19903         if (!concatMatrix &&
   19904                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
   19905                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
   19906                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
   19907                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
   19908             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
   19909             return more;
   19910         }
   19911         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
   19912 
   19913         if (hardwareAcceleratedCanvas) {
   19914             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
   19915             // retain the flag's value temporarily in the mRecreateDisplayList flag
   19916             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
   19917             mPrivateFlags &= ~PFLAG_INVALIDATED;
   19918         }
   19919 
   19920         RenderNode renderNode = null;
   19921         Bitmap cache = null;
   19922         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
   19923         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
   19924              if (layerType != LAYER_TYPE_NONE) {
   19925                  // If not drawing with RenderNode, treat HW layers as SW
   19926                  layerType = LAYER_TYPE_SOFTWARE;
   19927                  buildDrawingCache(true);
   19928             }
   19929             cache = getDrawingCache(true);
   19930         }
   19931 
   19932         if (drawingWithRenderNode) {
   19933             // Delay getting the display list until animation-driven alpha values are
   19934             // set up and possibly passed on to the view
   19935             renderNode = updateDisplayListIfDirty();
   19936             if (!renderNode.isValid()) {
   19937                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
   19938                 // to getDisplayList(), the display list will be marked invalid and we should not
   19939                 // try to use it again.
   19940                 renderNode = null;
   19941                 drawingWithRenderNode = false;
   19942             }
   19943         }
   19944 
   19945         int sx = 0;
   19946         int sy = 0;
   19947         if (!drawingWithRenderNode) {
   19948             computeScroll();
   19949             sx = mScrollX;
   19950             sy = mScrollY;
   19951         }
   19952 
   19953         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
   19954         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
   19955 
   19956         int restoreTo = -1;
   19957         if (!drawingWithRenderNode || transformToApply != null) {
   19958             restoreTo = canvas.save();
   19959         }
   19960         if (offsetForScroll) {
   19961             canvas.translate(mLeft - sx, mTop - sy);
   19962         } else {
   19963             if (!drawingWithRenderNode) {
   19964                 canvas.translate(mLeft, mTop);
   19965             }
   19966             if (scalingRequired) {
   19967                 if (drawingWithRenderNode) {
   19968                     // TODO: Might not need this if we put everything inside the DL
   19969                     restoreTo = canvas.save();
   19970                 }
   19971                 // mAttachInfo cannot be null, otherwise scalingRequired == false
   19972                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
   19973                 canvas.scale(scale, scale);
   19974             }
   19975         }
   19976 
   19977         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
   19978         if (transformToApply != null
   19979                 || alpha < 1
   19980                 || !hasIdentityMatrix()
   19981                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   19982             if (transformToApply != null || !childHasIdentityMatrix) {
   19983                 int transX = 0;
   19984                 int transY = 0;
   19985 
   19986                 if (offsetForScroll) {
   19987                     transX = -sx;
   19988                     transY = -sy;
   19989                 }
   19990 
   19991                 if (transformToApply != null) {
   19992                     if (concatMatrix) {
   19993                         if (drawingWithRenderNode) {
   19994                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
   19995                         } else {
   19996                             // Undo the scroll translation, apply the transformation matrix,
   19997                             // then redo the scroll translate to get the correct result.
   19998                             canvas.translate(-transX, -transY);
   19999                             canvas.concat(transformToApply.getMatrix());
   20000                             canvas.translate(transX, transY);
   20001                         }
   20002                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   20003                     }
   20004 
   20005                     float transformAlpha = transformToApply.getAlpha();
   20006                     if (transformAlpha < 1) {
   20007                         alpha *= transformAlpha;
   20008                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   20009                     }
   20010                 }
   20011 
   20012                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
   20013                     canvas.translate(-transX, -transY);
   20014                     canvas.concat(getMatrix());
   20015                     canvas.translate(transX, transY);
   20016                 }
   20017             }
   20018 
   20019             // Deal with alpha if it is or used to be <1
   20020             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   20021                 if (alpha < 1) {
   20022                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   20023                 } else {
   20024                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   20025                 }
   20026                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   20027                 if (!drawingWithDrawingCache) {
   20028                     final int multipliedAlpha = (int) (255 * alpha);
   20029                     if (!onSetAlpha(multipliedAlpha)) {
   20030                         if (drawingWithRenderNode) {
   20031                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
   20032                         } else if (layerType == LAYER_TYPE_NONE) {
   20033                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
   20034                                     multipliedAlpha);
   20035                         }
   20036                     } else {
   20037                         // Alpha is handled by the child directly, clobber the layer's alpha
   20038                         mPrivateFlags |= PFLAG_ALPHA_SET;
   20039                     }
   20040                 }
   20041             }
   20042         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   20043             onSetAlpha(255);
   20044             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   20045         }
   20046 
   20047         if (!drawingWithRenderNode) {
   20048             // apply clips directly, since RenderNode won't do it for this draw
   20049             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
   20050                 if (offsetForScroll) {
   20051                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
   20052                 } else {
   20053                     if (!scalingRequired || cache == null) {
   20054                         canvas.clipRect(0, 0, getWidth(), getHeight());
   20055                     } else {
   20056                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
   20057                     }
   20058                 }
   20059             }
   20060 
   20061             if (mClipBounds != null) {
   20062                 // clip bounds ignore scroll
   20063                 canvas.clipRect(mClipBounds);
   20064             }
   20065         }
   20066 
   20067         if (!drawingWithDrawingCache) {
   20068             if (drawingWithRenderNode) {
   20069                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   20070                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
   20071             } else {
   20072                 // Fast path for layouts with no backgrounds
   20073                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   20074                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   20075                     dispatchDraw(canvas);
   20076                 } else {
   20077                     draw(canvas);
   20078                 }
   20079             }
   20080         } else if (cache != null) {
   20081             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   20082             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
   20083                 // no layer paint, use temporary paint to draw bitmap
   20084                 Paint cachePaint = parent.mCachePaint;
   20085                 if (cachePaint == null) {
   20086                     cachePaint = new Paint();
   20087                     cachePaint.setDither(false);
   20088                     parent.mCachePaint = cachePaint;
   20089                 }
   20090                 cachePaint.setAlpha((int) (alpha * 255));
   20091                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
   20092             } else {
   20093                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
   20094                 int layerPaintAlpha = mLayerPaint.getAlpha();
   20095                 if (alpha < 1) {
   20096                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
   20097                 }
   20098                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
   20099                 if (alpha < 1) {
   20100                     mLayerPaint.setAlpha(layerPaintAlpha);
   20101                 }
   20102             }
   20103         }
   20104 
   20105         if (restoreTo >= 0) {
   20106             canvas.restoreToCount(restoreTo);
   20107         }
   20108 
   20109         if (a != null && !more) {
   20110             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
   20111                 onSetAlpha(255);
   20112             }
   20113             parent.finishAnimatingView(this, a);
   20114         }
   20115 
   20116         if (more && hardwareAcceleratedCanvas) {
   20117             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   20118                 // alpha animations should cause the child to recreate its display list
   20119                 invalidate(true);
   20120             }
   20121         }
   20122 
   20123         mRecreateDisplayList = false;
   20124 
   20125         return more;
   20126     }
   20127 
   20128     static Paint getDebugPaint() {
   20129         if (sDebugPaint == null) {
   20130             sDebugPaint = new Paint();
   20131             sDebugPaint.setAntiAlias(false);
   20132         }
   20133         return sDebugPaint;
   20134     }
   20135 
   20136     final int dipsToPixels(int dips) {
   20137         float scale = getContext().getResources().getDisplayMetrics().density;
   20138         return (int) (dips * scale + 0.5f);
   20139     }
   20140 
   20141     final private void debugDrawFocus(Canvas canvas) {
   20142         if (isFocused()) {
   20143             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
   20144             final int l = mScrollX;
   20145             final int r = l + mRight - mLeft;
   20146             final int t = mScrollY;
   20147             final int b = t + mBottom - mTop;
   20148 
   20149             final Paint paint = getDebugPaint();
   20150             paint.setColor(DEBUG_CORNERS_COLOR);
   20151 
   20152             // Draw squares in corners.
   20153             paint.setStyle(Paint.Style.FILL);
   20154             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
   20155             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
   20156             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
   20157             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
   20158 
   20159             // Draw big X across the view.
   20160             paint.setStyle(Paint.Style.STROKE);
   20161             canvas.drawLine(l, t, r, b, paint);
   20162             canvas.drawLine(l, b, r, t, paint);
   20163         }
   20164     }
   20165 
   20166     /**
   20167      * Manually render this view (and all of its children) to the given Canvas.
   20168      * The view must have already done a full layout before this function is
   20169      * called.  When implementing a view, implement
   20170      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
   20171      * If you do need to override this method, call the superclass version.
   20172      *
   20173      * @param canvas The Canvas to which the View is rendered.
   20174      */
   20175     @CallSuper
   20176     public void draw(Canvas canvas) {
   20177         final int privateFlags = mPrivateFlags;
   20178         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
   20179                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
   20180         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
   20181 
   20182         /*
   20183          * Draw traversal performs several drawing steps which must be executed
   20184          * in the appropriate order:
   20185          *
   20186          *      1. Draw the background
   20187          *      2. If necessary, save the canvas' layers to prepare for fading
   20188          *      3. Draw view's content
   20189          *      4. Draw children
   20190          *      5. If necessary, draw the fading edges and restore layers
   20191          *      6. Draw decorations (scrollbars for instance)
   20192          */
   20193 
   20194         // Step 1, draw the background, if needed
   20195         int saveCount;
   20196 
   20197         if (!dirtyOpaque) {
   20198             drawBackground(canvas);
   20199         }
   20200 
   20201         // skip step 2 & 5 if possible (common case)
   20202         final int viewFlags = mViewFlags;
   20203         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
   20204         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
   20205         if (!verticalEdges && !horizontalEdges) {
   20206             // Step 3, draw the content
   20207             if (!dirtyOpaque) onDraw(canvas);
   20208 
   20209             // Step 4, draw the children
   20210             dispatchDraw(canvas);
   20211 
   20212             drawAutofilledHighlight(canvas);
   20213 
   20214             // Overlay is part of the content and draws beneath Foreground
   20215             if (mOverlay != null && !mOverlay.isEmpty()) {
   20216                 mOverlay.getOverlayView().dispatchDraw(canvas);
   20217             }
   20218 
   20219             // Step 6, draw decorations (foreground, scrollbars)
   20220             onDrawForeground(canvas);
   20221 
   20222             // Step 7, draw the default focus highlight
   20223             drawDefaultFocusHighlight(canvas);
   20224 
   20225             if (debugDraw()) {
   20226                 debugDrawFocus(canvas);
   20227             }
   20228 
   20229             // we're done...
   20230             return;
   20231         }
   20232 
   20233         /*
   20234          * Here we do the full fledged routine...
   20235          * (this is an uncommon case where speed matters less,
   20236          * this is why we repeat some of the tests that have been
   20237          * done above)
   20238          */
   20239 
   20240         boolean drawTop = false;
   20241         boolean drawBottom = false;
   20242         boolean drawLeft = false;
   20243         boolean drawRight = false;
   20244 
   20245         float topFadeStrength = 0.0f;
   20246         float bottomFadeStrength = 0.0f;
   20247         float leftFadeStrength = 0.0f;
   20248         float rightFadeStrength = 0.0f;
   20249 
   20250         // Step 2, save the canvas' layers
   20251         int paddingLeft = mPaddingLeft;
   20252 
   20253         final boolean offsetRequired = isPaddingOffsetRequired();
   20254         if (offsetRequired) {
   20255             paddingLeft += getLeftPaddingOffset();
   20256         }
   20257 
   20258         int left = mScrollX + paddingLeft;
   20259         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
   20260         int top = mScrollY + getFadeTop(offsetRequired);
   20261         int bottom = top + getFadeHeight(offsetRequired);
   20262 
   20263         if (offsetRequired) {
   20264             right += getRightPaddingOffset();
   20265             bottom += getBottomPaddingOffset();
   20266         }
   20267 
   20268         final ScrollabilityCache scrollabilityCache = mScrollCache;
   20269         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
   20270         int length = (int) fadeHeight;
   20271 
   20272         // clip the fade length if top and bottom fades overlap
   20273         // overlapping fades produce odd-looking artifacts
   20274         if (verticalEdges && (top + length > bottom - length)) {
   20275             length = (bottom - top) / 2;
   20276         }
   20277 
   20278         // also clip horizontal fades if necessary
   20279         if (horizontalEdges && (left + length > right - length)) {
   20280             length = (right - left) / 2;
   20281         }
   20282 
   20283         if (verticalEdges) {
   20284             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
   20285             drawTop = topFadeStrength * fadeHeight > 1.0f;
   20286             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
   20287             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
   20288         }
   20289 
   20290         if (horizontalEdges) {
   20291             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
   20292             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
   20293             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
   20294             drawRight = rightFadeStrength * fadeHeight > 1.0f;
   20295         }
   20296 
   20297         saveCount = canvas.getSaveCount();
   20298 
   20299         int solidColor = getSolidColor();
   20300         if (solidColor == 0) {
   20301             if (drawTop) {
   20302                 canvas.saveUnclippedLayer(left, top, right, top + length);
   20303             }
   20304 
   20305             if (drawBottom) {
   20306                 canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
   20307             }
   20308 
   20309             if (drawLeft) {
   20310                 canvas.saveUnclippedLayer(left, top, left + length, bottom);
   20311             }
   20312 
   20313             if (drawRight) {
   20314                 canvas.saveUnclippedLayer(right - length, top, right, bottom);
   20315             }
   20316         } else {
   20317             scrollabilityCache.setFadeColor(solidColor);
   20318         }
   20319 
   20320         // Step 3, draw the content
   20321         if (!dirtyOpaque) onDraw(canvas);
   20322 
   20323         // Step 4, draw the children
   20324         dispatchDraw(canvas);
   20325 
   20326         // Step 5, draw the fade effect and restore layers
   20327         final Paint p = scrollabilityCache.paint;
   20328         final Matrix matrix = scrollabilityCache.matrix;
   20329         final Shader fade = scrollabilityCache.shader;
   20330 
   20331         if (drawTop) {
   20332             matrix.setScale(1, fadeHeight * topFadeStrength);
   20333             matrix.postTranslate(left, top);
   20334             fade.setLocalMatrix(matrix);
   20335             p.setShader(fade);
   20336             canvas.drawRect(left, top, right, top + length, p);
   20337         }
   20338 
   20339         if (drawBottom) {
   20340             matrix.setScale(1, fadeHeight * bottomFadeStrength);
   20341             matrix.postRotate(180);
   20342             matrix.postTranslate(left, bottom);
   20343             fade.setLocalMatrix(matrix);
   20344             p.setShader(fade);
   20345             canvas.drawRect(left, bottom - length, right, bottom, p);
   20346         }
   20347 
   20348         if (drawLeft) {
   20349             matrix.setScale(1, fadeHeight * leftFadeStrength);
   20350             matrix.postRotate(-90);
   20351             matrix.postTranslate(left, top);
   20352             fade.setLocalMatrix(matrix);
   20353             p.setShader(fade);
   20354             canvas.drawRect(left, top, left + length, bottom, p);
   20355         }
   20356 
   20357         if (drawRight) {
   20358             matrix.setScale(1, fadeHeight * rightFadeStrength);
   20359             matrix.postRotate(90);
   20360             matrix.postTranslate(right, top);
   20361             fade.setLocalMatrix(matrix);
   20362             p.setShader(fade);
   20363             canvas.drawRect(right - length, top, right, bottom, p);
   20364         }
   20365 
   20366         canvas.restoreToCount(saveCount);
   20367 
   20368         drawAutofilledHighlight(canvas);
   20369 
   20370         // Overlay is part of the content and draws beneath Foreground
   20371         if (mOverlay != null && !mOverlay.isEmpty()) {
   20372             mOverlay.getOverlayView().dispatchDraw(canvas);
   20373         }
   20374 
   20375         // Step 6, draw decorations (foreground, scrollbars)
   20376         onDrawForeground(canvas);
   20377 
   20378         if (debugDraw()) {
   20379             debugDrawFocus(canvas);
   20380         }
   20381     }
   20382 
   20383     /**
   20384      * Draws the background onto the specified canvas.
   20385      *
   20386      * @param canvas Canvas on which to draw the background
   20387      */
   20388     private void drawBackground(Canvas canvas) {
   20389         final Drawable background = mBackground;
   20390         if (background == null) {
   20391             return;
   20392         }
   20393 
   20394         setBackgroundBounds();
   20395 
   20396         // Attempt to use a display list if requested.
   20397         if (canvas.isHardwareAccelerated() && mAttachInfo != null
   20398                 && mAttachInfo.mThreadedRenderer != null) {
   20399             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
   20400 
   20401             final RenderNode renderNode = mBackgroundRenderNode;
   20402             if (renderNode != null && renderNode.isValid()) {
   20403                 setBackgroundRenderNodeProperties(renderNode);
   20404                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
   20405                 return;
   20406             }
   20407         }
   20408 
   20409         final int scrollX = mScrollX;
   20410         final int scrollY = mScrollY;
   20411         if ((scrollX | scrollY) == 0) {
   20412             background.draw(canvas);
   20413         } else {
   20414             canvas.translate(scrollX, scrollY);
   20415             background.draw(canvas);
   20416             canvas.translate(-scrollX, -scrollY);
   20417         }
   20418     }
   20419 
   20420     /**
   20421      * Sets the correct background bounds and rebuilds the outline, if needed.
   20422      * <p/>
   20423      * This is called by LayoutLib.
   20424      */
   20425     void setBackgroundBounds() {
   20426         if (mBackgroundSizeChanged && mBackground != null) {
   20427             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
   20428             mBackgroundSizeChanged = false;
   20429             rebuildOutline();
   20430         }
   20431     }
   20432 
   20433     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
   20434         renderNode.setTranslationX(mScrollX);
   20435         renderNode.setTranslationY(mScrollY);
   20436     }
   20437 
   20438     /**
   20439      * Creates a new display list or updates the existing display list for the
   20440      * specified Drawable.
   20441      *
   20442      * @param drawable Drawable for which to create a display list
   20443      * @param renderNode Existing RenderNode, or {@code null}
   20444      * @return A valid display list for the specified drawable
   20445      */
   20446     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
   20447         if (renderNode == null) {
   20448             renderNode = RenderNode.create(drawable.getClass().getName(), this);
   20449         }
   20450 
   20451         final Rect bounds = drawable.getBounds();
   20452         final int width = bounds.width();
   20453         final int height = bounds.height();
   20454         final DisplayListCanvas canvas = renderNode.start(width, height);
   20455 
   20456         // Reverse left/top translation done by drawable canvas, which will
   20457         // instead be applied by rendernode's LTRB bounds below. This way, the
   20458         // drawable's bounds match with its rendernode bounds and its content
   20459         // will lie within those bounds in the rendernode tree.
   20460         canvas.translate(-bounds.left, -bounds.top);
   20461 
   20462         try {
   20463             drawable.draw(canvas);
   20464         } finally {
   20465             renderNode.end(canvas);
   20466         }
   20467 
   20468         // Set up drawable properties that are view-independent.
   20469         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
   20470         renderNode.setProjectBackwards(drawable.isProjected());
   20471         renderNode.setProjectionReceiver(true);
   20472         renderNode.setClipToBounds(false);
   20473         return renderNode;
   20474     }
   20475 
   20476     /**
   20477      * Returns the overlay for this view, creating it if it does not yet exist.
   20478      * Adding drawables to the overlay will cause them to be displayed whenever
   20479      * the view itself is redrawn. Objects in the overlay should be actively
   20480      * managed: remove them when they should not be displayed anymore. The
   20481      * overlay will always have the same size as its host view.
   20482      *
   20483      * <p>Note: Overlays do not currently work correctly with {@link
   20484      * SurfaceView} or {@link TextureView}; contents in overlays for these
   20485      * types of views may not display correctly.</p>
   20486      *
   20487      * @return The ViewOverlay object for this view.
   20488      * @see ViewOverlay
   20489      */
   20490     public ViewOverlay getOverlay() {
   20491         if (mOverlay == null) {
   20492             mOverlay = new ViewOverlay(mContext, this);
   20493         }
   20494         return mOverlay;
   20495     }
   20496 
   20497     /**
   20498      * Override this if your view is known to always be drawn on top of a solid color background,
   20499      * and needs to draw fading edges. Returning a non-zero color enables the view system to
   20500      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
   20501      * should be set to 0xFF.
   20502      *
   20503      * @see #setVerticalFadingEdgeEnabled(boolean)
   20504      * @see #setHorizontalFadingEdgeEnabled(boolean)
   20505      *
   20506      * @return The known solid color background for this view, or 0 if the color may vary
   20507      */
   20508     @ViewDebug.ExportedProperty(category = "drawing")
   20509     @ColorInt
   20510     public int getSolidColor() {
   20511         return 0;
   20512     }
   20513 
   20514     /**
   20515      * Build a human readable string representation of the specified view flags.
   20516      *
   20517      * @param flags the view flags to convert to a string
   20518      * @return a String representing the supplied flags
   20519      */
   20520     private static String printFlags(int flags) {
   20521         String output = "";
   20522         int numFlags = 0;
   20523         if ((flags & FOCUSABLE) == FOCUSABLE) {
   20524             output += "TAKES_FOCUS";
   20525             numFlags++;
   20526         }
   20527 
   20528         switch (flags & VISIBILITY_MASK) {
   20529         case INVISIBLE:
   20530             if (numFlags > 0) {
   20531                 output += " ";
   20532             }
   20533             output += "INVISIBLE";
   20534             // USELESS HERE numFlags++;
   20535             break;
   20536         case GONE:
   20537             if (numFlags > 0) {
   20538                 output += " ";
   20539             }
   20540             output += "GONE";
   20541             // USELESS HERE numFlags++;
   20542             break;
   20543         default:
   20544             break;
   20545         }
   20546         return output;
   20547     }
   20548 
   20549     /**
   20550      * Build a human readable string representation of the specified private
   20551      * view flags.
   20552      *
   20553      * @param privateFlags the private view flags to convert to a string
   20554      * @return a String representing the supplied flags
   20555      */
   20556     private static String printPrivateFlags(int privateFlags) {
   20557         String output = "";
   20558         int numFlags = 0;
   20559 
   20560         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
   20561             output += "WANTS_FOCUS";
   20562             numFlags++;
   20563         }
   20564 
   20565         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
   20566             if (numFlags > 0) {
   20567                 output += " ";
   20568             }
   20569             output += "FOCUSED";
   20570             numFlags++;
   20571         }
   20572 
   20573         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
   20574             if (numFlags > 0) {
   20575                 output += " ";
   20576             }
   20577             output += "SELECTED";
   20578             numFlags++;
   20579         }
   20580 
   20581         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
   20582             if (numFlags > 0) {
   20583                 output += " ";
   20584             }
   20585             output += "IS_ROOT_NAMESPACE";
   20586             numFlags++;
   20587         }
   20588 
   20589         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
   20590             if (numFlags > 0) {
   20591                 output += " ";
   20592             }
   20593             output += "HAS_BOUNDS";
   20594             numFlags++;
   20595         }
   20596 
   20597         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
   20598             if (numFlags > 0) {
   20599                 output += " ";
   20600             }
   20601             output += "DRAWN";
   20602             // USELESS HERE numFlags++;
   20603         }
   20604         return output;
   20605     }
   20606 
   20607     /**
   20608      * <p>Indicates whether or not this view's layout will be requested during
   20609      * the next hierarchy layout pass.</p>
   20610      *
   20611      * @return true if the layout will be forced during next layout pass
   20612      */
   20613     public boolean isLayoutRequested() {
   20614         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   20615     }
   20616 
   20617     /**
   20618      * Return true if o is a ViewGroup that is laying out using optical bounds.
   20619      * @hide
   20620      */
   20621     public static boolean isLayoutModeOptical(Object o) {
   20622         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
   20623     }
   20624 
   20625     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
   20626         Insets parentInsets = mParent instanceof View ?
   20627                 ((View) mParent).getOpticalInsets() : Insets.NONE;
   20628         Insets childInsets = getOpticalInsets();
   20629         return setFrame(
   20630                 left   + parentInsets.left - childInsets.left,
   20631                 top    + parentInsets.top  - childInsets.top,
   20632                 right  + parentInsets.left + childInsets.right,
   20633                 bottom + parentInsets.top  + childInsets.bottom);
   20634     }
   20635 
   20636     /**
   20637      * Assign a size and position to a view and all of its
   20638      * descendants
   20639      *
   20640      * <p>This is the second phase of the layout mechanism.
   20641      * (The first is measuring). In this phase, each parent calls
   20642      * layout on all of its children to position them.
   20643      * This is typically done using the child measurements
   20644      * that were stored in the measure pass().</p>
   20645      *
   20646      * <p>Derived classes should not override this method.
   20647      * Derived classes with children should override
   20648      * onLayout. In that method, they should
   20649      * call layout on each of their children.</p>
   20650      *
   20651      * @param l Left position, relative to parent
   20652      * @param t Top position, relative to parent
   20653      * @param r Right position, relative to parent
   20654      * @param b Bottom position, relative to parent
   20655      */
   20656     @SuppressWarnings({"unchecked"})
   20657     public void layout(int l, int t, int r, int b) {
   20658         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
   20659             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
   20660             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   20661         }
   20662 
   20663         int oldL = mLeft;
   20664         int oldT = mTop;
   20665         int oldB = mBottom;
   20666         int oldR = mRight;
   20667 
   20668         boolean changed = isLayoutModeOptical(mParent) ?
   20669                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
   20670 
   20671         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
   20672             onLayout(changed, l, t, r, b);
   20673 
   20674             if (shouldDrawRoundScrollbar()) {
   20675                 if(mRoundScrollbarRenderer == null) {
   20676                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
   20677                 }
   20678             } else {
   20679                 mRoundScrollbarRenderer = null;
   20680             }
   20681 
   20682             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
   20683 
   20684             ListenerInfo li = mListenerInfo;
   20685             if (li != null && li.mOnLayoutChangeListeners != null) {
   20686                 ArrayList<OnLayoutChangeListener> listenersCopy =
   20687                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
   20688                 int numListeners = listenersCopy.size();
   20689                 for (int i = 0; i < numListeners; ++i) {
   20690                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
   20691                 }
   20692             }
   20693         }
   20694 
   20695         final boolean wasLayoutValid = isLayoutValid();
   20696 
   20697         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
   20698         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
   20699 
   20700         if (!wasLayoutValid && isFocused()) {
   20701             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
   20702             if (canTakeFocus()) {
   20703                 // We have a robust focus, so parents should no longer be wanting focus.
   20704                 clearParentsWantFocus();
   20705             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
   20706                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
   20707                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
   20708                 // and thus the safest action is to clear focus here.
   20709                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
   20710                 clearParentsWantFocus();
   20711             } else if (!hasParentWantsFocus()) {
   20712                 // original requestFocus was likely on this view directly, so just clear focus
   20713                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
   20714             }
   20715             // otherwise, we let parents handle re-assigning focus during their layout passes.
   20716         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
   20717             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
   20718             View focused = findFocus();
   20719             if (focused != null) {
   20720                 // Try to restore focus as close as possible to our starting focus.
   20721                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
   20722                     // Give up and clear focus once we've reached the top-most parent which wants
   20723                     // focus.
   20724                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
   20725                 }
   20726             }
   20727         }
   20728 
   20729         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
   20730             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
   20731             notifyEnterOrExitForAutoFillIfNeeded(true);
   20732         }
   20733     }
   20734 
   20735     private boolean hasParentWantsFocus() {
   20736         ViewParent parent = mParent;
   20737         while (parent instanceof ViewGroup) {
   20738             ViewGroup pv = (ViewGroup) parent;
   20739             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
   20740                 return true;
   20741             }
   20742             parent = pv.mParent;
   20743         }
   20744         return false;
   20745     }
   20746 
   20747     /**
   20748      * Called from layout when this view should
   20749      * assign a size and position to each of its children.
   20750      *
   20751      * Derived classes with children should override
   20752      * this method and call layout on each of
   20753      * their children.
   20754      * @param changed This is a new size or position for this view
   20755      * @param left Left position, relative to parent
   20756      * @param top Top position, relative to parent
   20757      * @param right Right position, relative to parent
   20758      * @param bottom Bottom position, relative to parent
   20759      */
   20760     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   20761     }
   20762 
   20763     /**
   20764      * Assign a size and position to this view.
   20765      *
   20766      * This is called from layout.
   20767      *
   20768      * @param left Left position, relative to parent
   20769      * @param top Top position, relative to parent
   20770      * @param right Right position, relative to parent
   20771      * @param bottom Bottom position, relative to parent
   20772      * @return true if the new size and position are different than the
   20773      *         previous ones
   20774      * {@hide}
   20775      */
   20776     protected boolean setFrame(int left, int top, int right, int bottom) {
   20777         boolean changed = false;
   20778 
   20779         if (DBG) {
   20780             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
   20781                     + right + "," + bottom + ")");
   20782         }
   20783 
   20784         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
   20785             changed = true;
   20786 
   20787             // Remember our drawn bit
   20788             int drawn = mPrivateFlags & PFLAG_DRAWN;
   20789 
   20790             int oldWidth = mRight - mLeft;
   20791             int oldHeight = mBottom - mTop;
   20792             int newWidth = right - left;
   20793             int newHeight = bottom - top;
   20794             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
   20795 
   20796             // Invalidate our old position
   20797             invalidate(sizeChanged);
   20798 
   20799             mLeft = left;
   20800             mTop = top;
   20801             mRight = right;
   20802             mBottom = bottom;
   20803             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
   20804 
   20805             mPrivateFlags |= PFLAG_HAS_BOUNDS;
   20806 
   20807 
   20808             if (sizeChanged) {
   20809                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
   20810             }
   20811 
   20812             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
   20813                 // If we are visible, force the DRAWN bit to on so that
   20814                 // this invalidate will go through (at least to our parent).
   20815                 // This is because someone may have invalidated this view
   20816                 // before this call to setFrame came in, thereby clearing
   20817                 // the DRAWN bit.
   20818                 mPrivateFlags |= PFLAG_DRAWN;
   20819                 invalidate(sizeChanged);
   20820                 // parent display list may need to be recreated based on a change in the bounds
   20821                 // of any child
   20822                 invalidateParentCaches();
   20823             }
   20824 
   20825             // Reset drawn bit to original value (invalidate turns it off)
   20826             mPrivateFlags |= drawn;
   20827 
   20828             mBackgroundSizeChanged = true;
   20829             mDefaultFocusHighlightSizeChanged = true;
   20830             if (mForegroundInfo != null) {
   20831                 mForegroundInfo.mBoundsChanged = true;
   20832             }
   20833 
   20834             notifySubtreeAccessibilityStateChangedIfNeeded();
   20835         }
   20836         return changed;
   20837     }
   20838 
   20839     /**
   20840      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
   20841      * @hide
   20842      */
   20843     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
   20844         setFrame(left, top, right, bottom);
   20845     }
   20846 
   20847     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
   20848         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
   20849         if (mOverlay != null) {
   20850             mOverlay.getOverlayView().setRight(newWidth);
   20851             mOverlay.getOverlayView().setBottom(newHeight);
   20852         }
   20853         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
   20854         // backtracking" of requestFocus during layout, so don't touch focus here.
   20855         if (!sCanFocusZeroSized && isLayoutValid()
   20856                 // Don't touch focus if animating
   20857                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
   20858             if (newWidth <= 0 || newHeight <= 0) {
   20859                 if (hasFocus()) {
   20860                     clearFocus();
   20861                     if (mParent instanceof ViewGroup) {
   20862                         ((ViewGroup) mParent).clearFocusedInCluster();
   20863                     }
   20864                 }
   20865                 clearAccessibilityFocus();
   20866             } else if (oldWidth <= 0 || oldHeight <= 0) {
   20867                 if (mParent != null && canTakeFocus()) {
   20868                     mParent.focusableViewAvailable(this);
   20869                 }
   20870             }
   20871         }
   20872         rebuildOutline();
   20873     }
   20874 
   20875     /**
   20876      * Finalize inflating a view from XML.  This is called as the last phase
   20877      * of inflation, after all child views have been added.
   20878      *
   20879      * <p>Even if the subclass overrides onFinishInflate, they should always be
   20880      * sure to call the super method, so that we get called.
   20881      */
   20882     @CallSuper
   20883     protected void onFinishInflate() {
   20884     }
   20885 
   20886     /**
   20887      * Returns the resources associated with this view.
   20888      *
   20889      * @return Resources object.
   20890      */
   20891     public Resources getResources() {
   20892         return mResources;
   20893     }
   20894 
   20895     /**
   20896      * Invalidates the specified Drawable.
   20897      *
   20898      * @param drawable the drawable to invalidate
   20899      */
   20900     @Override
   20901     public void invalidateDrawable(@NonNull Drawable drawable) {
   20902         if (verifyDrawable(drawable)) {
   20903             final Rect dirty = drawable.getDirtyBounds();
   20904             final int scrollX = mScrollX;
   20905             final int scrollY = mScrollY;
   20906 
   20907             invalidate(dirty.left + scrollX, dirty.top + scrollY,
   20908                     dirty.right + scrollX, dirty.bottom + scrollY);
   20909             rebuildOutline();
   20910         }
   20911     }
   20912 
   20913     /**
   20914      * Schedules an action on a drawable to occur at a specified time.
   20915      *
   20916      * @param who the recipient of the action
   20917      * @param what the action to run on the drawable
   20918      * @param when the time at which the action must occur. Uses the
   20919      *        {@link SystemClock#uptimeMillis} timebase.
   20920      */
   20921     @Override
   20922     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
   20923         if (verifyDrawable(who) && what != null) {
   20924             final long delay = when - SystemClock.uptimeMillis();
   20925             if (mAttachInfo != null) {
   20926                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   20927                         Choreographer.CALLBACK_ANIMATION, what, who,
   20928                         Choreographer.subtractFrameDelay(delay));
   20929             } else {
   20930                 // Postpone the runnable until we know
   20931                 // on which thread it needs to run.
   20932                 getRunQueue().postDelayed(what, delay);
   20933             }
   20934         }
   20935     }
   20936 
   20937     /**
   20938      * Cancels a scheduled action on a drawable.
   20939      *
   20940      * @param who the recipient of the action
   20941      * @param what the action to cancel
   20942      */
   20943     @Override
   20944     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
   20945         if (verifyDrawable(who) && what != null) {
   20946             if (mAttachInfo != null) {
   20947                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   20948                         Choreographer.CALLBACK_ANIMATION, what, who);
   20949             }
   20950             getRunQueue().removeCallbacks(what);
   20951         }
   20952     }
   20953 
   20954     /**
   20955      * Unschedule any events associated with the given Drawable.  This can be
   20956      * used when selecting a new Drawable into a view, so that the previous
   20957      * one is completely unscheduled.
   20958      *
   20959      * @param who The Drawable to unschedule.
   20960      *
   20961      * @see #drawableStateChanged
   20962      */
   20963     public void unscheduleDrawable(Drawable who) {
   20964         if (mAttachInfo != null && who != null) {
   20965             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   20966                     Choreographer.CALLBACK_ANIMATION, null, who);
   20967         }
   20968     }
   20969 
   20970     /**
   20971      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
   20972      * that the View directionality can and will be resolved before its Drawables.
   20973      *
   20974      * Will call {@link View#onResolveDrawables} when resolution is done.
   20975      *
   20976      * @hide
   20977      */
   20978     protected void resolveDrawables() {
   20979         // Drawables resolution may need to happen before resolving the layout direction (which is
   20980         // done only during the measure() call).
   20981         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
   20982         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
   20983         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
   20984         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
   20985         // direction to be resolved as its resolved value will be the same as its raw value.
   20986         if (!isLayoutDirectionResolved() &&
   20987                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
   20988             return;
   20989         }
   20990 
   20991         final int layoutDirection = isLayoutDirectionResolved() ?
   20992                 getLayoutDirection() : getRawLayoutDirection();
   20993 
   20994         if (mBackground != null) {
   20995             mBackground.setLayoutDirection(layoutDirection);
   20996         }
   20997         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   20998             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
   20999         }
   21000         if (mDefaultFocusHighlight != null) {
   21001             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
   21002         }
   21003         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
   21004         onResolveDrawables(layoutDirection);
   21005     }
   21006 
   21007     boolean areDrawablesResolved() {
   21008         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
   21009     }
   21010 
   21011     /**
   21012      * Called when layout direction has been resolved.
   21013      *
   21014      * The default implementation does nothing.
   21015      *
   21016      * @param layoutDirection The resolved layout direction.
   21017      *
   21018      * @see #LAYOUT_DIRECTION_LTR
   21019      * @see #LAYOUT_DIRECTION_RTL
   21020      *
   21021      * @hide
   21022      */
   21023     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
   21024     }
   21025 
   21026     /**
   21027      * @hide
   21028      */
   21029     protected void resetResolvedDrawables() {
   21030         resetResolvedDrawablesInternal();
   21031     }
   21032 
   21033     void resetResolvedDrawablesInternal() {
   21034         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
   21035     }
   21036 
   21037     /**
   21038      * If your view subclass is displaying its own Drawable objects, it should
   21039      * override this function and return true for any Drawable it is
   21040      * displaying.  This allows animations for those drawables to be
   21041      * scheduled.
   21042      *
   21043      * <p>Be sure to call through to the super class when overriding this
   21044      * function.
   21045      *
   21046      * @param who The Drawable to verify.  Return true if it is one you are
   21047      *            displaying, else return the result of calling through to the
   21048      *            super class.
   21049      *
   21050      * @return boolean If true than the Drawable is being displayed in the
   21051      *         view; else false and it is not allowed to animate.
   21052      *
   21053      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
   21054      * @see #drawableStateChanged()
   21055      */
   21056     @CallSuper
   21057     protected boolean verifyDrawable(@NonNull Drawable who) {
   21058         // Avoid verifying the scroll bar drawable so that we don't end up in
   21059         // an invalidation loop. This effectively prevents the scroll bar
   21060         // drawable from triggering invalidations and scheduling runnables.
   21061         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
   21062                 || (mDefaultFocusHighlight == who);
   21063     }
   21064 
   21065     /**
   21066      * This function is called whenever the state of the view changes in such
   21067      * a way that it impacts the state of drawables being shown.
   21068      * <p>
   21069      * If the View has a StateListAnimator, it will also be called to run necessary state
   21070      * change animations.
   21071      * <p>
   21072      * Be sure to call through to the superclass when overriding this function.
   21073      *
   21074      * @see Drawable#setState(int[])
   21075      */
   21076     @CallSuper
   21077     protected void drawableStateChanged() {
   21078         final int[] state = getDrawableState();
   21079         boolean changed = false;
   21080 
   21081         final Drawable bg = mBackground;
   21082         if (bg != null && bg.isStateful()) {
   21083             changed |= bg.setState(state);
   21084         }
   21085 
   21086         final Drawable hl = mDefaultFocusHighlight;
   21087         if (hl != null && hl.isStateful()) {
   21088             changed |= hl.setState(state);
   21089         }
   21090 
   21091         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   21092         if (fg != null && fg.isStateful()) {
   21093             changed |= fg.setState(state);
   21094         }
   21095 
   21096         if (mScrollCache != null) {
   21097             final Drawable scrollBar = mScrollCache.scrollBar;
   21098             if (scrollBar != null && scrollBar.isStateful()) {
   21099                 changed |= scrollBar.setState(state)
   21100                         && mScrollCache.state != ScrollabilityCache.OFF;
   21101             }
   21102         }
   21103 
   21104         if (mStateListAnimator != null) {
   21105             mStateListAnimator.setState(state);
   21106         }
   21107 
   21108         if (changed) {
   21109             invalidate();
   21110         }
   21111     }
   21112 
   21113     /**
   21114      * This function is called whenever the view hotspot changes and needs to
   21115      * be propagated to drawables or child views managed by the view.
   21116      * <p>
   21117      * Dispatching to child views is handled by
   21118      * {@link #dispatchDrawableHotspotChanged(float, float)}.
   21119      * <p>
   21120      * Be sure to call through to the superclass when overriding this function.
   21121      *
   21122      * @param x hotspot x coordinate
   21123      * @param y hotspot y coordinate
   21124      */
   21125     @CallSuper
   21126     public void drawableHotspotChanged(float x, float y) {
   21127         if (mBackground != null) {
   21128             mBackground.setHotspot(x, y);
   21129         }
   21130         if (mDefaultFocusHighlight != null) {
   21131             mDefaultFocusHighlight.setHotspot(x, y);
   21132         }
   21133         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   21134             mForegroundInfo.mDrawable.setHotspot(x, y);
   21135         }
   21136 
   21137         dispatchDrawableHotspotChanged(x, y);
   21138     }
   21139 
   21140     /**
   21141      * Dispatches drawableHotspotChanged to all of this View's children.
   21142      *
   21143      * @param x hotspot x coordinate
   21144      * @param y hotspot y coordinate
   21145      * @see #drawableHotspotChanged(float, float)
   21146      */
   21147     public void dispatchDrawableHotspotChanged(float x, float y) {
   21148     }
   21149 
   21150     /**
   21151      * Call this to force a view to update its drawable state. This will cause
   21152      * drawableStateChanged to be called on this view. Views that are interested
   21153      * in the new state should call getDrawableState.
   21154      *
   21155      * @see #drawableStateChanged
   21156      * @see #getDrawableState
   21157      */
   21158     public void refreshDrawableState() {
   21159         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   21160         drawableStateChanged();
   21161 
   21162         ViewParent parent = mParent;
   21163         if (parent != null) {
   21164             parent.childDrawableStateChanged(this);
   21165         }
   21166     }
   21167 
   21168     /**
   21169      * Create a default focus highlight if it doesn't exist.
   21170      * @return a default focus highlight.
   21171      */
   21172     private Drawable getDefaultFocusHighlightDrawable() {
   21173         if (mDefaultFocusHighlightCache == null) {
   21174             if (mContext != null) {
   21175                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
   21176                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
   21177                 mDefaultFocusHighlightCache = ta.getDrawable(0);
   21178                 ta.recycle();
   21179             }
   21180         }
   21181         return mDefaultFocusHighlightCache;
   21182     }
   21183 
   21184     /**
   21185      * Set the current default focus highlight.
   21186      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
   21187      */
   21188     private void setDefaultFocusHighlight(Drawable highlight) {
   21189         mDefaultFocusHighlight = highlight;
   21190         mDefaultFocusHighlightSizeChanged = true;
   21191         if (highlight != null) {
   21192             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   21193                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   21194             }
   21195             highlight.setLayoutDirection(getLayoutDirection());
   21196             if (highlight.isStateful()) {
   21197                 highlight.setState(getDrawableState());
   21198             }
   21199             if (isAttachedToWindow()) {
   21200                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   21201             }
   21202             // Set callback last, since the view may still be initializing.
   21203             highlight.setCallback(this);
   21204         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
   21205                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
   21206             mPrivateFlags |= PFLAG_SKIP_DRAW;
   21207         }
   21208         invalidate();
   21209     }
   21210 
   21211     /**
   21212      * Check whether we need to draw a default focus highlight when this view gets focused,
   21213      * which requires:
   21214      * <ul>
   21215      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
   21216      *         is not defined.</li>
   21217      *     <li>This view is not in touch mode.</li>
   21218      *     <li>This view doesn't opt out for a default focus highlight, via
   21219      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
   21220      *     <li>This view is attached to window.</li>
   21221      * </ul>
   21222      * @return {@code true} if a default focus highlight is needed.
   21223      * @hide
   21224      */
   21225     @TestApi
   21226     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
   21227         final boolean lackFocusState = (background == null || !background.isStateful()
   21228                 || !background.hasFocusStateSpecified())
   21229                 && (foreground == null || !foreground.isStateful()
   21230                 || !foreground.hasFocusStateSpecified());
   21231         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
   21232                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
   21233     }
   21234 
   21235     /**
   21236      * When this view is focused, switches on/off the default focused highlight.
   21237      * <p>
   21238      * This always happens when this view is focused, and only at this moment the default focus
   21239      * highlight can be visible.
   21240      */
   21241     private void switchDefaultFocusHighlight() {
   21242         if (isFocused()) {
   21243             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
   21244                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
   21245             final boolean active = mDefaultFocusHighlight != null;
   21246             if (needed && !active) {
   21247                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
   21248             } else if (!needed && active) {
   21249                 // The highlight is no longer needed, so tear it down.
   21250                 setDefaultFocusHighlight(null);
   21251             }
   21252         }
   21253     }
   21254 
   21255     /**
   21256      * Draw the default focus highlight onto the canvas.
   21257      * @param canvas the canvas where we're drawing the highlight.
   21258      */
   21259     private void drawDefaultFocusHighlight(Canvas canvas) {
   21260         if (mDefaultFocusHighlight != null) {
   21261             if (mDefaultFocusHighlightSizeChanged) {
   21262                 mDefaultFocusHighlightSizeChanged = false;
   21263                 final int l = mScrollX;
   21264                 final int r = l + mRight - mLeft;
   21265                 final int t = mScrollY;
   21266                 final int b = t + mBottom - mTop;
   21267                 mDefaultFocusHighlight.setBounds(l, t, r, b);
   21268             }
   21269             mDefaultFocusHighlight.draw(canvas);
   21270         }
   21271     }
   21272 
   21273     /**
   21274      * Return an array of resource IDs of the drawable states representing the
   21275      * current state of the view.
   21276      *
   21277      * @return The current drawable state
   21278      *
   21279      * @see Drawable#setState(int[])
   21280      * @see #drawableStateChanged()
   21281      * @see #onCreateDrawableState(int)
   21282      */
   21283     public final int[] getDrawableState() {
   21284         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
   21285             return mDrawableState;
   21286         } else {
   21287             mDrawableState = onCreateDrawableState(0);
   21288             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
   21289             return mDrawableState;
   21290         }
   21291     }
   21292 
   21293     /**
   21294      * Generate the new {@link android.graphics.drawable.Drawable} state for
   21295      * this view. This is called by the view
   21296      * system when the cached Drawable state is determined to be invalid.  To
   21297      * retrieve the current state, you should use {@link #getDrawableState}.
   21298      *
   21299      * @param extraSpace if non-zero, this is the number of extra entries you
   21300      * would like in the returned array in which you can place your own
   21301      * states.
   21302      *
   21303      * @return Returns an array holding the current {@link Drawable} state of
   21304      * the view.
   21305      *
   21306      * @see #mergeDrawableStates(int[], int[])
   21307      */
   21308     protected int[] onCreateDrawableState(int extraSpace) {
   21309         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
   21310                 mParent instanceof View) {
   21311             return ((View) mParent).onCreateDrawableState(extraSpace);
   21312         }
   21313 
   21314         int[] drawableState;
   21315 
   21316         int privateFlags = mPrivateFlags;
   21317 
   21318         int viewStateIndex = 0;
   21319         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
   21320         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
   21321         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
   21322         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
   21323         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
   21324         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
   21325         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
   21326                 ThreadedRenderer.isAvailable()) {
   21327             // This is set if HW acceleration is requested, even if the current
   21328             // process doesn't allow it.  This is just to allow app preview
   21329             // windows to better match their app.
   21330             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
   21331         }
   21332         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
   21333 
   21334         final int privateFlags2 = mPrivateFlags2;
   21335         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
   21336             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
   21337         }
   21338         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
   21339             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
   21340         }
   21341 
   21342         drawableState = StateSet.get(viewStateIndex);
   21343 
   21344         //noinspection ConstantIfStatement
   21345         if (false) {
   21346             Log.i("View", "drawableStateIndex=" + viewStateIndex);
   21347             Log.i("View", toString()
   21348                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
   21349                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
   21350                     + " fo=" + hasFocus()
   21351                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
   21352                     + " wf=" + hasWindowFocus()
   21353                     + ": " + Arrays.toString(drawableState));
   21354         }
   21355 
   21356         if (extraSpace == 0) {
   21357             return drawableState;
   21358         }
   21359 
   21360         final int[] fullState;
   21361         if (drawableState != null) {
   21362             fullState = new int[drawableState.length + extraSpace];
   21363             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
   21364         } else {
   21365             fullState = new int[extraSpace];
   21366         }
   21367 
   21368         return fullState;
   21369     }
   21370 
   21371     /**
   21372      * Merge your own state values in <var>additionalState</var> into the base
   21373      * state values <var>baseState</var> that were returned by
   21374      * {@link #onCreateDrawableState(int)}.
   21375      *
   21376      * @param baseState The base state values returned by
   21377      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
   21378      * own additional state values.
   21379      *
   21380      * @param additionalState The additional state values you would like
   21381      * added to <var>baseState</var>; this array is not modified.
   21382      *
   21383      * @return As a convenience, the <var>baseState</var> array you originally
   21384      * passed into the function is returned.
   21385      *
   21386      * @see #onCreateDrawableState(int)
   21387      */
   21388     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
   21389         final int N = baseState.length;
   21390         int i = N - 1;
   21391         while (i >= 0 && baseState[i] == 0) {
   21392             i--;
   21393         }
   21394         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
   21395         return baseState;
   21396     }
   21397 
   21398     /**
   21399      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
   21400      * on all Drawable objects associated with this view.
   21401      * <p>
   21402      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
   21403      * attached to this view.
   21404      */
   21405     @CallSuper
   21406     public void jumpDrawablesToCurrentState() {
   21407         if (mBackground != null) {
   21408             mBackground.jumpToCurrentState();
   21409         }
   21410         if (mStateListAnimator != null) {
   21411             mStateListAnimator.jumpToCurrentState();
   21412         }
   21413         if (mDefaultFocusHighlight != null) {
   21414             mDefaultFocusHighlight.jumpToCurrentState();
   21415         }
   21416         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   21417             mForegroundInfo.mDrawable.jumpToCurrentState();
   21418         }
   21419     }
   21420 
   21421     /**
   21422      * Sets the background color for this view.
   21423      * @param color the color of the background
   21424      */
   21425     @RemotableViewMethod
   21426     public void setBackgroundColor(@ColorInt int color) {
   21427         if (mBackground instanceof ColorDrawable) {
   21428             ((ColorDrawable) mBackground.mutate()).setColor(color);
   21429             computeOpaqueFlags();
   21430             mBackgroundResource = 0;
   21431         } else {
   21432             setBackground(new ColorDrawable(color));
   21433         }
   21434     }
   21435 
   21436     /**
   21437      * Set the background to a given resource. The resource should refer to
   21438      * a Drawable object or 0 to remove the background.
   21439      * @param resid The identifier of the resource.
   21440      *
   21441      * @attr ref android.R.styleable#View_background
   21442      */
   21443     @RemotableViewMethod
   21444     public void setBackgroundResource(@DrawableRes int resid) {
   21445         if (resid != 0 && resid == mBackgroundResource) {
   21446             return;
   21447         }
   21448 
   21449         Drawable d = null;
   21450         if (resid != 0) {
   21451             d = mContext.getDrawable(resid);
   21452         }
   21453         setBackground(d);
   21454 
   21455         mBackgroundResource = resid;
   21456     }
   21457 
   21458     /**
   21459      * Set the background to a given Drawable, or remove the background. If the
   21460      * background has padding, this View's padding is set to the background's
   21461      * padding. However, when a background is removed, this View's padding isn't
   21462      * touched. If setting the padding is desired, please use
   21463      * {@link #setPadding(int, int, int, int)}.
   21464      *
   21465      * @param background The Drawable to use as the background, or null to remove the
   21466      *        background
   21467      */
   21468     public void setBackground(Drawable background) {
   21469         //noinspection deprecation
   21470         setBackgroundDrawable(background);
   21471     }
   21472 
   21473     /**
   21474      * @deprecated use {@link #setBackground(Drawable)} instead
   21475      */
   21476     @Deprecated
   21477     public void setBackgroundDrawable(Drawable background) {
   21478         computeOpaqueFlags();
   21479 
   21480         if (background == mBackground) {
   21481             return;
   21482         }
   21483 
   21484         boolean requestLayout = false;
   21485 
   21486         mBackgroundResource = 0;
   21487 
   21488         /*
   21489          * Regardless of whether we're setting a new background or not, we want
   21490          * to clear the previous drawable. setVisible first while we still have the callback set.
   21491          */
   21492         if (mBackground != null) {
   21493             if (isAttachedToWindow()) {
   21494                 mBackground.setVisible(false, false);
   21495             }
   21496             mBackground.setCallback(null);
   21497             unscheduleDrawable(mBackground);
   21498         }
   21499 
   21500         if (background != null) {
   21501             Rect padding = sThreadLocal.get();
   21502             if (padding == null) {
   21503                 padding = new Rect();
   21504                 sThreadLocal.set(padding);
   21505             }
   21506             resetResolvedDrawablesInternal();
   21507             background.setLayoutDirection(getLayoutDirection());
   21508             if (background.getPadding(padding)) {
   21509                 resetResolvedPaddingInternal();
   21510                 switch (background.getLayoutDirection()) {
   21511                     case LAYOUT_DIRECTION_RTL:
   21512                         mUserPaddingLeftInitial = padding.right;
   21513                         mUserPaddingRightInitial = padding.left;
   21514                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
   21515                         break;
   21516                     case LAYOUT_DIRECTION_LTR:
   21517                     default:
   21518                         mUserPaddingLeftInitial = padding.left;
   21519                         mUserPaddingRightInitial = padding.right;
   21520                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
   21521                 }
   21522                 mLeftPaddingDefined = false;
   21523                 mRightPaddingDefined = false;
   21524             }
   21525 
   21526             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
   21527             // if it has a different minimum size, we should layout again
   21528             if (mBackground == null
   21529                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
   21530                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
   21531                 requestLayout = true;
   21532             }
   21533 
   21534             // Set mBackground before we set this as the callback and start making other
   21535             // background drawable state change calls. In particular, the setVisible call below
   21536             // can result in drawables attempting to start animations or otherwise invalidate,
   21537             // which requires the view set as the callback (us) to recognize the drawable as
   21538             // belonging to it as per verifyDrawable.
   21539             mBackground = background;
   21540             if (background.isStateful()) {
   21541                 background.setState(getDrawableState());
   21542             }
   21543             if (isAttachedToWindow()) {
   21544                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   21545             }
   21546 
   21547             applyBackgroundTint();
   21548 
   21549             // Set callback last, since the view may still be initializing.
   21550             background.setCallback(this);
   21551 
   21552             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   21553                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   21554                 requestLayout = true;
   21555             }
   21556         } else {
   21557             /* Remove the background */
   21558             mBackground = null;
   21559             if ((mViewFlags & WILL_NOT_DRAW) != 0
   21560                     && (mDefaultFocusHighlight == null)
   21561                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
   21562                 mPrivateFlags |= PFLAG_SKIP_DRAW;
   21563             }
   21564 
   21565             /*
   21566              * When the background is set, we try to apply its padding to this
   21567              * View. When the background is removed, we don't touch this View's
   21568              * padding. This is noted in the Javadocs. Hence, we don't need to
   21569              * requestLayout(), the invalidate() below is sufficient.
   21570              */
   21571 
   21572             // The old background's minimum size could have affected this
   21573             // View's layout, so let's requestLayout
   21574             requestLayout = true;
   21575         }
   21576 
   21577         computeOpaqueFlags();
   21578 
   21579         if (requestLayout) {
   21580             requestLayout();
   21581         }
   21582 
   21583         mBackgroundSizeChanged = true;
   21584         invalidate(true);
   21585         invalidateOutline();
   21586     }
   21587 
   21588     /**
   21589      * Gets the background drawable
   21590      *
   21591      * @return The drawable used as the background for this view, if any.
   21592      *
   21593      * @see #setBackground(Drawable)
   21594      *
   21595      * @attr ref android.R.styleable#View_background
   21596      */
   21597     public Drawable getBackground() {
   21598         return mBackground;
   21599     }
   21600 
   21601     /**
   21602      * Applies a tint to the background drawable. Does not modify the current tint
   21603      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   21604      * <p>
   21605      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
   21606      * mutate the drawable and apply the specified tint and tint mode using
   21607      * {@link Drawable#setTintList(ColorStateList)}.
   21608      *
   21609      * @param tint the tint to apply, may be {@code null} to clear tint
   21610      *
   21611      * @attr ref android.R.styleable#View_backgroundTint
   21612      * @see #getBackgroundTintList()
   21613      * @see Drawable#setTintList(ColorStateList)
   21614      */
   21615     public void setBackgroundTintList(@Nullable ColorStateList tint) {
   21616         if (mBackgroundTint == null) {
   21617             mBackgroundTint = new TintInfo();
   21618         }
   21619         mBackgroundTint.mTintList = tint;
   21620         mBackgroundTint.mHasTintList = true;
   21621 
   21622         applyBackgroundTint();
   21623     }
   21624 
   21625     /**
   21626      * Return the tint applied to the background drawable, if specified.
   21627      *
   21628      * @return the tint applied to the background drawable
   21629      * @attr ref android.R.styleable#View_backgroundTint
   21630      * @see #setBackgroundTintList(ColorStateList)
   21631      */
   21632     @Nullable
   21633     public ColorStateList getBackgroundTintList() {
   21634         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
   21635     }
   21636 
   21637     /**
   21638      * Specifies the blending mode used to apply the tint specified by
   21639      * {@link #setBackgroundTintList(ColorStateList)}} to the background
   21640      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   21641      *
   21642      * @param tintMode the blending mode used to apply the tint, may be
   21643      *                 {@code null} to clear tint
   21644      * @attr ref android.R.styleable#View_backgroundTintMode
   21645      * @see #getBackgroundTintMode()
   21646      * @see Drawable#setTintMode(PorterDuff.Mode)
   21647      */
   21648     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   21649         if (mBackgroundTint == null) {
   21650             mBackgroundTint = new TintInfo();
   21651         }
   21652         mBackgroundTint.mTintMode = tintMode;
   21653         mBackgroundTint.mHasTintMode = true;
   21654 
   21655         applyBackgroundTint();
   21656     }
   21657 
   21658     /**
   21659      * Return the blending mode used to apply the tint to the background
   21660      * drawable, if specified.
   21661      *
   21662      * @return the blending mode used to apply the tint to the background
   21663      *         drawable
   21664      * @attr ref android.R.styleable#View_backgroundTintMode
   21665      * @see #setBackgroundTintMode(PorterDuff.Mode)
   21666      */
   21667     @Nullable
   21668     public PorterDuff.Mode getBackgroundTintMode() {
   21669         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
   21670     }
   21671 
   21672     private void applyBackgroundTint() {
   21673         if (mBackground != null && mBackgroundTint != null) {
   21674             final TintInfo tintInfo = mBackgroundTint;
   21675             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   21676                 mBackground = mBackground.mutate();
   21677 
   21678                 if (tintInfo.mHasTintList) {
   21679                     mBackground.setTintList(tintInfo.mTintList);
   21680                 }
   21681 
   21682                 if (tintInfo.mHasTintMode) {
   21683                     mBackground.setTintMode(tintInfo.mTintMode);
   21684                 }
   21685 
   21686                 // The drawable (or one of its children) may not have been
   21687                 // stateful before applying the tint, so let's try again.
   21688                 if (mBackground.isStateful()) {
   21689                     mBackground.setState(getDrawableState());
   21690                 }
   21691             }
   21692         }
   21693     }
   21694 
   21695     /**
   21696      * Returns the drawable used as the foreground of this View. The
   21697      * foreground drawable, if non-null, is always drawn on top of the view's content.
   21698      *
   21699      * @return a Drawable or null if no foreground was set
   21700      *
   21701      * @see #onDrawForeground(Canvas)
   21702      */
   21703     public Drawable getForeground() {
   21704         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   21705     }
   21706 
   21707     /**
   21708      * Supply a Drawable that is to be rendered on top of all of the content in the view.
   21709      *
   21710      * @param foreground the Drawable to be drawn on top of the children
   21711      *
   21712      * @attr ref android.R.styleable#View_foreground
   21713      */
   21714     public void setForeground(Drawable foreground) {
   21715         if (mForegroundInfo == null) {
   21716             if (foreground == null) {
   21717                 // Nothing to do.
   21718                 return;
   21719             }
   21720             mForegroundInfo = new ForegroundInfo();
   21721         }
   21722 
   21723         if (foreground == mForegroundInfo.mDrawable) {
   21724             // Nothing to do
   21725             return;
   21726         }
   21727 
   21728         if (mForegroundInfo.mDrawable != null) {
   21729             if (isAttachedToWindow()) {
   21730                 mForegroundInfo.mDrawable.setVisible(false, false);
   21731             }
   21732             mForegroundInfo.mDrawable.setCallback(null);
   21733             unscheduleDrawable(mForegroundInfo.mDrawable);
   21734         }
   21735 
   21736         mForegroundInfo.mDrawable = foreground;
   21737         mForegroundInfo.mBoundsChanged = true;
   21738         if (foreground != null) {
   21739             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   21740                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   21741             }
   21742             foreground.setLayoutDirection(getLayoutDirection());
   21743             if (foreground.isStateful()) {
   21744                 foreground.setState(getDrawableState());
   21745             }
   21746             applyForegroundTint();
   21747             if (isAttachedToWindow()) {
   21748                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   21749             }
   21750             // Set callback last, since the view may still be initializing.
   21751             foreground.setCallback(this);
   21752         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
   21753                 && (mDefaultFocusHighlight == null)) {
   21754             mPrivateFlags |= PFLAG_SKIP_DRAW;
   21755         }
   21756         requestLayout();
   21757         invalidate();
   21758     }
   21759 
   21760     /**
   21761      * Magic bit used to support features of framework-internal window decor implementation details.
   21762      * This used to live exclusively in FrameLayout.
   21763      *
   21764      * @return true if the foreground should draw inside the padding region or false
   21765      *         if it should draw inset by the view's padding
   21766      * @hide internal use only; only used by FrameLayout and internal screen layouts.
   21767      */
   21768     public boolean isForegroundInsidePadding() {
   21769         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
   21770     }
   21771 
   21772     /**
   21773      * Describes how the foreground is positioned.
   21774      *
   21775      * @return foreground gravity.
   21776      *
   21777      * @see #setForegroundGravity(int)
   21778      *
   21779      * @attr ref android.R.styleable#View_foregroundGravity
   21780      */
   21781     public int getForegroundGravity() {
   21782         return mForegroundInfo != null ? mForegroundInfo.mGravity
   21783                 : Gravity.START | Gravity.TOP;
   21784     }
   21785 
   21786     /**
   21787      * Describes how the foreground is positioned. Defaults to START and TOP.
   21788      *
   21789      * @param gravity see {@link android.view.Gravity}
   21790      *
   21791      * @see #getForegroundGravity()
   21792      *
   21793      * @attr ref android.R.styleable#View_foregroundGravity
   21794      */
   21795     public void setForegroundGravity(int gravity) {
   21796         if (mForegroundInfo == null) {
   21797             mForegroundInfo = new ForegroundInfo();
   21798         }
   21799 
   21800         if (mForegroundInfo.mGravity != gravity) {
   21801             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
   21802                 gravity |= Gravity.START;
   21803             }
   21804 
   21805             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
   21806                 gravity |= Gravity.TOP;
   21807             }
   21808 
   21809             mForegroundInfo.mGravity = gravity;
   21810             requestLayout();
   21811         }
   21812     }
   21813 
   21814     /**
   21815      * Applies a tint to the foreground drawable. Does not modify the current tint
   21816      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   21817      * <p>
   21818      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
   21819      * mutate the drawable and apply the specified tint and tint mode using
   21820      * {@link Drawable#setTintList(ColorStateList)}.
   21821      *
   21822      * @param tint the tint to apply, may be {@code null} to clear tint
   21823      *
   21824      * @attr ref android.R.styleable#View_foregroundTint
   21825      * @see #getForegroundTintList()
   21826      * @see Drawable#setTintList(ColorStateList)
   21827      */
   21828     public void setForegroundTintList(@Nullable ColorStateList tint) {
   21829         if (mForegroundInfo == null) {
   21830             mForegroundInfo = new ForegroundInfo();
   21831         }
   21832         if (mForegroundInfo.mTintInfo == null) {
   21833             mForegroundInfo.mTintInfo = new TintInfo();
   21834         }
   21835         mForegroundInfo.mTintInfo.mTintList = tint;
   21836         mForegroundInfo.mTintInfo.mHasTintList = true;
   21837 
   21838         applyForegroundTint();
   21839     }
   21840 
   21841     /**
   21842      * Return the tint applied to the foreground drawable, if specified.
   21843      *
   21844      * @return the tint applied to the foreground drawable
   21845      * @attr ref android.R.styleable#View_foregroundTint
   21846      * @see #setForegroundTintList(ColorStateList)
   21847      */
   21848     @Nullable
   21849     public ColorStateList getForegroundTintList() {
   21850         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   21851                 ? mForegroundInfo.mTintInfo.mTintList : null;
   21852     }
   21853 
   21854     /**
   21855      * Specifies the blending mode used to apply the tint specified by
   21856      * {@link #setForegroundTintList(ColorStateList)}} to the background
   21857      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   21858      *
   21859      * @param tintMode the blending mode used to apply the tint, may be
   21860      *                 {@code null} to clear tint
   21861      * @attr ref android.R.styleable#View_foregroundTintMode
   21862      * @see #getForegroundTintMode()
   21863      * @see Drawable#setTintMode(PorterDuff.Mode)
   21864      */
   21865     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   21866         if (mForegroundInfo == null) {
   21867             mForegroundInfo = new ForegroundInfo();
   21868         }
   21869         if (mForegroundInfo.mTintInfo == null) {
   21870             mForegroundInfo.mTintInfo = new TintInfo();
   21871         }
   21872         mForegroundInfo.mTintInfo.mTintMode = tintMode;
   21873         mForegroundInfo.mTintInfo.mHasTintMode = true;
   21874 
   21875         applyForegroundTint();
   21876     }
   21877 
   21878     /**
   21879      * Return the blending mode used to apply the tint to the foreground
   21880      * drawable, if specified.
   21881      *
   21882      * @return the blending mode used to apply the tint to the foreground
   21883      *         drawable
   21884      * @attr ref android.R.styleable#View_foregroundTintMode
   21885      * @see #setForegroundTintMode(PorterDuff.Mode)
   21886      */
   21887     @Nullable
   21888     public PorterDuff.Mode getForegroundTintMode() {
   21889         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   21890                 ? mForegroundInfo.mTintInfo.mTintMode : null;
   21891     }
   21892 
   21893     private void applyForegroundTint() {
   21894         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   21895                 && mForegroundInfo.mTintInfo != null) {
   21896             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
   21897             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   21898                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
   21899 
   21900                 if (tintInfo.mHasTintList) {
   21901                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
   21902                 }
   21903 
   21904                 if (tintInfo.mHasTintMode) {
   21905                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
   21906                 }
   21907 
   21908                 // The drawable (or one of its children) may not have been
   21909                 // stateful before applying the tint, so let's try again.
   21910                 if (mForegroundInfo.mDrawable.isStateful()) {
   21911                     mForegroundInfo.mDrawable.setState(getDrawableState());
   21912                 }
   21913             }
   21914         }
   21915     }
   21916 
   21917     /**
   21918      * Get the drawable to be overlayed when a view is autofilled
   21919      *
   21920      * @return The drawable
   21921      *
   21922      * @throws IllegalStateException if the drawable could not be found.
   21923      */
   21924     @Nullable private Drawable getAutofilledDrawable() {
   21925         if (mAttachInfo == null) {
   21926             return null;
   21927         }
   21928         // Lazily load the isAutofilled drawable.
   21929         if (mAttachInfo.mAutofilledDrawable == null) {
   21930             Context rootContext = getRootView().getContext();
   21931             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
   21932             int attributeResourceId = a.getResourceId(0, 0);
   21933             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
   21934             a.recycle();
   21935         }
   21936 
   21937         return mAttachInfo.mAutofilledDrawable;
   21938     }
   21939 
   21940     /**
   21941      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
   21942      *
   21943      * @param canvas The canvas to draw on
   21944      */
   21945     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
   21946         if (isAutofilled()) {
   21947             Drawable autofilledHighlight = getAutofilledDrawable();
   21948 
   21949             if (autofilledHighlight != null) {
   21950                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
   21951                 autofilledHighlight.draw(canvas);
   21952             }
   21953         }
   21954     }
   21955 
   21956     /**
   21957      * Draw any foreground content for this view.
   21958      *
   21959      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
   21960      * drawable or other view-specific decorations. The foreground is drawn on top of the
   21961      * primary view content.</p>
   21962      *
   21963      * @param canvas canvas to draw into
   21964      */
   21965     public void onDrawForeground(Canvas canvas) {
   21966         onDrawScrollIndicators(canvas);
   21967         onDrawScrollBars(canvas);
   21968 
   21969         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   21970         if (foreground != null) {
   21971             if (mForegroundInfo.mBoundsChanged) {
   21972                 mForegroundInfo.mBoundsChanged = false;
   21973                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
   21974                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
   21975 
   21976                 if (mForegroundInfo.mInsidePadding) {
   21977                     selfBounds.set(0, 0, getWidth(), getHeight());
   21978                 } else {
   21979                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
   21980                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
   21981                 }
   21982 
   21983                 final int ld = getLayoutDirection();
   21984                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
   21985                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
   21986                 foreground.setBounds(overlayBounds);
   21987             }
   21988 
   21989             foreground.draw(canvas);
   21990         }
   21991     }
   21992 
   21993     /**
   21994      * Sets the padding. The view may add on the space required to display
   21995      * the scrollbars, depending on the style and visibility of the scrollbars.
   21996      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
   21997      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
   21998      * from the values set in this call.
   21999      *
   22000      * @attr ref android.R.styleable#View_padding
   22001      * @attr ref android.R.styleable#View_paddingBottom
   22002      * @attr ref android.R.styleable#View_paddingLeft
   22003      * @attr ref android.R.styleable#View_paddingRight
   22004      * @attr ref android.R.styleable#View_paddingTop
   22005      * @param left the left padding in pixels
   22006      * @param top the top padding in pixels
   22007      * @param right the right padding in pixels
   22008      * @param bottom the bottom padding in pixels
   22009      */
   22010     public void setPadding(int left, int top, int right, int bottom) {
   22011         resetResolvedPaddingInternal();
   22012 
   22013         mUserPaddingStart = UNDEFINED_PADDING;
   22014         mUserPaddingEnd = UNDEFINED_PADDING;
   22015 
   22016         mUserPaddingLeftInitial = left;
   22017         mUserPaddingRightInitial = right;
   22018 
   22019         mLeftPaddingDefined = true;
   22020         mRightPaddingDefined = true;
   22021 
   22022         internalSetPadding(left, top, right, bottom);
   22023     }
   22024 
   22025     /**
   22026      * @hide
   22027      */
   22028     protected void internalSetPadding(int left, int top, int right, int bottom) {
   22029         mUserPaddingLeft = left;
   22030         mUserPaddingRight = right;
   22031         mUserPaddingBottom = bottom;
   22032 
   22033         final int viewFlags = mViewFlags;
   22034         boolean changed = false;
   22035 
   22036         // Common case is there are no scroll bars.
   22037         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
   22038             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
   22039                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
   22040                         ? 0 : getVerticalScrollbarWidth();
   22041                 switch (mVerticalScrollbarPosition) {
   22042                     case SCROLLBAR_POSITION_DEFAULT:
   22043                         if (isLayoutRtl()) {
   22044                             left += offset;
   22045                         } else {
   22046                             right += offset;
   22047                         }
   22048                         break;
   22049                     case SCROLLBAR_POSITION_RIGHT:
   22050                         right += offset;
   22051                         break;
   22052                     case SCROLLBAR_POSITION_LEFT:
   22053                         left += offset;
   22054                         break;
   22055                 }
   22056             }
   22057             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
   22058                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
   22059                         ? 0 : getHorizontalScrollbarHeight();
   22060             }
   22061         }
   22062 
   22063         if (mPaddingLeft != left) {
   22064             changed = true;
   22065             mPaddingLeft = left;
   22066         }
   22067         if (mPaddingTop != top) {
   22068             changed = true;
   22069             mPaddingTop = top;
   22070         }
   22071         if (mPaddingRight != right) {
   22072             changed = true;
   22073             mPaddingRight = right;
   22074         }
   22075         if (mPaddingBottom != bottom) {
   22076             changed = true;
   22077             mPaddingBottom = bottom;
   22078         }
   22079 
   22080         if (changed) {
   22081             requestLayout();
   22082             invalidateOutline();
   22083         }
   22084     }
   22085 
   22086     /**
   22087      * Sets the relative padding. The view may add on the space required to display
   22088      * the scrollbars, depending on the style and visibility of the scrollbars.
   22089      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
   22090      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
   22091      * from the values set in this call.
   22092      *
   22093      * @attr ref android.R.styleable#View_padding
   22094      * @attr ref android.R.styleable#View_paddingBottom
   22095      * @attr ref android.R.styleable#View_paddingStart
   22096      * @attr ref android.R.styleable#View_paddingEnd
   22097      * @attr ref android.R.styleable#View_paddingTop
   22098      * @param start the start padding in pixels
   22099      * @param top the top padding in pixels
   22100      * @param end the end padding in pixels
   22101      * @param bottom the bottom padding in pixels
   22102      */
   22103     public void setPaddingRelative(int start, int top, int end, int bottom) {
   22104         resetResolvedPaddingInternal();
   22105 
   22106         mUserPaddingStart = start;
   22107         mUserPaddingEnd = end;
   22108         mLeftPaddingDefined = true;
   22109         mRightPaddingDefined = true;
   22110 
   22111         switch(getLayoutDirection()) {
   22112             case LAYOUT_DIRECTION_RTL:
   22113                 mUserPaddingLeftInitial = end;
   22114                 mUserPaddingRightInitial = start;
   22115                 internalSetPadding(end, top, start, bottom);
   22116                 break;
   22117             case LAYOUT_DIRECTION_LTR:
   22118             default:
   22119                 mUserPaddingLeftInitial = start;
   22120                 mUserPaddingRightInitial = end;
   22121                 internalSetPadding(start, top, end, bottom);
   22122         }
   22123     }
   22124 
   22125     /**
   22126      * Returns the top padding of this view.
   22127      *
   22128      * @return the top padding in pixels
   22129      */
   22130     public int getPaddingTop() {
   22131         return mPaddingTop;
   22132     }
   22133 
   22134     /**
   22135      * Returns the bottom padding of this view. If there are inset and enabled
   22136      * scrollbars, this value may include the space required to display the
   22137      * scrollbars as well.
   22138      *
   22139      * @return the bottom padding in pixels
   22140      */
   22141     public int getPaddingBottom() {
   22142         return mPaddingBottom;
   22143     }
   22144 
   22145     /**
   22146      * Returns the left padding of this view. If there are inset and enabled
   22147      * scrollbars, this value may include the space required to display the
   22148      * scrollbars as well.
   22149      *
   22150      * @return the left padding in pixels
   22151      */
   22152     public int getPaddingLeft() {
   22153         if (!isPaddingResolved()) {
   22154             resolvePadding();
   22155         }
   22156         return mPaddingLeft;
   22157     }
   22158 
   22159     /**
   22160      * Returns the start padding of this view depending on its resolved layout direction.
   22161      * If there are inset and enabled scrollbars, this value may include the space
   22162      * required to display the scrollbars as well.
   22163      *
   22164      * @return the start padding in pixels
   22165      */
   22166     public int getPaddingStart() {
   22167         if (!isPaddingResolved()) {
   22168             resolvePadding();
   22169         }
   22170         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   22171                 mPaddingRight : mPaddingLeft;
   22172     }
   22173 
   22174     /**
   22175      * Returns the right padding of this view. If there are inset and enabled
   22176      * scrollbars, this value may include the space required to display the
   22177      * scrollbars as well.
   22178      *
   22179      * @return the right padding in pixels
   22180      */
   22181     public int getPaddingRight() {
   22182         if (!isPaddingResolved()) {
   22183             resolvePadding();
   22184         }
   22185         return mPaddingRight;
   22186     }
   22187 
   22188     /**
   22189      * Returns the end padding of this view depending on its resolved layout direction.
   22190      * If there are inset and enabled scrollbars, this value may include the space
   22191      * required to display the scrollbars as well.
   22192      *
   22193      * @return the end padding in pixels
   22194      */
   22195     public int getPaddingEnd() {
   22196         if (!isPaddingResolved()) {
   22197             resolvePadding();
   22198         }
   22199         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   22200                 mPaddingLeft : mPaddingRight;
   22201     }
   22202 
   22203     /**
   22204      * Return if the padding has been set through relative values
   22205      * {@link #setPaddingRelative(int, int, int, int)} or through
   22206      * @attr ref android.R.styleable#View_paddingStart or
   22207      * @attr ref android.R.styleable#View_paddingEnd
   22208      *
   22209      * @return true if the padding is relative or false if it is not.
   22210      */
   22211     public boolean isPaddingRelative() {
   22212         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
   22213     }
   22214 
   22215     Insets computeOpticalInsets() {
   22216         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
   22217     }
   22218 
   22219     /**
   22220      * @hide
   22221      */
   22222     public void resetPaddingToInitialValues() {
   22223         if (isRtlCompatibilityMode()) {
   22224             mPaddingLeft = mUserPaddingLeftInitial;
   22225             mPaddingRight = mUserPaddingRightInitial;
   22226             return;
   22227         }
   22228         if (isLayoutRtl()) {
   22229             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
   22230             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
   22231         } else {
   22232             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
   22233             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
   22234         }
   22235     }
   22236 
   22237     /**
   22238      * @hide
   22239      */
   22240     public Insets getOpticalInsets() {
   22241         if (mLayoutInsets == null) {
   22242             mLayoutInsets = computeOpticalInsets();
   22243         }
   22244         return mLayoutInsets;
   22245     }
   22246 
   22247     /**
   22248      * Set this view's optical insets.
   22249      *
   22250      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
   22251      * property. Views that compute their own optical insets should call it as part of measurement.
   22252      * This method does not request layout. If you are setting optical insets outside of
   22253      * measure/layout itself you will want to call requestLayout() yourself.
   22254      * </p>
   22255      * @hide
   22256      */
   22257     public void setOpticalInsets(Insets insets) {
   22258         mLayoutInsets = insets;
   22259     }
   22260 
   22261     /**
   22262      * Changes the selection state of this view. A view can be selected or not.
   22263      * Note that selection is not the same as focus. Views are typically
   22264      * selected in the context of an AdapterView like ListView or GridView;
   22265      * the selected view is the view that is highlighted.
   22266      *
   22267      * @param selected true if the view must be selected, false otherwise
   22268      */
   22269     public void setSelected(boolean selected) {
   22270         //noinspection DoubleNegation
   22271         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
   22272             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
   22273             if (!selected) resetPressedState();
   22274             invalidate(true);
   22275             refreshDrawableState();
   22276             dispatchSetSelected(selected);
   22277             if (selected) {
   22278                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
   22279             } else {
   22280                 notifyViewAccessibilityStateChangedIfNeeded(
   22281                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   22282             }
   22283         }
   22284     }
   22285 
   22286     /**
   22287      * Dispatch setSelected to all of this View's children.
   22288      *
   22289      * @see #setSelected(boolean)
   22290      *
   22291      * @param selected The new selected state
   22292      */
   22293     protected void dispatchSetSelected(boolean selected) {
   22294     }
   22295 
   22296     /**
   22297      * Indicates the selection state of this view.
   22298      *
   22299      * @return true if the view is selected, false otherwise
   22300      */
   22301     @ViewDebug.ExportedProperty
   22302     public boolean isSelected() {
   22303         return (mPrivateFlags & PFLAG_SELECTED) != 0;
   22304     }
   22305 
   22306     /**
   22307      * Changes the activated state of this view. A view can be activated or not.
   22308      * Note that activation is not the same as selection.  Selection is
   22309      * a transient property, representing the view (hierarchy) the user is
   22310      * currently interacting with.  Activation is a longer-term state that the
   22311      * user can move views in and out of.  For example, in a list view with
   22312      * single or multiple selection enabled, the views in the current selection
   22313      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
   22314      * here.)  The activated state is propagated down to children of the view it
   22315      * is set on.
   22316      *
   22317      * @param activated true if the view must be activated, false otherwise
   22318      */
   22319     public void setActivated(boolean activated) {
   22320         //noinspection DoubleNegation
   22321         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
   22322             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
   22323             invalidate(true);
   22324             refreshDrawableState();
   22325             dispatchSetActivated(activated);
   22326         }
   22327     }
   22328 
   22329     /**
   22330      * Dispatch setActivated to all of this View's children.
   22331      *
   22332      * @see #setActivated(boolean)
   22333      *
   22334      * @param activated The new activated state
   22335      */
   22336     protected void dispatchSetActivated(boolean activated) {
   22337     }
   22338 
   22339     /**
   22340      * Indicates the activation state of this view.
   22341      *
   22342      * @return true if the view is activated, false otherwise
   22343      */
   22344     @ViewDebug.ExportedProperty
   22345     public boolean isActivated() {
   22346         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
   22347     }
   22348 
   22349     /**
   22350      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
   22351      * observer can be used to get notifications when global events, like
   22352      * layout, happen.
   22353      *
   22354      * The returned ViewTreeObserver observer is not guaranteed to remain
   22355      * valid for the lifetime of this View. If the caller of this method keeps
   22356      * a long-lived reference to ViewTreeObserver, it should always check for
   22357      * the return value of {@link ViewTreeObserver#isAlive()}.
   22358      *
   22359      * @return The ViewTreeObserver for this view's hierarchy.
   22360      */
   22361     public ViewTreeObserver getViewTreeObserver() {
   22362         if (mAttachInfo != null) {
   22363             return mAttachInfo.mTreeObserver;
   22364         }
   22365         if (mFloatingTreeObserver == null) {
   22366             mFloatingTreeObserver = new ViewTreeObserver(mContext);
   22367         }
   22368         return mFloatingTreeObserver;
   22369     }
   22370 
   22371     /**
   22372      * <p>Finds the topmost view in the current view hierarchy.</p>
   22373      *
   22374      * @return the topmost view containing this view
   22375      */
   22376     public View getRootView() {
   22377         if (mAttachInfo != null) {
   22378             final View v = mAttachInfo.mRootView;
   22379             if (v != null) {
   22380                 return v;
   22381             }
   22382         }
   22383 
   22384         View parent = this;
   22385 
   22386         while (parent.mParent != null && parent.mParent instanceof View) {
   22387             parent = (View) parent.mParent;
   22388         }
   22389 
   22390         return parent;
   22391     }
   22392 
   22393     /**
   22394      * Transforms a motion event from view-local coordinates to on-screen
   22395      * coordinates.
   22396      *
   22397      * @param ev the view-local motion event
   22398      * @return false if the transformation could not be applied
   22399      * @hide
   22400      */
   22401     public boolean toGlobalMotionEvent(MotionEvent ev) {
   22402         final AttachInfo info = mAttachInfo;
   22403         if (info == null) {
   22404             return false;
   22405         }
   22406 
   22407         final Matrix m = info.mTmpMatrix;
   22408         m.set(Matrix.IDENTITY_MATRIX);
   22409         transformMatrixToGlobal(m);
   22410         ev.transform(m);
   22411         return true;
   22412     }
   22413 
   22414     /**
   22415      * Transforms a motion event from on-screen coordinates to view-local
   22416      * coordinates.
   22417      *
   22418      * @param ev the on-screen motion event
   22419      * @return false if the transformation could not be applied
   22420      * @hide
   22421      */
   22422     public boolean toLocalMotionEvent(MotionEvent ev) {
   22423         final AttachInfo info = mAttachInfo;
   22424         if (info == null) {
   22425             return false;
   22426         }
   22427 
   22428         final Matrix m = info.mTmpMatrix;
   22429         m.set(Matrix.IDENTITY_MATRIX);
   22430         transformMatrixToLocal(m);
   22431         ev.transform(m);
   22432         return true;
   22433     }
   22434 
   22435     /**
   22436      * Modifies the input matrix such that it maps view-local coordinates to
   22437      * on-screen coordinates.
   22438      *
   22439      * @param m input matrix to modify
   22440      * @hide
   22441      */
   22442     public void transformMatrixToGlobal(Matrix m) {
   22443         final ViewParent parent = mParent;
   22444         if (parent instanceof View) {
   22445             final View vp = (View) parent;
   22446             vp.transformMatrixToGlobal(m);
   22447             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
   22448         } else if (parent instanceof ViewRootImpl) {
   22449             final ViewRootImpl vr = (ViewRootImpl) parent;
   22450             vr.transformMatrixToGlobal(m);
   22451             m.preTranslate(0, -vr.mCurScrollY);
   22452         }
   22453 
   22454         m.preTranslate(mLeft, mTop);
   22455 
   22456         if (!hasIdentityMatrix()) {
   22457             m.preConcat(getMatrix());
   22458         }
   22459     }
   22460 
   22461     /**
   22462      * Modifies the input matrix such that it maps on-screen coordinates to
   22463      * view-local coordinates.
   22464      *
   22465      * @param m input matrix to modify
   22466      * @hide
   22467      */
   22468     public void transformMatrixToLocal(Matrix m) {
   22469         final ViewParent parent = mParent;
   22470         if (parent instanceof View) {
   22471             final View vp = (View) parent;
   22472             vp.transformMatrixToLocal(m);
   22473             m.postTranslate(vp.mScrollX, vp.mScrollY);
   22474         } else if (parent instanceof ViewRootImpl) {
   22475             final ViewRootImpl vr = (ViewRootImpl) parent;
   22476             vr.transformMatrixToLocal(m);
   22477             m.postTranslate(0, vr.mCurScrollY);
   22478         }
   22479 
   22480         m.postTranslate(-mLeft, -mTop);
   22481 
   22482         if (!hasIdentityMatrix()) {
   22483             m.postConcat(getInverseMatrix());
   22484         }
   22485     }
   22486 
   22487     /**
   22488      * @hide
   22489      */
   22490     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
   22491             @ViewDebug.IntToString(from = 0, to = "x"),
   22492             @ViewDebug.IntToString(from = 1, to = "y")
   22493     })
   22494     public int[] getLocationOnScreen() {
   22495         int[] location = new int[2];
   22496         getLocationOnScreen(location);
   22497         return location;
   22498     }
   22499 
   22500     /**
   22501      * <p>Computes the coordinates of this view on the screen. The argument
   22502      * must be an array of two integers. After the method returns, the array
   22503      * contains the x and y location in that order.</p>
   22504      *
   22505      * @param outLocation an array of two integers in which to hold the coordinates
   22506      */
   22507     public void getLocationOnScreen(@Size(2) int[] outLocation) {
   22508         getLocationInWindow(outLocation);
   22509 
   22510         final AttachInfo info = mAttachInfo;
   22511         if (info != null) {
   22512             outLocation[0] += info.mWindowLeft;
   22513             outLocation[1] += info.mWindowTop;
   22514         }
   22515     }
   22516 
   22517     /**
   22518      * <p>Computes the coordinates of this view in its window. The argument
   22519      * must be an array of two integers. After the method returns, the array
   22520      * contains the x and y location in that order.</p>
   22521      *
   22522      * @param outLocation an array of two integers in which to hold the coordinates
   22523      */
   22524     public void getLocationInWindow(@Size(2) int[] outLocation) {
   22525         if (outLocation == null || outLocation.length < 2) {
   22526             throw new IllegalArgumentException("outLocation must be an array of two integers");
   22527         }
   22528 
   22529         outLocation[0] = 0;
   22530         outLocation[1] = 0;
   22531 
   22532         transformFromViewToWindowSpace(outLocation);
   22533     }
   22534 
   22535     /** @hide */
   22536     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
   22537         if (inOutLocation == null || inOutLocation.length < 2) {
   22538             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
   22539         }
   22540 
   22541         if (mAttachInfo == null) {
   22542             // When the view is not attached to a window, this method does not make sense
   22543             inOutLocation[0] = inOutLocation[1] = 0;
   22544             return;
   22545         }
   22546 
   22547         float position[] = mAttachInfo.mTmpTransformLocation;
   22548         position[0] = inOutLocation[0];
   22549         position[1] = inOutLocation[1];
   22550 
   22551         if (!hasIdentityMatrix()) {
   22552             getMatrix().mapPoints(position);
   22553         }
   22554 
   22555         position[0] += mLeft;
   22556         position[1] += mTop;
   22557 
   22558         ViewParent viewParent = mParent;
   22559         while (viewParent instanceof View) {
   22560             final View view = (View) viewParent;
   22561 
   22562             position[0] -= view.mScrollX;
   22563             position[1] -= view.mScrollY;
   22564 
   22565             if (!view.hasIdentityMatrix()) {
   22566                 view.getMatrix().mapPoints(position);
   22567             }
   22568 
   22569             position[0] += view.mLeft;
   22570             position[1] += view.mTop;
   22571 
   22572             viewParent = view.mParent;
   22573          }
   22574 
   22575         if (viewParent instanceof ViewRootImpl) {
   22576             // *cough*
   22577             final ViewRootImpl vr = (ViewRootImpl) viewParent;
   22578             position[1] -= vr.mCurScrollY;
   22579         }
   22580 
   22581         inOutLocation[0] = Math.round(position[0]);
   22582         inOutLocation[1] = Math.round(position[1]);
   22583     }
   22584 
   22585     /**
   22586      * @param id the id of the view to be found
   22587      * @return the view of the specified id, null if cannot be found
   22588      * @hide
   22589      */
   22590     protected <T extends View> T findViewTraversal(@IdRes int id) {
   22591         if (id == mID) {
   22592             return (T) this;
   22593         }
   22594         return null;
   22595     }
   22596 
   22597     /**
   22598      * @param tag the tag of the view to be found
   22599      * @return the view of specified tag, null if cannot be found
   22600      * @hide
   22601      */
   22602     protected <T extends View> T findViewWithTagTraversal(Object tag) {
   22603         if (tag != null && tag.equals(mTag)) {
   22604             return (T) this;
   22605         }
   22606         return null;
   22607     }
   22608 
   22609     /**
   22610      * @param predicate The predicate to evaluate.
   22611      * @param childToSkip If not null, ignores this child during the recursive traversal.
   22612      * @return The first view that matches the predicate or null.
   22613      * @hide
   22614      */
   22615     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
   22616             View childToSkip) {
   22617         if (predicate.test(this)) {
   22618             return (T) this;
   22619         }
   22620         return null;
   22621     }
   22622 
   22623     /**
   22624      * Finds the first descendant view with the given ID, the view itself if
   22625      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
   22626      * (< 0) or there is no matching view in the hierarchy.
   22627      * <p>
   22628      * <strong>Note:</strong> In most cases -- depending on compiler support --
   22629      * the resulting view is automatically cast to the target class type. If
   22630      * the target class type is unconstrained, an explicit cast may be
   22631      * necessary.
   22632      *
   22633      * @param id the ID to search for
   22634      * @return a view with given ID if found, or {@code null} otherwise
   22635      * @see View#requireViewById(int)
   22636      */
   22637     @Nullable
   22638     public final <T extends View> T findViewById(@IdRes int id) {
   22639         if (id == NO_ID) {
   22640             return null;
   22641         }
   22642         return findViewTraversal(id);
   22643     }
   22644 
   22645     /**
   22646      * Finds the first descendant view with the given ID, the view itself if the ID matches
   22647      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
   22648      * matching view in the hierarchy.
   22649      * <p>
   22650      * <strong>Note:</strong> In most cases -- depending on compiler support --
   22651      * the resulting view is automatically cast to the target class type. If
   22652      * the target class type is unconstrained, an explicit cast may be
   22653      * necessary.
   22654      *
   22655      * @param id the ID to search for
   22656      * @return a view with given ID
   22657      * @see View#findViewById(int)
   22658      */
   22659     @NonNull
   22660     public final <T extends View> T requireViewById(@IdRes int id) {
   22661         T view = findViewById(id);
   22662         if (view == null) {
   22663             throw new IllegalArgumentException("ID does not reference a View inside this View");
   22664         }
   22665         return view;
   22666     }
   22667 
   22668     /**
   22669      * Finds a view by its unuque and stable accessibility id.
   22670      *
   22671      * @param accessibilityId The searched accessibility id.
   22672      * @return The found view.
   22673      */
   22674     final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
   22675         if (accessibilityId < 0) {
   22676             return null;
   22677         }
   22678         T view = findViewByAccessibilityIdTraversal(accessibilityId);
   22679         if (view != null) {
   22680             return view.includeForAccessibility() ? view : null;
   22681         }
   22682         return null;
   22683     }
   22684 
   22685     /**
   22686      * Performs the traversal to find a view by its unique and stable accessibility id.
   22687      *
   22688      * <strong>Note:</strong>This method does not stop at the root namespace
   22689      * boundary since the user can touch the screen at an arbitrary location
   22690      * potentially crossing the root namespace boundary which will send an
   22691      * accessibility event to accessibility services and they should be able
   22692      * to obtain the event source. Also accessibility ids are guaranteed to be
   22693      * unique in the window.
   22694      *
   22695      * @param accessibilityId The accessibility id.
   22696      * @return The found view.
   22697      * @hide
   22698      */
   22699     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
   22700         if (getAccessibilityViewId() == accessibilityId) {
   22701             return (T) this;
   22702         }
   22703         return null;
   22704     }
   22705 
   22706     /**
   22707      * Performs the traversal to find a view by its autofill id.
   22708      *
   22709      * <strong>Note:</strong>This method does not stop at the root namespace
   22710      * boundary.
   22711      *
   22712      * @param autofillId The autofill id.
   22713      * @return The found view.
   22714      * @hide
   22715      */
   22716     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
   22717         if (getAutofillViewId() == autofillId) {
   22718             return (T) this;
   22719         }
   22720         return null;
   22721     }
   22722 
   22723     /**
   22724      * Look for a child view with the given tag.  If this view has the given
   22725      * tag, return this view.
   22726      *
   22727      * @param tag The tag to search for, using "tag.equals(getTag())".
   22728      * @return The View that has the given tag in the hierarchy or null
   22729      */
   22730     public final <T extends View> T findViewWithTag(Object tag) {
   22731         if (tag == null) {
   22732             return null;
   22733         }
   22734         return findViewWithTagTraversal(tag);
   22735     }
   22736 
   22737     /**
   22738      * Look for a child view that matches the specified predicate.
   22739      * If this view matches the predicate, return this view.
   22740      *
   22741      * @param predicate The predicate to evaluate.
   22742      * @return The first view that matches the predicate or null.
   22743      * @hide
   22744      */
   22745     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
   22746         return findViewByPredicateTraversal(predicate, null);
   22747     }
   22748 
   22749     /**
   22750      * Look for a child view that matches the specified predicate,
   22751      * starting with the specified view and its descendents and then
   22752      * recusively searching the ancestors and siblings of that view
   22753      * until this view is reached.
   22754      *
   22755      * This method is useful in cases where the predicate does not match
   22756      * a single unique view (perhaps multiple views use the same id)
   22757      * and we are trying to find the view that is "closest" in scope to the
   22758      * starting view.
   22759      *
   22760      * @param start The view to start from.
   22761      * @param predicate The predicate to evaluate.
   22762      * @return The first view that matches the predicate or null.
   22763      * @hide
   22764      */
   22765     public final <T extends View> T findViewByPredicateInsideOut(
   22766             View start, Predicate<View> predicate) {
   22767         View childToSkip = null;
   22768         for (;;) {
   22769             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
   22770             if (view != null || start == this) {
   22771                 return view;
   22772             }
   22773 
   22774             ViewParent parent = start.getParent();
   22775             if (parent == null || !(parent instanceof View)) {
   22776                 return null;
   22777             }
   22778 
   22779             childToSkip = start;
   22780             start = (View) parent;
   22781         }
   22782     }
   22783 
   22784     /**
   22785      * Sets the identifier for this view. The identifier does not have to be
   22786      * unique in this view's hierarchy. The identifier should be a positive
   22787      * number.
   22788      *
   22789      * @see #NO_ID
   22790      * @see #getId()
   22791      * @see #findViewById(int)
   22792      *
   22793      * @param id a number used to identify the view
   22794      *
   22795      * @attr ref android.R.styleable#View_id
   22796      */
   22797     public void setId(@IdRes int id) {
   22798         mID = id;
   22799         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
   22800             mID = generateViewId();
   22801         }
   22802     }
   22803 
   22804     /**
   22805      * {@hide}
   22806      *
   22807      * @param isRoot true if the view belongs to the root namespace, false
   22808      *        otherwise
   22809      */
   22810     public void setIsRootNamespace(boolean isRoot) {
   22811         if (isRoot) {
   22812             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
   22813         } else {
   22814             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
   22815         }
   22816     }
   22817 
   22818     /**
   22819      * {@hide}
   22820      *
   22821      * @return true if the view belongs to the root namespace, false otherwise
   22822      */
   22823     public boolean isRootNamespace() {
   22824         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
   22825     }
   22826 
   22827     /**
   22828      * Returns this view's identifier.
   22829      *
   22830      * @return a positive integer used to identify the view or {@link #NO_ID}
   22831      *         if the view has no ID
   22832      *
   22833      * @see #setId(int)
   22834      * @see #findViewById(int)
   22835      * @attr ref android.R.styleable#View_id
   22836      */
   22837     @IdRes
   22838     @ViewDebug.CapturedViewProperty
   22839     public int getId() {
   22840         return mID;
   22841     }
   22842 
   22843     /**
   22844      * Returns this view's tag.
   22845      *
   22846      * @return the Object stored in this view as a tag, or {@code null} if not
   22847      *         set
   22848      *
   22849      * @see #setTag(Object)
   22850      * @see #getTag(int)
   22851      */
   22852     @ViewDebug.ExportedProperty
   22853     public Object getTag() {
   22854         return mTag;
   22855     }
   22856 
   22857     /**
   22858      * Sets the tag associated with this view. A tag can be used to mark
   22859      * a view in its hierarchy and does not have to be unique within the
   22860      * hierarchy. Tags can also be used to store data within a view without
   22861      * resorting to another data structure.
   22862      *
   22863      * @param tag an Object to tag the view with
   22864      *
   22865      * @see #getTag()
   22866      * @see #setTag(int, Object)
   22867      */
   22868     public void setTag(final Object tag) {
   22869         mTag = tag;
   22870     }
   22871 
   22872     /**
   22873      * Returns the tag associated with this view and the specified key.
   22874      *
   22875      * @param key The key identifying the tag
   22876      *
   22877      * @return the Object stored in this view as a tag, or {@code null} if not
   22878      *         set
   22879      *
   22880      * @see #setTag(int, Object)
   22881      * @see #getTag()
   22882      */
   22883     public Object getTag(int key) {
   22884         if (mKeyedTags != null) return mKeyedTags.get(key);
   22885         return null;
   22886     }
   22887 
   22888     /**
   22889      * Sets a tag associated with this view and a key. A tag can be used
   22890      * to mark a view in its hierarchy and does not have to be unique within
   22891      * the hierarchy. Tags can also be used to store data within a view
   22892      * without resorting to another data structure.
   22893      *
   22894      * The specified key should be an id declared in the resources of the
   22895      * application to ensure it is unique (see the <a
   22896      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
   22897      * Keys identified as belonging to
   22898      * the Android framework or not associated with any package will cause
   22899      * an {@link IllegalArgumentException} to be thrown.
   22900      *
   22901      * @param key The key identifying the tag
   22902      * @param tag An Object to tag the view with
   22903      *
   22904      * @throws IllegalArgumentException If they specified key is not valid
   22905      *
   22906      * @see #setTag(Object)
   22907      * @see #getTag(int)
   22908      */
   22909     public void setTag(int key, final Object tag) {
   22910         // If the package id is 0x00 or 0x01, it's either an undefined package
   22911         // or a framework id
   22912         if ((key >>> 24) < 2) {
   22913             throw new IllegalArgumentException("The key must be an application-specific "
   22914                     + "resource id.");
   22915         }
   22916 
   22917         setKeyedTag(key, tag);
   22918     }
   22919 
   22920     /**
   22921      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
   22922      * framework id.
   22923      *
   22924      * @hide
   22925      */
   22926     public void setTagInternal(int key, Object tag) {
   22927         if ((key >>> 24) != 0x1) {
   22928             throw new IllegalArgumentException("The key must be a framework-specific "
   22929                     + "resource id.");
   22930         }
   22931 
   22932         setKeyedTag(key, tag);
   22933     }
   22934 
   22935     private void setKeyedTag(int key, Object tag) {
   22936         if (mKeyedTags == null) {
   22937             mKeyedTags = new SparseArray<Object>(2);
   22938         }
   22939 
   22940         mKeyedTags.put(key, tag);
   22941     }
   22942 
   22943     /**
   22944      * Prints information about this view in the log output, with the tag
   22945      * {@link #VIEW_LOG_TAG}.
   22946      *
   22947      * @hide
   22948      */
   22949     public void debug() {
   22950         debug(0);
   22951     }
   22952 
   22953     /**
   22954      * Prints information about this view in the log output, with the tag
   22955      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
   22956      * indentation defined by the <code>depth</code>.
   22957      *
   22958      * @param depth the indentation level
   22959      *
   22960      * @hide
   22961      */
   22962     protected void debug(int depth) {
   22963         String output = debugIndent(depth - 1);
   22964 
   22965         output += "+ " + this;
   22966         int id = getId();
   22967         if (id != -1) {
   22968             output += " (id=" + id + ")";
   22969         }
   22970         Object tag = getTag();
   22971         if (tag != null) {
   22972             output += " (tag=" + tag + ")";
   22973         }
   22974         Log.d(VIEW_LOG_TAG, output);
   22975 
   22976         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   22977             output = debugIndent(depth) + " FOCUSED";
   22978             Log.d(VIEW_LOG_TAG, output);
   22979         }
   22980 
   22981         output = debugIndent(depth);
   22982         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
   22983                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
   22984                 + "} ";
   22985         Log.d(VIEW_LOG_TAG, output);
   22986 
   22987         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
   22988                 || mPaddingBottom != 0) {
   22989             output = debugIndent(depth);
   22990             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
   22991                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
   22992             Log.d(VIEW_LOG_TAG, output);
   22993         }
   22994 
   22995         output = debugIndent(depth);
   22996         output += "mMeasureWidth=" + mMeasuredWidth +
   22997                 " mMeasureHeight=" + mMeasuredHeight;
   22998         Log.d(VIEW_LOG_TAG, output);
   22999 
   23000         output = debugIndent(depth);
   23001         if (mLayoutParams == null) {
   23002             output += "BAD! no layout params";
   23003         } else {
   23004             output = mLayoutParams.debug(output);
   23005         }
   23006         Log.d(VIEW_LOG_TAG, output);
   23007 
   23008         output = debugIndent(depth);
   23009         output += "flags={";
   23010         output += View.printFlags(mViewFlags);
   23011         output += "}";
   23012         Log.d(VIEW_LOG_TAG, output);
   23013 
   23014         output = debugIndent(depth);
   23015         output += "privateFlags={";
   23016         output += View.printPrivateFlags(mPrivateFlags);
   23017         output += "}";
   23018         Log.d(VIEW_LOG_TAG, output);
   23019     }
   23020 
   23021     /**
   23022      * Creates a string of whitespaces used for indentation.
   23023      *
   23024      * @param depth the indentation level
   23025      * @return a String containing (depth * 2 + 3) * 2 white spaces
   23026      *
   23027      * @hide
   23028      */
   23029     protected static String debugIndent(int depth) {
   23030         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
   23031         for (int i = 0; i < (depth * 2) + 3; i++) {
   23032             spaces.append(' ').append(' ');
   23033         }
   23034         return spaces.toString();
   23035     }
   23036 
   23037     /**
   23038      * <p>Return the offset of the widget's text baseline from the widget's top
   23039      * boundary. If this widget does not support baseline alignment, this
   23040      * method returns -1. </p>
   23041      *
   23042      * @return the offset of the baseline within the widget's bounds or -1
   23043      *         if baseline alignment is not supported
   23044      */
   23045     @ViewDebug.ExportedProperty(category = "layout")
   23046     public int getBaseline() {
   23047         return -1;
   23048     }
   23049 
   23050     /**
   23051      * Returns whether the view hierarchy is currently undergoing a layout pass. This
   23052      * information is useful to avoid situations such as calling {@link #requestLayout()} during
   23053      * a layout pass.
   23054      *
   23055      * @return whether the view hierarchy is currently undergoing a layout pass
   23056      */
   23057     public boolean isInLayout() {
   23058         ViewRootImpl viewRoot = getViewRootImpl();
   23059         return (viewRoot != null && viewRoot.isInLayout());
   23060     }
   23061 
   23062     /**
   23063      * Call this when something has changed which has invalidated the
   23064      * layout of this view. This will schedule a layout pass of the view
   23065      * tree. This should not be called while the view hierarchy is currently in a layout
   23066      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
   23067      * end of the current layout pass (and then layout will run again) or after the current
   23068      * frame is drawn and the next layout occurs.
   23069      *
   23070      * <p>Subclasses which override this method should call the superclass method to
   23071      * handle possible request-during-layout errors correctly.</p>
   23072      */
   23073     @CallSuper
   23074     public void requestLayout() {
   23075         if (mMeasureCache != null) mMeasureCache.clear();
   23076 
   23077         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
   23078             // Only trigger request-during-layout logic if this is the view requesting it,
   23079             // not the views in its parent hierarchy
   23080             ViewRootImpl viewRoot = getViewRootImpl();
   23081             if (viewRoot != null && viewRoot.isInLayout()) {
   23082                 if (!viewRoot.requestLayoutDuringLayout(this)) {
   23083                     return;
   23084                 }
   23085             }
   23086             mAttachInfo.mViewRequestingLayout = this;
   23087         }
   23088 
   23089         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   23090         mPrivateFlags |= PFLAG_INVALIDATED;
   23091 
   23092         if (mParent != null && !mParent.isLayoutRequested()) {
   23093             mParent.requestLayout();
   23094         }
   23095         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
   23096             mAttachInfo.mViewRequestingLayout = null;
   23097         }
   23098     }
   23099 
   23100     /**
   23101      * Forces this view to be laid out during the next layout pass.
   23102      * This method does not call requestLayout() or forceLayout()
   23103      * on the parent.
   23104      */
   23105     public void forceLayout() {
   23106         if (mMeasureCache != null) mMeasureCache.clear();
   23107 
   23108         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   23109         mPrivateFlags |= PFLAG_INVALIDATED;
   23110     }
   23111 
   23112     /**
   23113      * <p>
   23114      * This is called to find out how big a view should be. The parent
   23115      * supplies constraint information in the width and height parameters.
   23116      * </p>
   23117      *
   23118      * <p>
   23119      * The actual measurement work of a view is performed in
   23120      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
   23121      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
   23122      * </p>
   23123      *
   23124      *
   23125      * @param widthMeasureSpec Horizontal space requirements as imposed by the
   23126      *        parent
   23127      * @param heightMeasureSpec Vertical space requirements as imposed by the
   23128      *        parent
   23129      *
   23130      * @see #onMeasure(int, int)
   23131      */
   23132     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
   23133         boolean optical = isLayoutModeOptical(this);
   23134         if (optical != isLayoutModeOptical(mParent)) {
   23135             Insets insets = getOpticalInsets();
   23136             int oWidth  = insets.left + insets.right;
   23137             int oHeight = insets.top  + insets.bottom;
   23138             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
   23139             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
   23140         }
   23141 
   23142         // Suppress sign extension for the low bytes
   23143         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
   23144         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
   23145 
   23146         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   23147 
   23148         // Optimize layout by avoiding an extra EXACTLY pass when the view is
   23149         // already measured as the correct size. In API 23 and below, this
   23150         // extra pass is required to make LinearLayout re-distribute weight.
   23151         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
   23152                 || heightMeasureSpec != mOldHeightMeasureSpec;
   23153         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
   23154                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
   23155         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
   23156                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
   23157         final boolean needsLayout = specChanged
   23158                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
   23159 
   23160         if (forceLayout || needsLayout) {
   23161             // first clears the measured dimension flag
   23162             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
   23163 
   23164             resolveRtlPropertiesIfNeeded();
   23165 
   23166             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
   23167             if (cacheIndex < 0 || sIgnoreMeasureCache) {
   23168                 // measure ourselves, this should set the measured dimension flag back
   23169                 onMeasure(widthMeasureSpec, heightMeasureSpec);
   23170                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   23171             } else {
   23172                 long value = mMeasureCache.valueAt(cacheIndex);
   23173                 // Casting a long to int drops the high 32 bits, no mask needed
   23174                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
   23175                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   23176             }
   23177 
   23178             // flag not set, setMeasuredDimension() was not invoked, we raise
   23179             // an exception to warn the developer
   23180             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
   23181                 throw new IllegalStateException("View with id " + getId() + ": "
   23182                         + getClass().getName() + "#onMeasure() did not set the"
   23183                         + " measured dimension by calling"
   23184                         + " setMeasuredDimension()");
   23185             }
   23186 
   23187             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
   23188         }
   23189 
   23190         mOldWidthMeasureSpec = widthMeasureSpec;
   23191         mOldHeightMeasureSpec = heightMeasureSpec;
   23192 
   23193         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
   23194                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
   23195     }
   23196 
   23197     /**
   23198      * <p>
   23199      * Measure the view and its content to determine the measured width and the
   23200      * measured height. This method is invoked by {@link #measure(int, int)} and
   23201      * should be overridden by subclasses to provide accurate and efficient
   23202      * measurement of their contents.
   23203      * </p>
   23204      *
   23205      * <p>
   23206      * <strong>CONTRACT:</strong> When overriding this method, you
   23207      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
   23208      * measured width and height of this view. Failure to do so will trigger an
   23209      * <code>IllegalStateException</code>, thrown by
   23210      * {@link #measure(int, int)}. Calling the superclass'
   23211      * {@link #onMeasure(int, int)} is a valid use.
   23212      * </p>
   23213      *
   23214      * <p>
   23215      * The base class implementation of measure defaults to the background size,
   23216      * unless a larger size is allowed by the MeasureSpec. Subclasses should
   23217      * override {@link #onMeasure(int, int)} to provide better measurements of
   23218      * their content.
   23219      * </p>
   23220      *
   23221      * <p>
   23222      * If this method is overridden, it is the subclass's responsibility to make
   23223      * sure the measured height and width are at least the view's minimum height
   23224      * and width ({@link #getSuggestedMinimumHeight()} and
   23225      * {@link #getSuggestedMinimumWidth()}).
   23226      * </p>
   23227      *
   23228      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
   23229      *                         The requirements are encoded with
   23230      *                         {@link android.view.View.MeasureSpec}.
   23231      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
   23232      *                         The requirements are encoded with
   23233      *                         {@link android.view.View.MeasureSpec}.
   23234      *
   23235      * @see #getMeasuredWidth()
   23236      * @see #getMeasuredHeight()
   23237      * @see #setMeasuredDimension(int, int)
   23238      * @see #getSuggestedMinimumHeight()
   23239      * @see #getSuggestedMinimumWidth()
   23240      * @see android.view.View.MeasureSpec#getMode(int)
   23241      * @see android.view.View.MeasureSpec#getSize(int)
   23242      */
   23243     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   23244         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
   23245                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
   23246     }
   23247 
   23248     /**
   23249      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
   23250      * measured width and measured height. Failing to do so will trigger an
   23251      * exception at measurement time.</p>
   23252      *
   23253      * @param measuredWidth The measured width of this view.  May be a complex
   23254      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   23255      * {@link #MEASURED_STATE_TOO_SMALL}.
   23256      * @param measuredHeight The measured height of this view.  May be a complex
   23257      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   23258      * {@link #MEASURED_STATE_TOO_SMALL}.
   23259      */
   23260     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
   23261         boolean optical = isLayoutModeOptical(this);
   23262         if (optical != isLayoutModeOptical(mParent)) {
   23263             Insets insets = getOpticalInsets();
   23264             int opticalWidth  = insets.left + insets.right;
   23265             int opticalHeight = insets.top  + insets.bottom;
   23266 
   23267             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
   23268             measuredHeight += optical ? opticalHeight : -opticalHeight;
   23269         }
   23270         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
   23271     }
   23272 
   23273     /**
   23274      * Sets the measured dimension without extra processing for things like optical bounds.
   23275      * Useful for reapplying consistent values that have already been cooked with adjustments
   23276      * for optical bounds, etc. such as those from the measurement cache.
   23277      *
   23278      * @param measuredWidth The measured width of this view.  May be a complex
   23279      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   23280      * {@link #MEASURED_STATE_TOO_SMALL}.
   23281      * @param measuredHeight The measured height of this view.  May be a complex
   23282      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   23283      * {@link #MEASURED_STATE_TOO_SMALL}.
   23284      */
   23285     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
   23286         mMeasuredWidth = measuredWidth;
   23287         mMeasuredHeight = measuredHeight;
   23288 
   23289         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
   23290     }
   23291 
   23292     /**
   23293      * Merge two states as returned by {@link #getMeasuredState()}.
   23294      * @param curState The current state as returned from a view or the result
   23295      * of combining multiple views.
   23296      * @param newState The new view state to combine.
   23297      * @return Returns a new integer reflecting the combination of the two
   23298      * states.
   23299      */
   23300     public static int combineMeasuredStates(int curState, int newState) {
   23301         return curState | newState;
   23302     }
   23303 
   23304     /**
   23305      * Version of {@link #resolveSizeAndState(int, int, int)}
   23306      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
   23307      */
   23308     public static int resolveSize(int size, int measureSpec) {
   23309         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
   23310     }
   23311 
   23312     /**
   23313      * Utility to reconcile a desired size and state, with constraints imposed
   23314      * by a MeasureSpec. Will take the desired size, unless a different size
   23315      * is imposed by the constraints. The returned value is a compound integer,
   23316      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
   23317      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
   23318      * resulting size is smaller than the size the view wants to be.
   23319      *
   23320      * @param size How big the view wants to be.
   23321      * @param measureSpec Constraints imposed by the parent.
   23322      * @param childMeasuredState Size information bit mask for the view's
   23323      *                           children.
   23324      * @return Size information bit mask as defined by
   23325      *         {@link #MEASURED_SIZE_MASK} and
   23326      *         {@link #MEASURED_STATE_TOO_SMALL}.
   23327      */
   23328     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
   23329         final int specMode = MeasureSpec.getMode(measureSpec);
   23330         final int specSize = MeasureSpec.getSize(measureSpec);
   23331         final int result;
   23332         switch (specMode) {
   23333             case MeasureSpec.AT_MOST:
   23334                 if (specSize < size) {
   23335                     result = specSize | MEASURED_STATE_TOO_SMALL;
   23336                 } else {
   23337                     result = size;
   23338                 }
   23339                 break;
   23340             case MeasureSpec.EXACTLY:
   23341                 result = specSize;
   23342                 break;
   23343             case MeasureSpec.UNSPECIFIED:
   23344             default:
   23345                 result = size;
   23346         }
   23347         return result | (childMeasuredState & MEASURED_STATE_MASK);
   23348     }
   23349 
   23350     /**
   23351      * Utility to return a default size. Uses the supplied size if the
   23352      * MeasureSpec imposed no constraints. Will get larger if allowed
   23353      * by the MeasureSpec.
   23354      *
   23355      * @param size Default size for this view
   23356      * @param measureSpec Constraints imposed by the parent
   23357      * @return The size this view should be.
   23358      */
   23359     public static int getDefaultSize(int size, int measureSpec) {
   23360         int result = size;
   23361         int specMode = MeasureSpec.getMode(measureSpec);
   23362         int specSize = MeasureSpec.getSize(measureSpec);
   23363 
   23364         switch (specMode) {
   23365         case MeasureSpec.UNSPECIFIED:
   23366             result = size;
   23367             break;
   23368         case MeasureSpec.AT_MOST:
   23369         case MeasureSpec.EXACTLY:
   23370             result = specSize;
   23371             break;
   23372         }
   23373         return result;
   23374     }
   23375 
   23376     /**
   23377      * Returns the suggested minimum height that the view should use. This
   23378      * returns the maximum of the view's minimum height
   23379      * and the background's minimum height
   23380      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
   23381      * <p>
   23382      * When being used in {@link #onMeasure(int, int)}, the caller should still
   23383      * ensure the returned height is within the requirements of the parent.
   23384      *
   23385      * @return The suggested minimum height of the view.
   23386      */
   23387     protected int getSuggestedMinimumHeight() {
   23388         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
   23389 
   23390     }
   23391 
   23392     /**
   23393      * Returns the suggested minimum width that the view should use. This
   23394      * returns the maximum of the view's minimum width
   23395      * and the background's minimum width
   23396      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
   23397      * <p>
   23398      * When being used in {@link #onMeasure(int, int)}, the caller should still
   23399      * ensure the returned width is within the requirements of the parent.
   23400      *
   23401      * @return The suggested minimum width of the view.
   23402      */
   23403     protected int getSuggestedMinimumWidth() {
   23404         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
   23405     }
   23406 
   23407     /**
   23408      * Returns the minimum height of the view.
   23409      *
   23410      * @return the minimum height the view will try to be, in pixels
   23411      *
   23412      * @see #setMinimumHeight(int)
   23413      *
   23414      * @attr ref android.R.styleable#View_minHeight
   23415      */
   23416     public int getMinimumHeight() {
   23417         return mMinHeight;
   23418     }
   23419 
   23420     /**
   23421      * Sets the minimum height of the view. It is not guaranteed the view will
   23422      * be able to achieve this minimum height (for example, if its parent layout
   23423      * constrains it with less available height).
   23424      *
   23425      * @param minHeight The minimum height the view will try to be, in pixels
   23426      *
   23427      * @see #getMinimumHeight()
   23428      *
   23429      * @attr ref android.R.styleable#View_minHeight
   23430      */
   23431     @RemotableViewMethod
   23432     public void setMinimumHeight(int minHeight) {
   23433         mMinHeight = minHeight;
   23434         requestLayout();
   23435     }
   23436 
   23437     /**
   23438      * Returns the minimum width of the view.
   23439      *
   23440      * @return the minimum width the view will try to be, in pixels
   23441      *
   23442      * @see #setMinimumWidth(int)
   23443      *
   23444      * @attr ref android.R.styleable#View_minWidth
   23445      */
   23446     public int getMinimumWidth() {
   23447         return mMinWidth;
   23448     }
   23449 
   23450     /**
   23451      * Sets the minimum width of the view. It is not guaranteed the view will
   23452      * be able to achieve this minimum width (for example, if its parent layout
   23453      * constrains it with less available width).
   23454      *
   23455      * @param minWidth The minimum width the view will try to be, in pixels
   23456      *
   23457      * @see #getMinimumWidth()
   23458      *
   23459      * @attr ref android.R.styleable#View_minWidth
   23460      */
   23461     public void setMinimumWidth(int minWidth) {
   23462         mMinWidth = minWidth;
   23463         requestLayout();
   23464 
   23465     }
   23466 
   23467     /**
   23468      * Get the animation currently associated with this view.
   23469      *
   23470      * @return The animation that is currently playing or
   23471      *         scheduled to play for this view.
   23472      */
   23473     public Animation getAnimation() {
   23474         return mCurrentAnimation;
   23475     }
   23476 
   23477     /**
   23478      * Start the specified animation now.
   23479      *
   23480      * @param animation the animation to start now
   23481      */
   23482     public void startAnimation(Animation animation) {
   23483         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
   23484         setAnimation(animation);
   23485         invalidateParentCaches();
   23486         invalidate(true);
   23487     }
   23488 
   23489     /**
   23490      * Cancels any animations for this view.
   23491      */
   23492     public void clearAnimation() {
   23493         if (mCurrentAnimation != null) {
   23494             mCurrentAnimation.detach();
   23495         }
   23496         mCurrentAnimation = null;
   23497         invalidateParentIfNeeded();
   23498     }
   23499 
   23500     /**
   23501      * Sets the next animation to play for this view.
   23502      * If you want the animation to play immediately, use
   23503      * {@link #startAnimation(android.view.animation.Animation)} instead.
   23504      * This method provides allows fine-grained
   23505      * control over the start time and invalidation, but you
   23506      * must make sure that 1) the animation has a start time set, and
   23507      * 2) the view's parent (which controls animations on its children)
   23508      * will be invalidated when the animation is supposed to
   23509      * start.
   23510      *
   23511      * @param animation The next animation, or null.
   23512      */
   23513     public void setAnimation(Animation animation) {
   23514         mCurrentAnimation = animation;
   23515 
   23516         if (animation != null) {
   23517             // If the screen is off assume the animation start time is now instead of
   23518             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
   23519             // would cause the animation to start when the screen turns back on
   23520             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
   23521                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
   23522                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
   23523             }
   23524             animation.reset();
   23525         }
   23526     }
   23527 
   23528     /**
   23529      * Invoked by a parent ViewGroup to notify the start of the animation
   23530      * currently associated with this view. If you override this method,
   23531      * always call super.onAnimationStart();
   23532      *
   23533      * @see #setAnimation(android.view.animation.Animation)
   23534      * @see #getAnimation()
   23535      */
   23536     @CallSuper
   23537     protected void onAnimationStart() {
   23538         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
   23539     }
   23540 
   23541     /**
   23542      * Invoked by a parent ViewGroup to notify the end of the animation
   23543      * currently associated with this view. If you override this method,
   23544      * always call super.onAnimationEnd();
   23545      *
   23546      * @see #setAnimation(android.view.animation.Animation)
   23547      * @see #getAnimation()
   23548      */
   23549     @CallSuper
   23550     protected void onAnimationEnd() {
   23551         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
   23552     }
   23553 
   23554     /**
   23555      * Invoked if there is a Transform that involves alpha. Subclass that can
   23556      * draw themselves with the specified alpha should return true, and then
   23557      * respect that alpha when their onDraw() is called. If this returns false
   23558      * then the view may be redirected to draw into an offscreen buffer to
   23559      * fulfill the request, which will look fine, but may be slower than if the
   23560      * subclass handles it internally. The default implementation returns false.
   23561      *
   23562      * @param alpha The alpha (0..255) to apply to the view's drawing
   23563      * @return true if the view can draw with the specified alpha.
   23564      */
   23565     protected boolean onSetAlpha(int alpha) {
   23566         return false;
   23567     }
   23568 
   23569     /**
   23570      * This is used by the RootView to perform an optimization when
   23571      * the view hierarchy contains one or several SurfaceView.
   23572      * SurfaceView is always considered transparent, but its children are not,
   23573      * therefore all View objects remove themselves from the global transparent
   23574      * region (passed as a parameter to this function).
   23575      *
   23576      * @param region The transparent region for this ViewAncestor (window).
   23577      *
   23578      * @return Returns true if the effective visibility of the view at this
   23579      * point is opaque, regardless of the transparent region; returns false
   23580      * if it is possible for underlying windows to be seen behind the view.
   23581      *
   23582      * {@hide}
   23583      */
   23584     public boolean gatherTransparentRegion(Region region) {
   23585         final AttachInfo attachInfo = mAttachInfo;
   23586         if (region != null && attachInfo != null) {
   23587             final int pflags = mPrivateFlags;
   23588             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
   23589                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
   23590                 // remove it from the transparent region.
   23591                 final int[] location = attachInfo.mTransparentLocation;
   23592                 getLocationInWindow(location);
   23593                 // When a view has Z value, then it will be better to leave some area below the view
   23594                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
   23595                 // the bottom part needs more offset than the left, top and right parts due to the
   23596                 // spot light effects.
   23597                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
   23598                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
   23599                         location[0] + mRight - mLeft + shadowOffset,
   23600                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
   23601             } else {
   23602                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
   23603                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
   23604                     // the background drawable's non-transparent parts from this transparent region.
   23605                     applyDrawableToTransparentRegion(mBackground, region);
   23606                 }
   23607                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   23608                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
   23609                     // Similarly, we remove the foreground drawable's non-transparent parts.
   23610                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
   23611                 }
   23612                 if (mDefaultFocusHighlight != null
   23613                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
   23614                     // Similarly, we remove the default focus highlight's non-transparent parts.
   23615                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
   23616                 }
   23617             }
   23618         }
   23619         return true;
   23620     }
   23621 
   23622     /**
   23623      * Play a sound effect for this view.
   23624      *
   23625      * <p>The framework will play sound effects for some built in actions, such as
   23626      * clicking, but you may wish to play these effects in your widget,
   23627      * for instance, for internal navigation.
   23628      *
   23629      * <p>The sound effect will only be played if sound effects are enabled by the user, and
   23630      * {@link #isSoundEffectsEnabled()} is true.
   23631      *
   23632      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
   23633      */
   23634     public void playSoundEffect(int soundConstant) {
   23635         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
   23636             return;
   23637         }
   23638         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
   23639     }
   23640 
   23641     /**
   23642      * BZZZTT!!1!
   23643      *
   23644      * <p>Provide haptic feedback to the user for this view.
   23645      *
   23646      * <p>The framework will provide haptic feedback for some built in actions,
   23647      * such as long presses, but you may wish to provide feedback for your
   23648      * own widget.
   23649      *
   23650      * <p>The feedback will only be performed if
   23651      * {@link #isHapticFeedbackEnabled()} is true.
   23652      *
   23653      * @param feedbackConstant One of the constants defined in
   23654      * {@link HapticFeedbackConstants}
   23655      */
   23656     public boolean performHapticFeedback(int feedbackConstant) {
   23657         return performHapticFeedback(feedbackConstant, 0);
   23658     }
   23659 
   23660     /**
   23661      * BZZZTT!!1!
   23662      *
   23663      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
   23664      *
   23665      * @param feedbackConstant One of the constants defined in
   23666      * {@link HapticFeedbackConstants}
   23667      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
   23668      */
   23669     public boolean performHapticFeedback(int feedbackConstant, int flags) {
   23670         if (mAttachInfo == null) {
   23671             return false;
   23672         }
   23673         //noinspection SimplifiableIfStatement
   23674         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
   23675                 && !isHapticFeedbackEnabled()) {
   23676             return false;
   23677         }
   23678         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
   23679                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
   23680     }
   23681 
   23682     /**
   23683      * Request that the visibility of the status bar or other screen/window
   23684      * decorations be changed.
   23685      *
   23686      * <p>This method is used to put the over device UI into temporary modes
   23687      * where the user's attention is focused more on the application content,
   23688      * by dimming or hiding surrounding system affordances.  This is typically
   23689      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   23690      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
   23691      * to be placed behind the action bar (and with these flags other system
   23692      * affordances) so that smooth transitions between hiding and showing them
   23693      * can be done.
   23694      *
   23695      * <p>Two representative examples of the use of system UI visibility is
   23696      * implementing a content browsing application (like a magazine reader)
   23697      * and a video playing application.
   23698      *
   23699      * <p>The first code shows a typical implementation of a View in a content
   23700      * browsing application.  In this implementation, the application goes
   23701      * into a content-oriented mode by hiding the status bar and action bar,
   23702      * and putting the navigation elements into lights out mode.  The user can
   23703      * then interact with content while in this mode.  Such an application should
   23704      * provide an easy way for the user to toggle out of the mode (such as to
   23705      * check information in the status bar or access notifications).  In the
   23706      * implementation here, this is done simply by tapping on the content.
   23707      *
   23708      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
   23709      *      content}
   23710      *
   23711      * <p>This second code sample shows a typical implementation of a View
   23712      * in a video playing application.  In this situation, while the video is
   23713      * playing the application would like to go into a complete full-screen mode,
   23714      * to use as much of the display as possible for the video.  When in this state
   23715      * the user can not interact with the application; the system intercepts
   23716      * touching on the screen to pop the UI out of full screen mode.  See
   23717      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
   23718      *
   23719      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
   23720      *      content}
   23721      *
   23722      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   23723      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   23724      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   23725      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   23726      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   23727      */
   23728     public void setSystemUiVisibility(int visibility) {
   23729         if (visibility != mSystemUiVisibility) {
   23730             mSystemUiVisibility = visibility;
   23731             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   23732                 mParent.recomputeViewAttributes(this);
   23733             }
   23734         }
   23735     }
   23736 
   23737     /**
   23738      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
   23739      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   23740      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   23741      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   23742      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   23743      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   23744      */
   23745     public int getSystemUiVisibility() {
   23746         return mSystemUiVisibility;
   23747     }
   23748 
   23749     /**
   23750      * Returns the current system UI visibility that is currently set for
   23751      * the entire window.  This is the combination of the
   23752      * {@link #setSystemUiVisibility(int)} values supplied by all of the
   23753      * views in the window.
   23754      */
   23755     public int getWindowSystemUiVisibility() {
   23756         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
   23757     }
   23758 
   23759     /**
   23760      * Override to find out when the window's requested system UI visibility
   23761      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
   23762      * This is different from the callbacks received through
   23763      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
   23764      * in that this is only telling you about the local request of the window,
   23765      * not the actual values applied by the system.
   23766      */
   23767     public void onWindowSystemUiVisibilityChanged(int visible) {
   23768     }
   23769 
   23770     /**
   23771      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
   23772      * the view hierarchy.
   23773      */
   23774     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
   23775         onWindowSystemUiVisibilityChanged(visible);
   23776     }
   23777 
   23778     /**
   23779      * Set a listener to receive callbacks when the visibility of the system bar changes.
   23780      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
   23781      */
   23782     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
   23783         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
   23784         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   23785             mParent.recomputeViewAttributes(this);
   23786         }
   23787     }
   23788 
   23789     /**
   23790      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
   23791      * the view hierarchy.
   23792      */
   23793     public void dispatchSystemUiVisibilityChanged(int visibility) {
   23794         ListenerInfo li = mListenerInfo;
   23795         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   23796             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
   23797                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
   23798         }
   23799     }
   23800 
   23801     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
   23802         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
   23803         if (val != mSystemUiVisibility) {
   23804             setSystemUiVisibility(val);
   23805             return true;
   23806         }
   23807         return false;
   23808     }
   23809 
   23810     /** @hide */
   23811     public void setDisabledSystemUiVisibility(int flags) {
   23812         if (mAttachInfo != null) {
   23813             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
   23814                 mAttachInfo.mDisabledSystemUiVisibility = flags;
   23815                 if (mParent != null) {
   23816                     mParent.recomputeViewAttributes(this);
   23817                 }
   23818             }
   23819         }
   23820     }
   23821 
   23822     /**
   23823      * Creates an image that the system displays during the drag and drop
   23824      * operation. This is called a &quot;drag shadow&quot;. The default implementation
   23825      * for a DragShadowBuilder based on a View returns an image that has exactly the same
   23826      * appearance as the given View. The default also positions the center of the drag shadow
   23827      * directly under the touch point. If no View is provided (the constructor with no parameters
   23828      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
   23829      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
   23830      * default is an invisible drag shadow.
   23831      * <p>
   23832      * You are not required to use the View you provide to the constructor as the basis of the
   23833      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
   23834      * anything you want as the drag shadow.
   23835      * </p>
   23836      * <p>
   23837      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
   23838      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
   23839      *  size and position of the drag shadow. It uses this data to construct a
   23840      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
   23841      *  so that your application can draw the shadow image in the Canvas.
   23842      * </p>
   23843      *
   23844      * <div class="special reference">
   23845      * <h3>Developer Guides</h3>
   23846      * <p>For a guide to implementing drag and drop features, read the
   23847      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   23848      * </div>
   23849      */
   23850     public static class DragShadowBuilder {
   23851         private final WeakReference<View> mView;
   23852 
   23853         /**
   23854          * Constructs a shadow image builder based on a View. By default, the resulting drag
   23855          * shadow will have the same appearance and dimensions as the View, with the touch point
   23856          * over the center of the View.
   23857          * @param view A View. Any View in scope can be used.
   23858          */
   23859         public DragShadowBuilder(View view) {
   23860             mView = new WeakReference<View>(view);
   23861         }
   23862 
   23863         /**
   23864          * Construct a shadow builder object with no associated View.  This
   23865          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
   23866          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
   23867          * to supply the drag shadow's dimensions and appearance without
   23868          * reference to any View object.
   23869          */
   23870         public DragShadowBuilder() {
   23871             mView = new WeakReference<View>(null);
   23872         }
   23873 
   23874         /**
   23875          * Returns the View object that had been passed to the
   23876          * {@link #View.DragShadowBuilder(View)}
   23877          * constructor.  If that View parameter was {@code null} or if the
   23878          * {@link #View.DragShadowBuilder()}
   23879          * constructor was used to instantiate the builder object, this method will return
   23880          * null.
   23881          *
   23882          * @return The View object associate with this builder object.
   23883          */
   23884         @SuppressWarnings({"JavadocReference"})
   23885         final public View getView() {
   23886             return mView.get();
   23887         }
   23888 
   23889         /**
   23890          * Provides the metrics for the shadow image. These include the dimensions of
   23891          * the shadow image, and the point within that shadow that should
   23892          * be centered under the touch location while dragging.
   23893          * <p>
   23894          * The default implementation sets the dimensions of the shadow to be the
   23895          * same as the dimensions of the View itself and centers the shadow under
   23896          * the touch point.
   23897          * </p>
   23898          *
   23899          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
   23900          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
   23901          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
   23902          * image.
   23903          *
   23904          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
   23905          * shadow image that should be underneath the touch point during the drag and drop
   23906          * operation. Your application must set {@link android.graphics.Point#x} to the
   23907          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
   23908          */
   23909         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
   23910             final View view = mView.get();
   23911             if (view != null) {
   23912                 outShadowSize.set(view.getWidth(), view.getHeight());
   23913                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
   23914             } else {
   23915                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
   23916             }
   23917         }
   23918 
   23919         /**
   23920          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
   23921          * based on the dimensions it received from the
   23922          * {@link #onProvideShadowMetrics(Point, Point)} callback.
   23923          *
   23924          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
   23925          */
   23926         public void onDrawShadow(Canvas canvas) {
   23927             final View view = mView.get();
   23928             if (view != null) {
   23929                 view.draw(canvas);
   23930             } else {
   23931                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
   23932             }
   23933         }
   23934     }
   23935 
   23936     /**
   23937      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
   23938      * startDragAndDrop()} for newer platform versions.
   23939      */
   23940     @Deprecated
   23941     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
   23942                                    Object myLocalState, int flags) {
   23943         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
   23944     }
   23945 
   23946     /**
   23947      * Starts a drag and drop operation. When your application calls this method, it passes a
   23948      * {@link android.view.View.DragShadowBuilder} object to the system. The
   23949      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
   23950      * to get metrics for the drag shadow, and then calls the object's
   23951      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
   23952      * <p>
   23953      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
   23954      *  drag events to all the View objects in your application that are currently visible. It does
   23955      *  this either by calling the View object's drag listener (an implementation of
   23956      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
   23957      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
   23958      *  Both are passed a {@link android.view.DragEvent} object that has a
   23959      *  {@link android.view.DragEvent#getAction()} value of
   23960      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
   23961      * </p>
   23962      * <p>
   23963      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
   23964      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
   23965      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
   23966      * to the View the user selected for dragging.
   23967      * </p>
   23968      * @param data A {@link android.content.ClipData} object pointing to the data to be
   23969      * transferred by the drag and drop operation.
   23970      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   23971      * drag shadow.
   23972      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
   23973      * drop operation. When dispatching drag events to views in the same activity this object
   23974      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
   23975      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
   23976      * will return null).
   23977      * <p>
   23978      * myLocalState is a lightweight mechanism for the sending information from the dragged View
   23979      * to the target Views. For example, it can contain flags that differentiate between a
   23980      * a copy operation and a move operation.
   23981      * </p>
   23982      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
   23983      * flags, or any combination of the following:
   23984      *     <ul>
   23985      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
   23986      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
   23987      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
   23988      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
   23989      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
   23990      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
   23991      *     </ul>
   23992      * @return {@code true} if the method completes successfully, or
   23993      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
   23994      * do a drag, and so no drag operation is in progress.
   23995      */
   23996     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
   23997             Object myLocalState, int flags) {
   23998         if (ViewDebug.DEBUG_DRAG) {
   23999             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
   24000         }
   24001         if (mAttachInfo == null) {
   24002             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
   24003             return false;
   24004         }
   24005 
   24006         if (data != null) {
   24007             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
   24008         }
   24009 
   24010         Point shadowSize = new Point();
   24011         Point shadowTouchPoint = new Point();
   24012         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
   24013 
   24014         if ((shadowSize.x < 0) || (shadowSize.y < 0)
   24015                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
   24016             throw new IllegalStateException("Drag shadow dimensions must not be negative");
   24017         }
   24018 
   24019         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
   24020         // does not accept zero size surface.
   24021         if (shadowSize.x == 0  || shadowSize.y == 0) {
   24022             if (!sAcceptZeroSizeDragShadow) {
   24023                 throw new IllegalStateException("Drag shadow dimensions must be positive");
   24024             }
   24025             shadowSize.x = 1;
   24026             shadowSize.y = 1;
   24027         }
   24028 
   24029         if (ViewDebug.DEBUG_DRAG) {
   24030             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
   24031                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
   24032         }
   24033         if (mAttachInfo.mDragSurface != null) {
   24034             mAttachInfo.mDragSurface.release();
   24035         }
   24036         mAttachInfo.mDragSurface = new Surface();
   24037         mAttachInfo.mDragToken = null;
   24038 
   24039         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
   24040         final SurfaceSession session = new SurfaceSession(root.mSurface);
   24041         final SurfaceControl surface = new SurfaceControl.Builder(session)
   24042                 .setName("drag surface")
   24043                 .setSize(shadowSize.x, shadowSize.y)
   24044                 .setFormat(PixelFormat.TRANSLUCENT)
   24045                 .build();
   24046         try {
   24047             mAttachInfo.mDragSurface.copyFrom(surface);
   24048             final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
   24049             try {
   24050                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   24051                 shadowBuilder.onDrawShadow(canvas);
   24052             } finally {
   24053                 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
   24054             }
   24055 
   24056             // Cache the local state object for delivery with DragEvents
   24057             root.setLocalDragState(myLocalState);
   24058 
   24059             // repurpose 'shadowSize' for the last touch point
   24060             root.getLastTouchPoint(shadowSize);
   24061 
   24062             mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag(
   24063                     mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(),
   24064                     shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
   24065             if (ViewDebug.DEBUG_DRAG) {
   24066                 Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken);
   24067             }
   24068 
   24069             return mAttachInfo.mDragToken != null;
   24070         } catch (Exception e) {
   24071             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
   24072             return false;
   24073         } finally {
   24074             if (mAttachInfo.mDragToken == null) {
   24075                 mAttachInfo.mDragSurface.destroy();
   24076                 mAttachInfo.mDragSurface = null;
   24077                 root.setLocalDragState(null);
   24078             }
   24079             session.kill();
   24080         }
   24081     }
   24082 
   24083     /**
   24084      * Cancels an ongoing drag and drop operation.
   24085      * <p>
   24086      * A {@link android.view.DragEvent} object with
   24087      * {@link android.view.DragEvent#getAction()} value of
   24088      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
   24089      * {@link android.view.DragEvent#getResult()} value of {@code false}
   24090      * will be sent to every
   24091      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
   24092      * even if they are not currently visible.
   24093      * </p>
   24094      * <p>
   24095      * This method can be called on any View in the same window as the View on which
   24096      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
   24097      * was called.
   24098      * </p>
   24099      */
   24100     public final void cancelDragAndDrop() {
   24101         if (ViewDebug.DEBUG_DRAG) {
   24102             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
   24103         }
   24104         if (mAttachInfo == null) {
   24105             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
   24106             return;
   24107         }
   24108         if (mAttachInfo.mDragToken != null) {
   24109             try {
   24110                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
   24111             } catch (Exception e) {
   24112                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
   24113             }
   24114             mAttachInfo.mDragToken = null;
   24115         } else {
   24116             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
   24117         }
   24118     }
   24119 
   24120     /**
   24121      * Updates the drag shadow for the ongoing drag and drop operation.
   24122      *
   24123      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   24124      * new drag shadow.
   24125      */
   24126     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
   24127         if (ViewDebug.DEBUG_DRAG) {
   24128             Log.d(VIEW_LOG_TAG, "updateDragShadow");
   24129         }
   24130         if (mAttachInfo == null) {
   24131             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
   24132             return;
   24133         }
   24134         if (mAttachInfo.mDragToken != null) {
   24135             try {
   24136                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
   24137                 try {
   24138                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   24139                     shadowBuilder.onDrawShadow(canvas);
   24140                 } finally {
   24141                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
   24142                 }
   24143             } catch (Exception e) {
   24144                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
   24145             }
   24146         } else {
   24147             Log.e(VIEW_LOG_TAG, "No active drag");
   24148         }
   24149     }
   24150 
   24151     /**
   24152      * Starts a move from {startX, startY}, the amount of the movement will be the offset
   24153      * between {startX, startY} and the new cursor positon.
   24154      * @param startX horizontal coordinate where the move started.
   24155      * @param startY vertical coordinate where the move started.
   24156      * @return whether moving was started successfully.
   24157      * @hide
   24158      */
   24159     public final boolean startMovingTask(float startX, float startY) {
   24160         if (ViewDebug.DEBUG_POSITIONING) {
   24161             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
   24162         }
   24163         try {
   24164             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
   24165         } catch (RemoteException e) {
   24166             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
   24167         }
   24168         return false;
   24169     }
   24170 
   24171     /**
   24172      * Handles drag events sent by the system following a call to
   24173      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
   24174      * startDragAndDrop()}.
   24175      *<p>
   24176      * When the system calls this method, it passes a
   24177      * {@link android.view.DragEvent} object. A call to
   24178      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
   24179      * in DragEvent. The method uses these to determine what is happening in the drag and drop
   24180      * operation.
   24181      * @param event The {@link android.view.DragEvent} sent by the system.
   24182      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
   24183      * in DragEvent, indicating the type of drag event represented by this object.
   24184      * @return {@code true} if the method was successful, otherwise {@code false}.
   24185      * <p>
   24186      *  The method should return {@code true} in response to an action type of
   24187      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
   24188      *  operation.
   24189      * </p>
   24190      * <p>
   24191      *  The method should also return {@code true} in response to an action type of
   24192      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
   24193      *  {@code false} if it didn't.
   24194      * </p>
   24195      * <p>
   24196      *  For all other events, the return value is ignored.
   24197      * </p>
   24198      */
   24199     public boolean onDragEvent(DragEvent event) {
   24200         return false;
   24201     }
   24202 
   24203     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
   24204     boolean dispatchDragEnterExitInPreN(DragEvent event) {
   24205         return callDragEventHandler(event);
   24206     }
   24207 
   24208     /**
   24209      * Detects if this View is enabled and has a drag event listener.
   24210      * If both are true, then it calls the drag event listener with the
   24211      * {@link android.view.DragEvent} it received. If the drag event listener returns
   24212      * {@code true}, then dispatchDragEvent() returns {@code true}.
   24213      * <p>
   24214      * For all other cases, the method calls the
   24215      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
   24216      * method and returns its result.
   24217      * </p>
   24218      * <p>
   24219      * This ensures that a drag event is always consumed, even if the View does not have a drag
   24220      * event listener. However, if the View has a listener and the listener returns true, then
   24221      * onDragEvent() is not called.
   24222      * </p>
   24223      */
   24224     public boolean dispatchDragEvent(DragEvent event) {
   24225         event.mEventHandlerWasCalled = true;
   24226         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
   24227             event.mAction == DragEvent.ACTION_DROP) {
   24228             // About to deliver an event with coordinates to this view. Notify that now this view
   24229             // has drag focus. This will send exit/enter events as needed.
   24230             getViewRootImpl().setDragFocus(this, event);
   24231         }
   24232         return callDragEventHandler(event);
   24233     }
   24234 
   24235     final boolean callDragEventHandler(DragEvent event) {
   24236         final boolean result;
   24237 
   24238         ListenerInfo li = mListenerInfo;
   24239         //noinspection SimplifiableIfStatement
   24240         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   24241                 && li.mOnDragListener.onDrag(this, event)) {
   24242             result = true;
   24243         } else {
   24244             result = onDragEvent(event);
   24245         }
   24246 
   24247         switch (event.mAction) {
   24248             case DragEvent.ACTION_DRAG_ENTERED: {
   24249                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
   24250                 refreshDrawableState();
   24251             } break;
   24252             case DragEvent.ACTION_DRAG_EXITED: {
   24253                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
   24254                 refreshDrawableState();
   24255             } break;
   24256             case DragEvent.ACTION_DRAG_ENDED: {
   24257                 mPrivateFlags2 &= ~View.DRAG_MASK;
   24258                 refreshDrawableState();
   24259             } break;
   24260         }
   24261 
   24262         return result;
   24263     }
   24264 
   24265     boolean canAcceptDrag() {
   24266         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
   24267     }
   24268 
   24269     /**
   24270      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
   24271      * it is ever exposed at all.
   24272      * @hide
   24273      */
   24274     public void onCloseSystemDialogs(String reason) {
   24275     }
   24276 
   24277     /**
   24278      * Given a Drawable whose bounds have been set to draw into this view,
   24279      * update a Region being computed for
   24280      * {@link #gatherTransparentRegion(android.graphics.Region)} so
   24281      * that any non-transparent parts of the Drawable are removed from the
   24282      * given transparent region.
   24283      *
   24284      * @param dr The Drawable whose transparency is to be applied to the region.
   24285      * @param region A Region holding the current transparency information,
   24286      * where any parts of the region that are set are considered to be
   24287      * transparent.  On return, this region will be modified to have the
   24288      * transparency information reduced by the corresponding parts of the
   24289      * Drawable that are not transparent.
   24290      * {@hide}
   24291      */
   24292     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
   24293         if (DBG) {
   24294             Log.i("View", "Getting transparent region for: " + this);
   24295         }
   24296         final Region r = dr.getTransparentRegion();
   24297         final Rect db = dr.getBounds();
   24298         final AttachInfo attachInfo = mAttachInfo;
   24299         if (r != null && attachInfo != null) {
   24300             final int w = getRight()-getLeft();
   24301             final int h = getBottom()-getTop();
   24302             if (db.left > 0) {
   24303                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
   24304                 r.op(0, 0, db.left, h, Region.Op.UNION);
   24305             }
   24306             if (db.right < w) {
   24307                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
   24308                 r.op(db.right, 0, w, h, Region.Op.UNION);
   24309             }
   24310             if (db.top > 0) {
   24311                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
   24312                 r.op(0, 0, w, db.top, Region.Op.UNION);
   24313             }
   24314             if (db.bottom < h) {
   24315                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
   24316                 r.op(0, db.bottom, w, h, Region.Op.UNION);
   24317             }
   24318             final int[] location = attachInfo.mTransparentLocation;
   24319             getLocationInWindow(location);
   24320             r.translate(location[0], location[1]);
   24321             region.op(r, Region.Op.INTERSECT);
   24322         } else {
   24323             region.op(db, Region.Op.DIFFERENCE);
   24324         }
   24325     }
   24326 
   24327     private void checkForLongClick(int delayOffset, float x, float y) {
   24328         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
   24329             mHasPerformedLongPress = false;
   24330 
   24331             if (mPendingCheckForLongPress == null) {
   24332                 mPendingCheckForLongPress = new CheckForLongPress();
   24333             }
   24334             mPendingCheckForLongPress.setAnchor(x, y);
   24335             mPendingCheckForLongPress.rememberWindowAttachCount();
   24336             mPendingCheckForLongPress.rememberPressedState();
   24337             postDelayed(mPendingCheckForLongPress,
   24338                     ViewConfiguration.getLongPressTimeout() - delayOffset);
   24339         }
   24340     }
   24341 
   24342     /**
   24343      * Inflate a view from an XML resource.  This convenience method wraps the {@link
   24344      * LayoutInflater} class, which provides a full range of options for view inflation.
   24345      *
   24346      * @param context The Context object for your activity or application.
   24347      * @param resource The resource ID to inflate
   24348      * @param root A view group that will be the parent.  Used to properly inflate the
   24349      * layout_* parameters.
   24350      * @see LayoutInflater
   24351      */
   24352     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
   24353         LayoutInflater factory = LayoutInflater.from(context);
   24354         return factory.inflate(resource, root);
   24355     }
   24356 
   24357     /**
   24358      * Scroll the view with standard behavior for scrolling beyond the normal
   24359      * content boundaries. Views that call this method should override
   24360      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
   24361      * results of an over-scroll operation.
   24362      *
   24363      * Views can use this method to handle any touch or fling-based scrolling.
   24364      *
   24365      * @param deltaX Change in X in pixels
   24366      * @param deltaY Change in Y in pixels
   24367      * @param scrollX Current X scroll value in pixels before applying deltaX
   24368      * @param scrollY Current Y scroll value in pixels before applying deltaY
   24369      * @param scrollRangeX Maximum content scroll range along the X axis
   24370      * @param scrollRangeY Maximum content scroll range along the Y axis
   24371      * @param maxOverScrollX Number of pixels to overscroll by in either direction
   24372      *          along the X axis.
   24373      * @param maxOverScrollY Number of pixels to overscroll by in either direction
   24374      *          along the Y axis.
   24375      * @param isTouchEvent true if this scroll operation is the result of a touch event.
   24376      * @return true if scrolling was clamped to an over-scroll boundary along either
   24377      *          axis, false otherwise.
   24378      */
   24379     @SuppressWarnings({"UnusedParameters"})
   24380     protected boolean overScrollBy(int deltaX, int deltaY,
   24381             int scrollX, int scrollY,
   24382             int scrollRangeX, int scrollRangeY,
   24383             int maxOverScrollX, int maxOverScrollY,
   24384             boolean isTouchEvent) {
   24385         final int overScrollMode = mOverScrollMode;
   24386         final boolean canScrollHorizontal =
   24387                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
   24388         final boolean canScrollVertical =
   24389                 computeVerticalScrollRange() > computeVerticalScrollExtent();
   24390         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
   24391                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
   24392         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
   24393                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
   24394 
   24395         int newScrollX = scrollX + deltaX;
   24396         if (!overScrollHorizontal) {
   24397             maxOverScrollX = 0;
   24398         }
   24399 
   24400         int newScrollY = scrollY + deltaY;
   24401         if (!overScrollVertical) {
   24402             maxOverScrollY = 0;
   24403         }
   24404 
   24405         // Clamp values if at the limits and record
   24406         final int left = -maxOverScrollX;
   24407         final int right = maxOverScrollX + scrollRangeX;
   24408         final int top = -maxOverScrollY;
   24409         final int bottom = maxOverScrollY + scrollRangeY;
   24410 
   24411         boolean clampedX = false;
   24412         if (newScrollX > right) {
   24413             newScrollX = right;
   24414             clampedX = true;
   24415         } else if (newScrollX < left) {
   24416             newScrollX = left;
   24417             clampedX = true;
   24418         }
   24419 
   24420         boolean clampedY = false;
   24421         if (newScrollY > bottom) {
   24422             newScrollY = bottom;
   24423             clampedY = true;
   24424         } else if (newScrollY < top) {
   24425             newScrollY = top;
   24426             clampedY = true;
   24427         }
   24428 
   24429         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
   24430 
   24431         return clampedX || clampedY;
   24432     }
   24433 
   24434     /**
   24435      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
   24436      * respond to the results of an over-scroll operation.
   24437      *
   24438      * @param scrollX New X scroll value in pixels
   24439      * @param scrollY New Y scroll value in pixels
   24440      * @param clampedX True if scrollX was clamped to an over-scroll boundary
   24441      * @param clampedY True if scrollY was clamped to an over-scroll boundary
   24442      */
   24443     protected void onOverScrolled(int scrollX, int scrollY,
   24444             boolean clampedX, boolean clampedY) {
   24445         // Intentionally empty.
   24446     }
   24447 
   24448     /**
   24449      * Returns the over-scroll mode for this view. The result will be
   24450      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   24451      * (allow over-scrolling only if the view content is larger than the container),
   24452      * or {@link #OVER_SCROLL_NEVER}.
   24453      *
   24454      * @return This view's over-scroll mode.
   24455      */
   24456     public int getOverScrollMode() {
   24457         return mOverScrollMode;
   24458     }
   24459 
   24460     /**
   24461      * Set the over-scroll mode for this view. Valid over-scroll modes are
   24462      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   24463      * (allow over-scrolling only if the view content is larger than the container),
   24464      * or {@link #OVER_SCROLL_NEVER}.
   24465      *
   24466      * Setting the over-scroll mode of a view will have an effect only if the
   24467      * view is capable of scrolling.
   24468      *
   24469      * @param overScrollMode The new over-scroll mode for this view.
   24470      */
   24471     public void setOverScrollMode(int overScrollMode) {
   24472         if (overScrollMode != OVER_SCROLL_ALWAYS &&
   24473                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
   24474                 overScrollMode != OVER_SCROLL_NEVER) {
   24475             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
   24476         }
   24477         mOverScrollMode = overScrollMode;
   24478     }
   24479 
   24480     /**
   24481      * Enable or disable nested scrolling for this view.
   24482      *
   24483      * <p>If this property is set to true the view will be permitted to initiate nested
   24484      * scrolling operations with a compatible parent view in the current hierarchy. If this
   24485      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
   24486      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
   24487      * the nested scroll.</p>
   24488      *
   24489      * @param enabled true to enable nested scrolling, false to disable
   24490      *
   24491      * @see #isNestedScrollingEnabled()
   24492      */
   24493     public void setNestedScrollingEnabled(boolean enabled) {
   24494         if (enabled) {
   24495             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
   24496         } else {
   24497             stopNestedScroll();
   24498             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
   24499         }
   24500     }
   24501 
   24502     /**
   24503      * Returns true if nested scrolling is enabled for this view.
   24504      *
   24505      * <p>If nested scrolling is enabled and this View class implementation supports it,
   24506      * this view will act as a nested scrolling child view when applicable, forwarding data
   24507      * about the scroll operation in progress to a compatible and cooperating nested scrolling
   24508      * parent.</p>
   24509      *
   24510      * @return true if nested scrolling is enabled
   24511      *
   24512      * @see #setNestedScrollingEnabled(boolean)
   24513      */
   24514     public boolean isNestedScrollingEnabled() {
   24515         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
   24516                 PFLAG3_NESTED_SCROLLING_ENABLED;
   24517     }
   24518 
   24519     /**
   24520      * Begin a nestable scroll operation along the given axes.
   24521      *
   24522      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
   24523      *
   24524      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
   24525      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
   24526      * In the case of touch scrolling the nested scroll will be terminated automatically in
   24527      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
   24528      * In the event of programmatic scrolling the caller must explicitly call
   24529      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
   24530      *
   24531      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
   24532      * If it returns false the caller may ignore the rest of this contract until the next scroll.
   24533      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
   24534      *
   24535      * <p>At each incremental step of the scroll the caller should invoke
   24536      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
   24537      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
   24538      * parent at least partially consumed the scroll and the caller should adjust the amount it
   24539      * scrolls by.</p>
   24540      *
   24541      * <p>After applying the remainder of the scroll delta the caller should invoke
   24542      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
   24543      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
   24544      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
   24545      * </p>
   24546      *
   24547      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
   24548      *             {@link #SCROLL_AXIS_VERTICAL}.
   24549      * @return true if a cooperative parent was found and nested scrolling has been enabled for
   24550      *         the current gesture.
   24551      *
   24552      * @see #stopNestedScroll()
   24553      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   24554      * @see #dispatchNestedScroll(int, int, int, int, int[])
   24555      */
   24556     public boolean startNestedScroll(int axes) {
   24557         if (hasNestedScrollingParent()) {
   24558             // Already in progress
   24559             return true;
   24560         }
   24561         if (isNestedScrollingEnabled()) {
   24562             ViewParent p = getParent();
   24563             View child = this;
   24564             while (p != null) {
   24565                 try {
   24566                     if (p.onStartNestedScroll(child, this, axes)) {
   24567                         mNestedScrollingParent = p;
   24568                         p.onNestedScrollAccepted(child, this, axes);
   24569                         return true;
   24570                     }
   24571                 } catch (AbstractMethodError e) {
   24572                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
   24573                             "method onStartNestedScroll", e);
   24574                     // Allow the search upward to continue
   24575                 }
   24576                 if (p instanceof View) {
   24577                     child = (View) p;
   24578                 }
   24579                 p = p.getParent();
   24580             }
   24581         }
   24582         return false;
   24583     }
   24584 
   24585     /**
   24586      * Stop a nested scroll in progress.
   24587      *
   24588      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
   24589      *
   24590      * @see #startNestedScroll(int)
   24591      */
   24592     public void stopNestedScroll() {
   24593         if (mNestedScrollingParent != null) {
   24594             mNestedScrollingParent.onStopNestedScroll(this);
   24595             mNestedScrollingParent = null;
   24596         }
   24597     }
   24598 
   24599     /**
   24600      * Returns true if this view has a nested scrolling parent.
   24601      *
   24602      * <p>The presence of a nested scrolling parent indicates that this view has initiated
   24603      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
   24604      *
   24605      * @return whether this view has a nested scrolling parent
   24606      */
   24607     public boolean hasNestedScrollingParent() {
   24608         return mNestedScrollingParent != null;
   24609     }
   24610 
   24611     /**
   24612      * Dispatch one step of a nested scroll in progress.
   24613      *
   24614      * <p>Implementations of views that support nested scrolling should call this to report
   24615      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
   24616      * is not currently in progress or nested scrolling is not
   24617      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
   24618      *
   24619      * <p>Compatible View implementations should also call
   24620      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
   24621      * consuming a component of the scroll event themselves.</p>
   24622      *
   24623      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
   24624      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
   24625      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
   24626      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
   24627      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   24628      *                       in local view coordinates of this view from before this operation
   24629      *                       to after it completes. View implementations may use this to adjust
   24630      *                       expected input coordinate tracking.
   24631      * @return true if the event was dispatched, false if it could not be dispatched.
   24632      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   24633      */
   24634     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
   24635             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
   24636         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   24637             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
   24638                 int startX = 0;
   24639                 int startY = 0;
   24640                 if (offsetInWindow != null) {
   24641                     getLocationInWindow(offsetInWindow);
   24642                     startX = offsetInWindow[0];
   24643                     startY = offsetInWindow[1];
   24644                 }
   24645 
   24646                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
   24647                         dxUnconsumed, dyUnconsumed);
   24648 
   24649                 if (offsetInWindow != null) {
   24650                     getLocationInWindow(offsetInWindow);
   24651                     offsetInWindow[0] -= startX;
   24652                     offsetInWindow[1] -= startY;
   24653                 }
   24654                 return true;
   24655             } else if (offsetInWindow != null) {
   24656                 // No motion, no dispatch. Keep offsetInWindow up to date.
   24657                 offsetInWindow[0] = 0;
   24658                 offsetInWindow[1] = 0;
   24659             }
   24660         }
   24661         return false;
   24662     }
   24663 
   24664     /**
   24665      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
   24666      *
   24667      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
   24668      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
   24669      * scrolling operation to consume some or all of the scroll operation before the child view
   24670      * consumes it.</p>
   24671      *
   24672      * @param dx Horizontal scroll distance in pixels
   24673      * @param dy Vertical scroll distance in pixels
   24674      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
   24675      *                 and consumed[1] the consumed dy.
   24676      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   24677      *                       in local view coordinates of this view from before this operation
   24678      *                       to after it completes. View implementations may use this to adjust
   24679      *                       expected input coordinate tracking.
   24680      * @return true if the parent consumed some or all of the scroll delta
   24681      * @see #dispatchNestedScroll(int, int, int, int, int[])
   24682      */
   24683     public boolean dispatchNestedPreScroll(int dx, int dy,
   24684             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
   24685         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   24686             if (dx != 0 || dy != 0) {
   24687                 int startX = 0;
   24688                 int startY = 0;
   24689                 if (offsetInWindow != null) {
   24690                     getLocationInWindow(offsetInWindow);
   24691                     startX = offsetInWindow[0];
   24692                     startY = offsetInWindow[1];
   24693                 }
   24694 
   24695                 if (consumed == null) {
   24696                     if (mTempNestedScrollConsumed == null) {
   24697                         mTempNestedScrollConsumed = new int[2];
   24698                     }
   24699                     consumed = mTempNestedScrollConsumed;
   24700                 }
   24701                 consumed[0] = 0;
   24702                 consumed[1] = 0;
   24703                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
   24704 
   24705                 if (offsetInWindow != null) {
   24706                     getLocationInWindow(offsetInWindow);
   24707                     offsetInWindow[0] -= startX;
   24708                     offsetInWindow[1] -= startY;
   24709                 }
   24710                 return consumed[0] != 0 || consumed[1] != 0;
   24711             } else if (offsetInWindow != null) {
   24712                 offsetInWindow[0] = 0;
   24713                 offsetInWindow[1] = 0;
   24714             }
   24715         }
   24716         return false;
   24717     }
   24718 
   24719     /**
   24720      * Dispatch a fling to a nested scrolling parent.
   24721      *
   24722      * <p>This method should be used to indicate that a nested scrolling child has detected
   24723      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
   24724      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
   24725      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
   24726      * along a scrollable axis.</p>
   24727      *
   24728      * <p>If a nested scrolling child view would normally fling but it is at the edge of
   24729      * its own content, it can use this method to delegate the fling to its nested scrolling
   24730      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
   24731      *
   24732      * @param velocityX Horizontal fling velocity in pixels per second
   24733      * @param velocityY Vertical fling velocity in pixels per second
   24734      * @param consumed true if the child consumed the fling, false otherwise
   24735      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
   24736      */
   24737     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
   24738         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   24739             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
   24740         }
   24741         return false;
   24742     }
   24743 
   24744     /**
   24745      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
   24746      *
   24747      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
   24748      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
   24749      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
   24750      * before the child view consumes it. If this method returns <code>true</code>, a nested
   24751      * parent view consumed the fling and this view should not scroll as a result.</p>
   24752      *
   24753      * <p>For a better user experience, only one view in a nested scrolling chain should consume
   24754      * the fling at a time. If a parent view consumed the fling this method will return false.
   24755      * Custom view implementations should account for this in two ways:</p>
   24756      *
   24757      * <ul>
   24758      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
   24759      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
   24760      *     position regardless.</li>
   24761      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
   24762      *     even to settle back to a valid idle position.</li>
   24763      * </ul>
   24764      *
   24765      * <p>Views should also not offer fling velocities to nested parent views along an axis
   24766      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
   24767      * should not offer a horizontal fling velocity to its parents since scrolling along that
   24768      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
   24769      *
   24770      * @param velocityX Horizontal fling velocity in pixels per second
   24771      * @param velocityY Vertical fling velocity in pixels per second
   24772      * @return true if a nested scrolling parent consumed the fling
   24773      */
   24774     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
   24775         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   24776             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
   24777         }
   24778         return false;
   24779     }
   24780 
   24781     /**
   24782      * Gets a scale factor that determines the distance the view should scroll
   24783      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
   24784      * @return The vertical scroll scale factor.
   24785      * @hide
   24786      */
   24787     protected float getVerticalScrollFactor() {
   24788         if (mVerticalScrollFactor == 0) {
   24789             TypedValue outValue = new TypedValue();
   24790             if (!mContext.getTheme().resolveAttribute(
   24791                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
   24792                 throw new IllegalStateException(
   24793                         "Expected theme to define listPreferredItemHeight.");
   24794             }
   24795             mVerticalScrollFactor = outValue.getDimension(
   24796                     mContext.getResources().getDisplayMetrics());
   24797         }
   24798         return mVerticalScrollFactor;
   24799     }
   24800 
   24801     /**
   24802      * Gets a scale factor that determines the distance the view should scroll
   24803      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
   24804      * @return The horizontal scroll scale factor.
   24805      * @hide
   24806      */
   24807     protected float getHorizontalScrollFactor() {
   24808         // TODO: Should use something else.
   24809         return getVerticalScrollFactor();
   24810     }
   24811 
   24812     /**
   24813      * Return the value specifying the text direction or policy that was set with
   24814      * {@link #setTextDirection(int)}.
   24815      *
   24816      * @return the defined text direction. It can be one of:
   24817      *
   24818      * {@link #TEXT_DIRECTION_INHERIT},
   24819      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   24820      * {@link #TEXT_DIRECTION_ANY_RTL},
   24821      * {@link #TEXT_DIRECTION_LTR},
   24822      * {@link #TEXT_DIRECTION_RTL},
   24823      * {@link #TEXT_DIRECTION_LOCALE},
   24824      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   24825      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   24826      *
   24827      * @attr ref android.R.styleable#View_textDirection
   24828      *
   24829      * @hide
   24830      */
   24831     @ViewDebug.ExportedProperty(category = "text", mapping = {
   24832             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   24833             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   24834             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   24835             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   24836             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   24837             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   24838             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   24839             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   24840     })
   24841     public int getRawTextDirection() {
   24842         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   24843     }
   24844 
   24845     /**
   24846      * Set the text direction.
   24847      *
   24848      * @param textDirection the direction to set. Should be one of:
   24849      *
   24850      * {@link #TEXT_DIRECTION_INHERIT},
   24851      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   24852      * {@link #TEXT_DIRECTION_ANY_RTL},
   24853      * {@link #TEXT_DIRECTION_LTR},
   24854      * {@link #TEXT_DIRECTION_RTL},
   24855      * {@link #TEXT_DIRECTION_LOCALE}
   24856      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   24857      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
   24858      *
   24859      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
   24860      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
   24861      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
   24862      *
   24863      * @attr ref android.R.styleable#View_textDirection
   24864      */
   24865     public void setTextDirection(int textDirection) {
   24866         if (getRawTextDirection() != textDirection) {
   24867             // Reset the current text direction and the resolved one
   24868             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   24869             resetResolvedTextDirection();
   24870             // Set the new text direction
   24871             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
   24872             // Do resolution
   24873             resolveTextDirection();
   24874             // Notify change
   24875             onRtlPropertiesChanged(getLayoutDirection());
   24876             // Refresh
   24877             requestLayout();
   24878             invalidate(true);
   24879         }
   24880     }
   24881 
   24882     /**
   24883      * Return the resolved text direction.
   24884      *
   24885      * @return the resolved text direction. Returns one of:
   24886      *
   24887      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   24888      * {@link #TEXT_DIRECTION_ANY_RTL},
   24889      * {@link #TEXT_DIRECTION_LTR},
   24890      * {@link #TEXT_DIRECTION_RTL},
   24891      * {@link #TEXT_DIRECTION_LOCALE},
   24892      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   24893      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   24894      *
   24895      * @attr ref android.R.styleable#View_textDirection
   24896      */
   24897     @ViewDebug.ExportedProperty(category = "text", mapping = {
   24898             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   24899             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   24900             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   24901             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   24902             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   24903             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   24904             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   24905             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   24906     })
   24907     public int getTextDirection() {
   24908         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   24909     }
   24910 
   24911     /**
   24912      * Resolve the text direction.
   24913      *
   24914      * @return true if resolution has been done, false otherwise.
   24915      *
   24916      * @hide
   24917      */
   24918     public boolean resolveTextDirection() {
   24919         // Reset any previous text direction resolution
   24920         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   24921 
   24922         if (hasRtlSupport()) {
   24923             // Set resolved text direction flag depending on text direction flag
   24924             final int textDirection = getRawTextDirection();
   24925             switch(textDirection) {
   24926                 case TEXT_DIRECTION_INHERIT:
   24927                     if (!canResolveTextDirection()) {
   24928                         // We cannot do the resolution if there is no parent, so use the default one
   24929                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   24930                         // Resolution will need to happen again later
   24931                         return false;
   24932                     }
   24933 
   24934                     // Parent has not yet resolved, so we still return the default
   24935                     try {
   24936                         if (!mParent.isTextDirectionResolved()) {
   24937                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   24938                             // Resolution will need to happen again later
   24939                             return false;
   24940                         }
   24941                     } catch (AbstractMethodError e) {
   24942                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   24943                                 " does not fully implement ViewParent", e);
   24944                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
   24945                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   24946                         return true;
   24947                     }
   24948 
   24949                     // Set current resolved direction to the same value as the parent's one
   24950                     int parentResolvedDirection;
   24951                     try {
   24952                         parentResolvedDirection = mParent.getTextDirection();
   24953                     } catch (AbstractMethodError e) {
   24954                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   24955                                 " does not fully implement ViewParent", e);
   24956                         parentResolvedDirection = TEXT_DIRECTION_LTR;
   24957                     }
   24958                     switch (parentResolvedDirection) {
   24959                         case TEXT_DIRECTION_FIRST_STRONG:
   24960                         case TEXT_DIRECTION_ANY_RTL:
   24961                         case TEXT_DIRECTION_LTR:
   24962                         case TEXT_DIRECTION_RTL:
   24963                         case TEXT_DIRECTION_LOCALE:
   24964                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
   24965                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
   24966                             mPrivateFlags2 |=
   24967                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   24968                             break;
   24969                         default:
   24970                             // Default resolved direction is "first strong" heuristic
   24971                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   24972                     }
   24973                     break;
   24974                 case TEXT_DIRECTION_FIRST_STRONG:
   24975                 case TEXT_DIRECTION_ANY_RTL:
   24976                 case TEXT_DIRECTION_LTR:
   24977                 case TEXT_DIRECTION_RTL:
   24978                 case TEXT_DIRECTION_LOCALE:
   24979                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
   24980                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
   24981                     // Resolved direction is the same as text direction
   24982                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   24983                     break;
   24984                 default:
   24985                     // Default resolved direction is "first strong" heuristic
   24986                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   24987             }
   24988         } else {
   24989             // Default resolved direction is "first strong" heuristic
   24990             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   24991         }
   24992 
   24993         // Set to resolved
   24994         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
   24995         return true;
   24996     }
   24997 
   24998     /**
   24999      * Check if text direction resolution can be done.
   25000      *
   25001      * @return true if text direction resolution can be done otherwise return false.
   25002      */
   25003     public boolean canResolveTextDirection() {
   25004         switch (getRawTextDirection()) {
   25005             case TEXT_DIRECTION_INHERIT:
   25006                 if (mParent != null) {
   25007                     try {
   25008                         return mParent.canResolveTextDirection();
   25009                     } catch (AbstractMethodError e) {
   25010                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   25011                                 " does not fully implement ViewParent", e);
   25012                     }
   25013                 }
   25014                 return false;
   25015 
   25016             default:
   25017                 return true;
   25018         }
   25019     }
   25020 
   25021     /**
   25022      * Reset resolved text direction. Text direction will be resolved during a call to
   25023      * {@link #onMeasure(int, int)}.
   25024      *
   25025      * @hide
   25026      */
   25027     public void resetResolvedTextDirection() {
   25028         // Reset any previous text direction resolution
   25029         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   25030         // Set to default value
   25031         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   25032     }
   25033 
   25034     /**
   25035      * @return true if text direction is inherited.
   25036      *
   25037      * @hide
   25038      */
   25039     public boolean isTextDirectionInherited() {
   25040         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
   25041     }
   25042 
   25043     /**
   25044      * @return true if text direction is resolved.
   25045      */
   25046     public boolean isTextDirectionResolved() {
   25047         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
   25048     }
   25049 
   25050     /**
   25051      * Return the value specifying the text alignment or policy that was set with
   25052      * {@link #setTextAlignment(int)}.
   25053      *
   25054      * @return the defined text alignment. It can be one of:
   25055      *
   25056      * {@link #TEXT_ALIGNMENT_INHERIT},
   25057      * {@link #TEXT_ALIGNMENT_GRAVITY},
   25058      * {@link #TEXT_ALIGNMENT_CENTER},
   25059      * {@link #TEXT_ALIGNMENT_TEXT_START},
   25060      * {@link #TEXT_ALIGNMENT_TEXT_END},
   25061      * {@link #TEXT_ALIGNMENT_VIEW_START},
   25062      * {@link #TEXT_ALIGNMENT_VIEW_END}
   25063      *
   25064      * @attr ref android.R.styleable#View_textAlignment
   25065      *
   25066      * @hide
   25067      */
   25068     @ViewDebug.ExportedProperty(category = "text", mapping = {
   25069             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   25070             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   25071             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   25072             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   25073             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   25074             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   25075             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   25076     })
   25077     @TextAlignment
   25078     public int getRawTextAlignment() {
   25079         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   25080     }
   25081 
   25082     /**
   25083      * Set the text alignment.
   25084      *
   25085      * @param textAlignment The text alignment to set. Should be one of
   25086      *
   25087      * {@link #TEXT_ALIGNMENT_INHERIT},
   25088      * {@link #TEXT_ALIGNMENT_GRAVITY},
   25089      * {@link #TEXT_ALIGNMENT_CENTER},
   25090      * {@link #TEXT_ALIGNMENT_TEXT_START},
   25091      * {@link #TEXT_ALIGNMENT_TEXT_END},
   25092      * {@link #TEXT_ALIGNMENT_VIEW_START},
   25093      * {@link #TEXT_ALIGNMENT_VIEW_END}
   25094      *
   25095      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
   25096      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   25097      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
   25098      *
   25099      * @attr ref android.R.styleable#View_textAlignment
   25100      */
   25101     public void setTextAlignment(@TextAlignment int textAlignment) {
   25102         if (textAlignment != getRawTextAlignment()) {
   25103             // Reset the current and resolved text alignment
   25104             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   25105             resetResolvedTextAlignment();
   25106             // Set the new text alignment
   25107             mPrivateFlags2 |=
   25108                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
   25109             // Do resolution
   25110             resolveTextAlignment();
   25111             // Notify change
   25112             onRtlPropertiesChanged(getLayoutDirection());
   25113             // Refresh
   25114             requestLayout();
   25115             invalidate(true);
   25116         }
   25117     }
   25118 
   25119     /**
   25120      * Return the resolved text alignment.
   25121      *
   25122      * @return the resolved text alignment. Returns one of:
   25123      *
   25124      * {@link #TEXT_ALIGNMENT_GRAVITY},
   25125      * {@link #TEXT_ALIGNMENT_CENTER},
   25126      * {@link #TEXT_ALIGNMENT_TEXT_START},
   25127      * {@link #TEXT_ALIGNMENT_TEXT_END},
   25128      * {@link #TEXT_ALIGNMENT_VIEW_START},
   25129      * {@link #TEXT_ALIGNMENT_VIEW_END}
   25130      *
   25131      * @attr ref android.R.styleable#View_textAlignment
   25132      */
   25133     @ViewDebug.ExportedProperty(category = "text", mapping = {
   25134             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   25135             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   25136             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   25137             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   25138             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   25139             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   25140             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   25141     })
   25142     @TextAlignment
   25143     public int getTextAlignment() {
   25144         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
   25145                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   25146     }
   25147 
   25148     /**
   25149      * Resolve the text alignment.
   25150      *
   25151      * @return true if resolution has been done, false otherwise.
   25152      *
   25153      * @hide
   25154      */
   25155     public boolean resolveTextAlignment() {
   25156         // Reset any previous text alignment resolution
   25157         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   25158 
   25159         if (hasRtlSupport()) {
   25160             // Set resolved text alignment flag depending on text alignment flag
   25161             final int textAlignment = getRawTextAlignment();
   25162             switch (textAlignment) {
   25163                 case TEXT_ALIGNMENT_INHERIT:
   25164                     // Check if we can resolve the text alignment
   25165                     if (!canResolveTextAlignment()) {
   25166                         // We cannot do the resolution if there is no parent so use the default
   25167                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   25168                         // Resolution will need to happen again later
   25169                         return false;
   25170                     }
   25171 
   25172                     // Parent has not yet resolved, so we still return the default
   25173                     try {
   25174                         if (!mParent.isTextAlignmentResolved()) {
   25175                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   25176                             // Resolution will need to happen again later
   25177                             return false;
   25178                         }
   25179                     } catch (AbstractMethodError e) {
   25180                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   25181                                 " does not fully implement ViewParent", e);
   25182                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   25183                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   25184                         return true;
   25185                     }
   25186 
   25187                     int parentResolvedTextAlignment;
   25188                     try {
   25189                         parentResolvedTextAlignment = mParent.getTextAlignment();
   25190                     } catch (AbstractMethodError e) {
   25191                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   25192                                 " does not fully implement ViewParent", e);
   25193                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
   25194                     }
   25195                     switch (parentResolvedTextAlignment) {
   25196                         case TEXT_ALIGNMENT_GRAVITY:
   25197                         case TEXT_ALIGNMENT_TEXT_START:
   25198                         case TEXT_ALIGNMENT_TEXT_END:
   25199                         case TEXT_ALIGNMENT_CENTER:
   25200                         case TEXT_ALIGNMENT_VIEW_START:
   25201                         case TEXT_ALIGNMENT_VIEW_END:
   25202                             // Resolved text alignment is the same as the parent resolved
   25203                             // text alignment
   25204                             mPrivateFlags2 |=
   25205                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   25206                             break;
   25207                         default:
   25208                             // Use default resolved text alignment
   25209                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   25210                     }
   25211                     break;
   25212                 case TEXT_ALIGNMENT_GRAVITY:
   25213                 case TEXT_ALIGNMENT_TEXT_START:
   25214                 case TEXT_ALIGNMENT_TEXT_END:
   25215                 case TEXT_ALIGNMENT_CENTER:
   25216                 case TEXT_ALIGNMENT_VIEW_START:
   25217                 case TEXT_ALIGNMENT_VIEW_END:
   25218                     // Resolved text alignment is the same as text alignment
   25219                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   25220                     break;
   25221                 default:
   25222                     // Use default resolved text alignment
   25223                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   25224             }
   25225         } else {
   25226             // Use default resolved text alignment
   25227             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   25228         }
   25229 
   25230         // Set the resolved
   25231         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   25232         return true;
   25233     }
   25234 
   25235     /**
   25236      * Check if text alignment resolution can be done.
   25237      *
   25238      * @return true if text alignment resolution can be done otherwise return false.
   25239      */
   25240     public boolean canResolveTextAlignment() {
   25241         switch (getRawTextAlignment()) {
   25242             case TEXT_DIRECTION_INHERIT:
   25243                 if (mParent != null) {
   25244                     try {
   25245                         return mParent.canResolveTextAlignment();
   25246                     } catch (AbstractMethodError e) {
   25247                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   25248                                 " does not fully implement ViewParent", e);
   25249                     }
   25250                 }
   25251                 return false;
   25252 
   25253             default:
   25254                 return true;
   25255         }
   25256     }
   25257 
   25258     /**
   25259      * Reset resolved text alignment. Text alignment will be resolved during a call to
   25260      * {@link #onMeasure(int, int)}.
   25261      *
   25262      * @hide
   25263      */
   25264     public void resetResolvedTextAlignment() {
   25265         // Reset any previous text alignment resolution
   25266         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   25267         // Set to default
   25268         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   25269     }
   25270 
   25271     /**
   25272      * @return true if text alignment is inherited.
   25273      *
   25274      * @hide
   25275      */
   25276     public boolean isTextAlignmentInherited() {
   25277         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
   25278     }
   25279 
   25280     /**
   25281      * @return true if text alignment is resolved.
   25282      */
   25283     public boolean isTextAlignmentResolved() {
   25284         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   25285     }
   25286 
   25287     /**
   25288      * Generate a value suitable for use in {@link #setId(int)}.
   25289      * This value will not collide with ID values generated at build time by aapt for R.id.
   25290      *
   25291      * @return a generated ID value
   25292      */
   25293     public static int generateViewId() {
   25294         for (;;) {
   25295             final int result = sNextGeneratedId.get();
   25296             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
   25297             int newValue = result + 1;
   25298             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
   25299             if (sNextGeneratedId.compareAndSet(result, newValue)) {
   25300                 return result;
   25301             }
   25302         }
   25303     }
   25304 
   25305     private static boolean isViewIdGenerated(int id) {
   25306         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
   25307     }
   25308 
   25309     /**
   25310      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
   25311      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
   25312      *                           a normal View or a ViewGroup with
   25313      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
   25314      * @hide
   25315      */
   25316     public void captureTransitioningViews(List<View> transitioningViews) {
   25317         if (getVisibility() == View.VISIBLE) {
   25318             transitioningViews.add(this);
   25319         }
   25320     }
   25321 
   25322     /**
   25323      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
   25324      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
   25325      * @hide
   25326      */
   25327     public void findNamedViews(Map<String, View> namedElements) {
   25328         if (getVisibility() == VISIBLE || mGhostView != null) {
   25329             String transitionName = getTransitionName();
   25330             if (transitionName != null) {
   25331                 namedElements.put(transitionName, this);
   25332             }
   25333         }
   25334     }
   25335 
   25336     /**
   25337      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
   25338      * The default implementation does not care the location or event types, but some subclasses
   25339      * may use it (such as WebViews).
   25340      * @param event The MotionEvent from a mouse
   25341      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
   25342      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
   25343      * @see PointerIcon
   25344      */
   25345     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
   25346         final float x = event.getX(pointerIndex);
   25347         final float y = event.getY(pointerIndex);
   25348         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
   25349             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
   25350         }
   25351         return mPointerIcon;
   25352     }
   25353 
   25354     /**
   25355      * Set the pointer icon for the current view.
   25356      * Passing {@code null} will restore the pointer icon to its default value.
   25357      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
   25358      */
   25359     public void setPointerIcon(PointerIcon pointerIcon) {
   25360         mPointerIcon = pointerIcon;
   25361         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
   25362             return;
   25363         }
   25364         try {
   25365             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
   25366         } catch (RemoteException e) {
   25367         }
   25368     }
   25369 
   25370     /**
   25371      * Gets the pointer icon for the current view.
   25372      */
   25373     public PointerIcon getPointerIcon() {
   25374         return mPointerIcon;
   25375     }
   25376 
   25377     /**
   25378      * Checks pointer capture status.
   25379      *
   25380      * @return true if the view has pointer capture.
   25381      * @see #requestPointerCapture()
   25382      * @see #hasPointerCapture()
   25383      */
   25384     public boolean hasPointerCapture() {
   25385         final ViewRootImpl viewRootImpl = getViewRootImpl();
   25386         if (viewRootImpl == null) {
   25387             return false;
   25388         }
   25389         return viewRootImpl.hasPointerCapture();
   25390     }
   25391 
   25392     /**
   25393      * Requests pointer capture mode.
   25394      * <p>
   25395      * When the window has pointer capture, the mouse pointer icon will disappear and will not
   25396      * change its position. Further mouse will be dispatched with the source
   25397      * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
   25398      * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
   25399      * (touchscreens, or stylus) will not be affected.
   25400      * <p>
   25401      * If the window already has pointer capture, this call does nothing.
   25402      * <p>
   25403      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
   25404      * automatically when the window loses focus.
   25405      *
   25406      * @see #releasePointerCapture()
   25407      * @see #hasPointerCapture()
   25408      */
   25409     public void requestPointerCapture() {
   25410         final ViewRootImpl viewRootImpl = getViewRootImpl();
   25411         if (viewRootImpl != null) {
   25412             viewRootImpl.requestPointerCapture(true);
   25413         }
   25414     }
   25415 
   25416 
   25417     /**
   25418      * Releases the pointer capture.
   25419      * <p>
   25420      * If the window does not have pointer capture, this call will do nothing.
   25421      * @see #requestPointerCapture()
   25422      * @see #hasPointerCapture()
   25423      */
   25424     public void releasePointerCapture() {
   25425         final ViewRootImpl viewRootImpl = getViewRootImpl();
   25426         if (viewRootImpl != null) {
   25427             viewRootImpl.requestPointerCapture(false);
   25428         }
   25429     }
   25430 
   25431     /**
   25432      * Called when the window has just acquired or lost pointer capture.
   25433      *
   25434      * @param hasCapture True if the view now has pointerCapture, false otherwise.
   25435      */
   25436     @CallSuper
   25437     public void onPointerCaptureChange(boolean hasCapture) {
   25438     }
   25439 
   25440     /**
   25441      * @see #onPointerCaptureChange
   25442      */
   25443     public void dispatchPointerCaptureChanged(boolean hasCapture) {
   25444         onPointerCaptureChange(hasCapture);
   25445     }
   25446 
   25447     /**
   25448      * Implement this method to handle captured pointer events
   25449      *
   25450      * @param event The captured pointer event.
   25451      * @return True if the event was handled, false otherwise.
   25452      * @see #requestPointerCapture()
   25453      */
   25454     public boolean onCapturedPointerEvent(MotionEvent event) {
   25455         return false;
   25456     }
   25457 
   25458     /**
   25459      * Interface definition for a callback to be invoked when a captured pointer event
   25460      * is being dispatched this view. The callback will be invoked before the event is
   25461      * given to the view.
   25462      */
   25463     public interface OnCapturedPointerListener {
   25464         /**
   25465          * Called when a captured pointer event is dispatched to a view.
   25466          * @param view The view this event has been dispatched to.
   25467          * @param event The captured event.
   25468          * @return True if the listener has consumed the event, false otherwise.
   25469          */
   25470         boolean onCapturedPointer(View view, MotionEvent event);
   25471     }
   25472 
   25473     /**
   25474      * Set a listener to receive callbacks when the pointer capture state of a view changes.
   25475      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
   25476      */
   25477     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
   25478         getListenerInfo().mOnCapturedPointerListener = l;
   25479     }
   25480 
   25481     // Properties
   25482     //
   25483     /**
   25484      * A Property wrapper around the <code>alpha</code> functionality handled by the
   25485      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
   25486      */
   25487     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
   25488         @Override
   25489         public void setValue(View object, float value) {
   25490             object.setAlpha(value);
   25491         }
   25492 
   25493         @Override
   25494         public Float get(View object) {
   25495             return object.getAlpha();
   25496         }
   25497     };
   25498 
   25499     /**
   25500      * A Property wrapper around the <code>translationX</code> functionality handled by the
   25501      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
   25502      */
   25503     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
   25504         @Override
   25505         public void setValue(View object, float value) {
   25506             object.setTranslationX(value);
   25507         }
   25508 
   25509                 @Override
   25510         public Float get(View object) {
   25511             return object.getTranslationX();
   25512         }
   25513     };
   25514 
   25515     /**
   25516      * A Property wrapper around the <code>translationY</code> functionality handled by the
   25517      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
   25518      */
   25519     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
   25520         @Override
   25521         public void setValue(View object, float value) {
   25522             object.setTranslationY(value);
   25523         }
   25524 
   25525         @Override
   25526         public Float get(View object) {
   25527             return object.getTranslationY();
   25528         }
   25529     };
   25530 
   25531     /**
   25532      * A Property wrapper around the <code>translationZ</code> functionality handled by the
   25533      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
   25534      */
   25535     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
   25536         @Override
   25537         public void setValue(View object, float value) {
   25538             object.setTranslationZ(value);
   25539         }
   25540 
   25541         @Override
   25542         public Float get(View object) {
   25543             return object.getTranslationZ();
   25544         }
   25545     };
   25546 
   25547     /**
   25548      * A Property wrapper around the <code>x</code> functionality handled by the
   25549      * {@link View#setX(float)} and {@link View#getX()} methods.
   25550      */
   25551     public static final Property<View, Float> X = new FloatProperty<View>("x") {
   25552         @Override
   25553         public void setValue(View object, float value) {
   25554             object.setX(value);
   25555         }
   25556 
   25557         @Override
   25558         public Float get(View object) {
   25559             return object.getX();
   25560         }
   25561     };
   25562 
   25563     /**
   25564      * A Property wrapper around the <code>y</code> functionality handled by the
   25565      * {@link View#setY(float)} and {@link View#getY()} methods.
   25566      */
   25567     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
   25568         @Override
   25569         public void setValue(View object, float value) {
   25570             object.setY(value);
   25571         }
   25572 
   25573         @Override
   25574         public Float get(View object) {
   25575             return object.getY();
   25576         }
   25577     };
   25578 
   25579     /**
   25580      * A Property wrapper around the <code>z</code> functionality handled by the
   25581      * {@link View#setZ(float)} and {@link View#getZ()} methods.
   25582      */
   25583     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
   25584         @Override
   25585         public void setValue(View object, float value) {
   25586             object.setZ(value);
   25587         }
   25588 
   25589         @Override
   25590         public Float get(View object) {
   25591             return object.getZ();
   25592         }
   25593     };
   25594 
   25595     /**
   25596      * A Property wrapper around the <code>rotation</code> functionality handled by the
   25597      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
   25598      */
   25599     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
   25600         @Override
   25601         public void setValue(View object, float value) {
   25602             object.setRotation(value);
   25603         }
   25604 
   25605         @Override
   25606         public Float get(View object) {
   25607             return object.getRotation();
   25608         }
   25609     };
   25610 
   25611     /**
   25612      * A Property wrapper around the <code>rotationX</code> functionality handled by the
   25613      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
   25614      */
   25615     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
   25616         @Override
   25617         public void setValue(View object, float value) {
   25618             object.setRotationX(value);
   25619         }
   25620 
   25621         @Override
   25622         public Float get(View object) {
   25623             return object.getRotationX();
   25624         }
   25625     };
   25626 
   25627     /**
   25628      * A Property wrapper around the <code>rotationY</code> functionality handled by the
   25629      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
   25630      */
   25631     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
   25632         @Override
   25633         public void setValue(View object, float value) {
   25634             object.setRotationY(value);
   25635         }
   25636 
   25637         @Override
   25638         public Float get(View object) {
   25639             return object.getRotationY();
   25640         }
   25641     };
   25642 
   25643     /**
   25644      * A Property wrapper around the <code>scaleX</code> functionality handled by the
   25645      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
   25646      */
   25647     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
   25648         @Override
   25649         public void setValue(View object, float value) {
   25650             object.setScaleX(value);
   25651         }
   25652 
   25653         @Override
   25654         public Float get(View object) {
   25655             return object.getScaleX();
   25656         }
   25657     };
   25658 
   25659     /**
   25660      * A Property wrapper around the <code>scaleY</code> functionality handled by the
   25661      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
   25662      */
   25663     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
   25664         @Override
   25665         public void setValue(View object, float value) {
   25666             object.setScaleY(value);
   25667         }
   25668 
   25669         @Override
   25670         public Float get(View object) {
   25671             return object.getScaleY();
   25672         }
   25673     };
   25674 
   25675     /**
   25676      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
   25677      * Each MeasureSpec represents a requirement for either the width or the height.
   25678      * A MeasureSpec is comprised of a size and a mode. There are three possible
   25679      * modes:
   25680      * <dl>
   25681      * <dt>UNSPECIFIED</dt>
   25682      * <dd>
   25683      * The parent has not imposed any constraint on the child. It can be whatever size
   25684      * it wants.
   25685      * </dd>
   25686      *
   25687      * <dt>EXACTLY</dt>
   25688      * <dd>
   25689      * The parent has determined an exact size for the child. The child is going to be
   25690      * given those bounds regardless of how big it wants to be.
   25691      * </dd>
   25692      *
   25693      * <dt>AT_MOST</dt>
   25694      * <dd>
   25695      * The child can be as large as it wants up to the specified size.
   25696      * </dd>
   25697      * </dl>
   25698      *
   25699      * MeasureSpecs are implemented as ints to reduce object allocation. This class
   25700      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
   25701      */
   25702     public static class MeasureSpec {
   25703         private static final int MODE_SHIFT = 30;
   25704         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
   25705 
   25706         /** @hide */
   25707         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
   25708         @Retention(RetentionPolicy.SOURCE)
   25709         public @interface MeasureSpecMode {}
   25710 
   25711         /**
   25712          * Measure specification mode: The parent has not imposed any constraint
   25713          * on the child. It can be whatever size it wants.
   25714          */
   25715         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
   25716 
   25717         /**
   25718          * Measure specification mode: The parent has determined an exact size
   25719          * for the child. The child is going to be given those bounds regardless
   25720          * of how big it wants to be.
   25721          */
   25722         public static final int EXACTLY     = 1 << MODE_SHIFT;
   25723 
   25724         /**
   25725          * Measure specification mode: The child can be as large as it wants up
   25726          * to the specified size.
   25727          */
   25728         public static final int AT_MOST     = 2 << MODE_SHIFT;
   25729 
   25730         /**
   25731          * Creates a measure specification based on the supplied size and mode.
   25732          *
   25733          * The mode must always be one of the following:
   25734          * <ul>
   25735          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
   25736          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
   25737          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
   25738          * </ul>
   25739          *
   25740          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
   25741          * implementation was such that the order of arguments did not matter
   25742          * and overflow in either value could impact the resulting MeasureSpec.
   25743          * {@link android.widget.RelativeLayout} was affected by this bug.
   25744          * Apps targeting API levels greater than 17 will get the fixed, more strict
   25745          * behavior.</p>
   25746          *
   25747          * @param size the size of the measure specification
   25748          * @param mode the mode of the measure specification
   25749          * @return the measure specification based on size and mode
   25750          */
   25751         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
   25752                                           @MeasureSpecMode int mode) {
   25753             if (sUseBrokenMakeMeasureSpec) {
   25754                 return size + mode;
   25755             } else {
   25756                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
   25757             }
   25758         }
   25759 
   25760         /**
   25761          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
   25762          * will automatically get a size of 0. Older apps expect this.
   25763          *
   25764          * @hide internal use only for compatibility with system widgets and older apps
   25765          */
   25766         public static int makeSafeMeasureSpec(int size, int mode) {
   25767             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
   25768                 return 0;
   25769             }
   25770             return makeMeasureSpec(size, mode);
   25771         }
   25772 
   25773         /**
   25774          * Extracts the mode from the supplied measure specification.
   25775          *
   25776          * @param measureSpec the measure specification to extract the mode from
   25777          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
   25778          *         {@link android.view.View.MeasureSpec#AT_MOST} or
   25779          *         {@link android.view.View.MeasureSpec#EXACTLY}
   25780          */
   25781         @MeasureSpecMode
   25782         public static int getMode(int measureSpec) {
   25783             //noinspection ResourceType
   25784             return (measureSpec & MODE_MASK);
   25785         }
   25786 
   25787         /**
   25788          * Extracts the size from the supplied measure specification.
   25789          *
   25790          * @param measureSpec the measure specification to extract the size from
   25791          * @return the size in pixels defined in the supplied measure specification
   25792          */
   25793         public static int getSize(int measureSpec) {
   25794             return (measureSpec & ~MODE_MASK);
   25795         }
   25796 
   25797         static int adjust(int measureSpec, int delta) {
   25798             final int mode = getMode(measureSpec);
   25799             int size = getSize(measureSpec);
   25800             if (mode == UNSPECIFIED) {
   25801                 // No need to adjust size for UNSPECIFIED mode.
   25802                 return makeMeasureSpec(size, UNSPECIFIED);
   25803             }
   25804             size += delta;
   25805             if (size < 0) {
   25806                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
   25807                         ") spec: " + toString(measureSpec) + " delta: " + delta);
   25808                 size = 0;
   25809             }
   25810             return makeMeasureSpec(size, mode);
   25811         }
   25812 
   25813         /**
   25814          * Returns a String representation of the specified measure
   25815          * specification.
   25816          *
   25817          * @param measureSpec the measure specification to convert to a String
   25818          * @return a String with the following format: "MeasureSpec: MODE SIZE"
   25819          */
   25820         public static String toString(int measureSpec) {
   25821             int mode = getMode(measureSpec);
   25822             int size = getSize(measureSpec);
   25823 
   25824             StringBuilder sb = new StringBuilder("MeasureSpec: ");
   25825 
   25826             if (mode == UNSPECIFIED)
   25827                 sb.append("UNSPECIFIED ");
   25828             else if (mode == EXACTLY)
   25829                 sb.append("EXACTLY ");
   25830             else if (mode == AT_MOST)
   25831                 sb.append("AT_MOST ");
   25832             else
   25833                 sb.append(mode).append(" ");
   25834 
   25835             sb.append(size);
   25836             return sb.toString();
   25837         }
   25838     }
   25839 
   25840     private final class CheckForLongPress implements Runnable {
   25841         private int mOriginalWindowAttachCount;
   25842         private float mX;
   25843         private float mY;
   25844         private boolean mOriginalPressedState;
   25845 
   25846         @Override
   25847         public void run() {
   25848             if ((mOriginalPressedState == isPressed()) && (mParent != null)
   25849                     && mOriginalWindowAttachCount == mWindowAttachCount) {
   25850                 if (performLongClick(mX, mY)) {
   25851                     mHasPerformedLongPress = true;
   25852                 }
   25853             }
   25854         }
   25855 
   25856         public void setAnchor(float x, float y) {
   25857             mX = x;
   25858             mY = y;
   25859         }
   25860 
   25861         public void rememberWindowAttachCount() {
   25862             mOriginalWindowAttachCount = mWindowAttachCount;
   25863         }
   25864 
   25865         public void rememberPressedState() {
   25866             mOriginalPressedState = isPressed();
   25867         }
   25868     }
   25869 
   25870     private final class CheckForTap implements Runnable {
   25871         public float x;
   25872         public float y;
   25873 
   25874         @Override
   25875         public void run() {
   25876             mPrivateFlags &= ~PFLAG_PREPRESSED;
   25877             setPressed(true, x, y);
   25878             checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
   25879         }
   25880     }
   25881 
   25882     private final class PerformClick implements Runnable {
   25883         @Override
   25884         public void run() {
   25885             performClickInternal();
   25886         }
   25887     }
   25888 
   25889     /**
   25890      * This method returns a ViewPropertyAnimator object, which can be used to animate
   25891      * specific properties on this View.
   25892      *
   25893      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
   25894      */
   25895     public ViewPropertyAnimator animate() {
   25896         if (mAnimator == null) {
   25897             mAnimator = new ViewPropertyAnimator(this);
   25898         }
   25899         return mAnimator;
   25900     }
   25901 
   25902     /**
   25903      * Sets the name of the View to be used to identify Views in Transitions.
   25904      * Names should be unique in the View hierarchy.
   25905      *
   25906      * @param transitionName The name of the View to uniquely identify it for Transitions.
   25907      */
   25908     public final void setTransitionName(String transitionName) {
   25909         mTransitionName = transitionName;
   25910     }
   25911 
   25912     /**
   25913      * Returns the name of the View to be used to identify Views in Transitions.
   25914      * Names should be unique in the View hierarchy.
   25915      *
   25916      * <p>This returns null if the View has not been given a name.</p>
   25917      *
   25918      * @return The name used of the View to be used to identify Views in Transitions or null
   25919      * if no name has been given.
   25920      */
   25921     @ViewDebug.ExportedProperty
   25922     public String getTransitionName() {
   25923         return mTransitionName;
   25924     }
   25925 
   25926     /**
   25927      * @hide
   25928      */
   25929     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
   25930         // Do nothing.
   25931     }
   25932 
   25933     /**
   25934      * Interface definition for a callback to be invoked when a hardware key event is
   25935      * dispatched to this view. The callback will be invoked before the key event is
   25936      * given to the view. This is only useful for hardware keyboards; a software input
   25937      * method has no obligation to trigger this listener.
   25938      */
   25939     public interface OnKeyListener {
   25940         /**
   25941          * Called when a hardware key is dispatched to a view. This allows listeners to
   25942          * get a chance to respond before the target view.
   25943          * <p>Key presses in software keyboards will generally NOT trigger this method,
   25944          * although some may elect to do so in some situations. Do not assume a
   25945          * software input method has to be key-based; even if it is, it may use key presses
   25946          * in a different way than you expect, so there is no way to reliably catch soft
   25947          * input key presses.
   25948          *
   25949          * @param v The view the key has been dispatched to.
   25950          * @param keyCode The code for the physical key that was pressed
   25951          * @param event The KeyEvent object containing full information about
   25952          *        the event.
   25953          * @return True if the listener has consumed the event, false otherwise.
   25954          */
   25955         boolean onKey(View v, int keyCode, KeyEvent event);
   25956     }
   25957 
   25958     /**
   25959      * Interface definition for a callback to be invoked when a hardware key event hasn't
   25960      * been handled by the view hierarchy.
   25961      */
   25962     public interface OnUnhandledKeyEventListener {
   25963         /**
   25964          * Called when a hardware key is dispatched to a view after being unhandled during normal
   25965          * {@link KeyEvent} dispatch.
   25966          *
   25967          * @param v The view the key has been dispatched to.
   25968          * @param event The KeyEvent object containing information about the event.
   25969          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
   25970          */
   25971         boolean onUnhandledKeyEvent(View v, KeyEvent event);
   25972     }
   25973 
   25974     /**
   25975      * Interface definition for a callback to be invoked when a touch event is
   25976      * dispatched to this view. The callback will be invoked before the touch
   25977      * event is given to the view.
   25978      */
   25979     public interface OnTouchListener {
   25980         /**
   25981          * Called when a touch event is dispatched to a view. This allows listeners to
   25982          * get a chance to respond before the target view.
   25983          *
   25984          * @param v The view the touch event has been dispatched to.
   25985          * @param event The MotionEvent object containing full information about
   25986          *        the event.
   25987          * @return True if the listener has consumed the event, false otherwise.
   25988          */
   25989         boolean onTouch(View v, MotionEvent event);
   25990     }
   25991 
   25992     /**
   25993      * Interface definition for a callback to be invoked when a hover event is
   25994      * dispatched to this view. The callback will be invoked before the hover
   25995      * event is given to the view.
   25996      */
   25997     public interface OnHoverListener {
   25998         /**
   25999          * Called when a hover event is dispatched to a view. This allows listeners to
   26000          * get a chance to respond before the target view.
   26001          *
   26002          * @param v The view the hover event has been dispatched to.
   26003          * @param event The MotionEvent object containing full information about
   26004          *        the event.
   26005          * @return True if the listener has consumed the event, false otherwise.
   26006          */
   26007         boolean onHover(View v, MotionEvent event);
   26008     }
   26009 
   26010     /**
   26011      * Interface definition for a callback to be invoked when a generic motion event is
   26012      * dispatched to this view. The callback will be invoked before the generic motion
   26013      * event is given to the view.
   26014      */
   26015     public interface OnGenericMotionListener {
   26016         /**
   26017          * Called when a generic motion event is dispatched to a view. This allows listeners to
   26018          * get a chance to respond before the target view.
   26019          *
   26020          * @param v The view the generic motion event has been dispatched to.
   26021          * @param event The MotionEvent object containing full information about
   26022          *        the event.
   26023          * @return True if the listener has consumed the event, false otherwise.
   26024          */
   26025         boolean onGenericMotion(View v, MotionEvent event);
   26026     }
   26027 
   26028     /**
   26029      * Interface definition for a callback to be invoked when a view has been clicked and held.
   26030      */
   26031     public interface OnLongClickListener {
   26032         /**
   26033          * Called when a view has been clicked and held.
   26034          *
   26035          * @param v The view that was clicked and held.
   26036          *
   26037          * @return true if the callback consumed the long click, false otherwise.
   26038          */
   26039         boolean onLongClick(View v);
   26040     }
   26041 
   26042     /**
   26043      * Interface definition for a callback to be invoked when a drag is being dispatched
   26044      * to this view.  The callback will be invoked before the hosting view's own
   26045      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
   26046      * onDrag(event) behavior, it should return 'false' from this callback.
   26047      *
   26048      * <div class="special reference">
   26049      * <h3>Developer Guides</h3>
   26050      * <p>For a guide to implementing drag and drop features, read the
   26051      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   26052      * </div>
   26053      */
   26054     public interface OnDragListener {
   26055         /**
   26056          * Called when a drag event is dispatched to a view. This allows listeners
   26057          * to get a chance to override base View behavior.
   26058          *
   26059          * @param v The View that received the drag event.
   26060          * @param event The {@link android.view.DragEvent} object for the drag event.
   26061          * @return {@code true} if the drag event was handled successfully, or {@code false}
   26062          * if the drag event was not handled. Note that {@code false} will trigger the View
   26063          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
   26064          */
   26065         boolean onDrag(View v, DragEvent event);
   26066     }
   26067 
   26068     /**
   26069      * Interface definition for a callback to be invoked when the focus state of
   26070      * a view changed.
   26071      */
   26072     public interface OnFocusChangeListener {
   26073         /**
   26074          * Called when the focus state of a view has changed.
   26075          *
   26076          * @param v The view whose state has changed.
   26077          * @param hasFocus The new focus state of v.
   26078          */
   26079         void onFocusChange(View v, boolean hasFocus);
   26080     }
   26081 
   26082     /**
   26083      * Interface definition for a callback to be invoked when a view is clicked.
   26084      */
   26085     public interface OnClickListener {
   26086         /**
   26087          * Called when a view has been clicked.
   26088          *
   26089          * @param v The view that was clicked.
   26090          */
   26091         void onClick(View v);
   26092     }
   26093 
   26094     /**
   26095      * Interface definition for a callback to be invoked when a view is context clicked.
   26096      */
   26097     public interface OnContextClickListener {
   26098         /**
   26099          * Called when a view is context clicked.
   26100          *
   26101          * @param v The view that has been context clicked.
   26102          * @return true if the callback consumed the context click, false otherwise.
   26103          */
   26104         boolean onContextClick(View v);
   26105     }
   26106 
   26107     /**
   26108      * Interface definition for a callback to be invoked when the context menu
   26109      * for this view is being built.
   26110      */
   26111     public interface OnCreateContextMenuListener {
   26112         /**
   26113          * Called when the context menu for this view is being built. It is not
   26114          * safe to hold onto the menu after this method returns.
   26115          *
   26116          * @param menu The context menu that is being built
   26117          * @param v The view for which the context menu is being built
   26118          * @param menuInfo Extra information about the item for which the
   26119          *            context menu should be shown. This information will vary
   26120          *            depending on the class of v.
   26121          */
   26122         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
   26123     }
   26124 
   26125     /**
   26126      * Interface definition for a callback to be invoked when the status bar changes
   26127      * visibility.  This reports <strong>global</strong> changes to the system UI
   26128      * state, not what the application is requesting.
   26129      *
   26130      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
   26131      */
   26132     public interface OnSystemUiVisibilityChangeListener {
   26133         /**
   26134          * Called when the status bar changes visibility because of a call to
   26135          * {@link View#setSystemUiVisibility(int)}.
   26136          *
   26137          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   26138          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
   26139          * This tells you the <strong>global</strong> state of these UI visibility
   26140          * flags, not what your app is currently applying.
   26141          */
   26142         public void onSystemUiVisibilityChange(int visibility);
   26143     }
   26144 
   26145     /**
   26146      * Interface definition for a callback to be invoked when this view is attached
   26147      * or detached from its window.
   26148      */
   26149     public interface OnAttachStateChangeListener {
   26150         /**
   26151          * Called when the view is attached to a window.
   26152          * @param v The view that was attached
   26153          */
   26154         public void onViewAttachedToWindow(View v);
   26155         /**
   26156          * Called when the view is detached from a window.
   26157          * @param v The view that was detached
   26158          */
   26159         public void onViewDetachedFromWindow(View v);
   26160     }
   26161 
   26162     /**
   26163      * Listener for applying window insets on a view in a custom way.
   26164      *
   26165      * <p>Apps may choose to implement this interface if they want to apply custom policy
   26166      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
   26167      * is set, its
   26168      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   26169      * method will be called instead of the View's own
   26170      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
   26171      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
   26172      * the View's normal behavior as part of its own.</p>
   26173      */
   26174     public interface OnApplyWindowInsetsListener {
   26175         /**
   26176          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
   26177          * on a View, this listener method will be called instead of the view's own
   26178          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   26179          *
   26180          * @param v The view applying window insets
   26181          * @param insets The insets to apply
   26182          * @return The insets supplied, minus any insets that were consumed
   26183          */
   26184         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
   26185     }
   26186 
   26187     private final class UnsetPressedState implements Runnable {
   26188         @Override
   26189         public void run() {
   26190             setPressed(false);
   26191         }
   26192     }
   26193 
   26194     /**
   26195      * When a view becomes invisible checks if autofill considers the view invisible too. This
   26196      * happens after the regular removal operation to make sure the operation is finished by the
   26197      * time this is called.
   26198      */
   26199     private static class VisibilityChangeForAutofillHandler extends Handler {
   26200         private final AutofillManager mAfm;
   26201         private final View mView;
   26202 
   26203         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
   26204                 @NonNull View view) {
   26205             mAfm = afm;
   26206             mView = view;
   26207         }
   26208 
   26209         @Override
   26210         public void handleMessage(Message msg) {
   26211             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
   26212         }
   26213     }
   26214 
   26215     /**
   26216      * Base class for derived classes that want to save and restore their own
   26217      * state in {@link android.view.View#onSaveInstanceState()}.
   26218      */
   26219     public static class BaseSavedState extends AbsSavedState {
   26220         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
   26221         static final int IS_AUTOFILLED = 0b10;
   26222         static final int AUTOFILL_ID = 0b100;
   26223 
   26224         // Flags that describe what data in this state is valid
   26225         int mSavedData;
   26226         String mStartActivityRequestWhoSaved;
   26227         boolean mIsAutofilled;
   26228         int mAutofillViewId;
   26229 
   26230         /**
   26231          * Constructor used when reading from a parcel. Reads the state of the superclass.
   26232          *
   26233          * @param source parcel to read from
   26234          */
   26235         public BaseSavedState(Parcel source) {
   26236             this(source, null);
   26237         }
   26238 
   26239         /**
   26240          * Constructor used when reading from a parcel using a given class loader.
   26241          * Reads the state of the superclass.
   26242          *
   26243          * @param source parcel to read from
   26244          * @param loader ClassLoader to use for reading
   26245          */
   26246         public BaseSavedState(Parcel source, ClassLoader loader) {
   26247             super(source, loader);
   26248             mSavedData = source.readInt();
   26249             mStartActivityRequestWhoSaved = source.readString();
   26250             mIsAutofilled = source.readBoolean();
   26251             mAutofillViewId = source.readInt();
   26252         }
   26253 
   26254         /**
   26255          * Constructor called by derived classes when creating their SavedState objects
   26256          *
   26257          * @param superState The state of the superclass of this view
   26258          */
   26259         public BaseSavedState(Parcelable superState) {
   26260             super(superState);
   26261         }
   26262 
   26263         @Override
   26264         public void writeToParcel(Parcel out, int flags) {
   26265             super.writeToParcel(out, flags);
   26266 
   26267             out.writeInt(mSavedData);
   26268             out.writeString(mStartActivityRequestWhoSaved);
   26269             out.writeBoolean(mIsAutofilled);
   26270             out.writeInt(mAutofillViewId);
   26271         }
   26272 
   26273         public static final Parcelable.Creator<BaseSavedState> CREATOR
   26274                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
   26275             @Override
   26276             public BaseSavedState createFromParcel(Parcel in) {
   26277                 return new BaseSavedState(in);
   26278             }
   26279 
   26280             @Override
   26281             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
   26282                 return new BaseSavedState(in, loader);
   26283             }
   26284 
   26285             @Override
   26286             public BaseSavedState[] newArray(int size) {
   26287                 return new BaseSavedState[size];
   26288             }
   26289         };
   26290     }
   26291 
   26292     /**
   26293      * A set of information given to a view when it is attached to its parent
   26294      * window.
   26295      */
   26296     final static class AttachInfo {
   26297         interface Callbacks {
   26298             void playSoundEffect(int effectId);
   26299             boolean performHapticFeedback(int effectId, boolean always);
   26300         }
   26301 
   26302         /**
   26303          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
   26304          * to a Handler. This class contains the target (View) to invalidate and
   26305          * the coordinates of the dirty rectangle.
   26306          *
   26307          * For performance purposes, this class also implements a pool of up to
   26308          * POOL_LIMIT objects that get reused. This reduces memory allocations
   26309          * whenever possible.
   26310          */
   26311         static class InvalidateInfo {
   26312             private static final int POOL_LIMIT = 10;
   26313 
   26314             private static final SynchronizedPool<InvalidateInfo> sPool =
   26315                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
   26316 
   26317             View target;
   26318 
   26319             int left;
   26320             int top;
   26321             int right;
   26322             int bottom;
   26323 
   26324             public static InvalidateInfo obtain() {
   26325                 InvalidateInfo instance = sPool.acquire();
   26326                 return (instance != null) ? instance : new InvalidateInfo();
   26327             }
   26328 
   26329             public void recycle() {
   26330                 target = null;
   26331                 sPool.release(this);
   26332             }
   26333         }
   26334 
   26335         final IWindowSession mSession;
   26336 
   26337         final IWindow mWindow;
   26338 
   26339         final IBinder mWindowToken;
   26340 
   26341         Display mDisplay;
   26342 
   26343         final Callbacks mRootCallbacks;
   26344 
   26345         IWindowId mIWindowId;
   26346         WindowId mWindowId;
   26347 
   26348         /**
   26349          * The top view of the hierarchy.
   26350          */
   26351         View mRootView;
   26352 
   26353         IBinder mPanelParentWindowToken;
   26354 
   26355         boolean mHardwareAccelerated;
   26356         boolean mHardwareAccelerationRequested;
   26357         ThreadedRenderer mThreadedRenderer;
   26358         List<RenderNode> mPendingAnimatingRenderNodes;
   26359 
   26360         /**
   26361          * The state of the display to which the window is attached, as reported
   26362          * by {@link Display#getState()}.  Note that the display state constants
   26363          * declared by {@link Display} do not exactly line up with the screen state
   26364          * constants declared by {@link View} (there are more display states than
   26365          * screen states).
   26366          */
   26367         int mDisplayState = Display.STATE_UNKNOWN;
   26368 
   26369         /**
   26370          * Scale factor used by the compatibility mode
   26371          */
   26372         float mApplicationScale;
   26373 
   26374         /**
   26375          * Indicates whether the application is in compatibility mode
   26376          */
   26377         boolean mScalingRequired;
   26378 
   26379         /**
   26380          * Left position of this view's window
   26381          */
   26382         int mWindowLeft;
   26383 
   26384         /**
   26385          * Top position of this view's window
   26386          */
   26387         int mWindowTop;
   26388 
   26389         /**
   26390          * Indicates whether views need to use 32-bit drawing caches
   26391          */
   26392         boolean mUse32BitDrawingCache;
   26393 
   26394         /**
   26395          * For windows that are full-screen but using insets to layout inside
   26396          * of the screen areas, these are the current insets to appear inside
   26397          * the overscan area of the display.
   26398          */
   26399         final Rect mOverscanInsets = new Rect();
   26400 
   26401         /**
   26402          * For windows that are full-screen but using insets to layout inside
   26403          * of the screen decorations, these are the current insets for the
   26404          * content of the window.
   26405          */
   26406         final Rect mContentInsets = new Rect();
   26407 
   26408         /**
   26409          * For windows that are full-screen but using insets to layout inside
   26410          * of the screen decorations, these are the current insets for the
   26411          * actual visible parts of the window.
   26412          */
   26413         final Rect mVisibleInsets = new Rect();
   26414 
   26415         /**
   26416          * For windows that are full-screen but using insets to layout inside
   26417          * of the screen decorations, these are the current insets for the
   26418          * stable system windows.
   26419          */
   26420         final Rect mStableInsets = new Rect();
   26421 
   26422         final DisplayCutout.ParcelableWrapper mDisplayCutout =
   26423                 new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
   26424 
   26425         /**
   26426          * For windows that include areas that are not covered by real surface these are the outsets
   26427          * for real surface.
   26428          */
   26429         final Rect mOutsets = new Rect();
   26430 
   26431         /**
   26432          * In multi-window we force show the navigation bar. Because we don't want that the surface
   26433          * size changes in this mode, we instead have a flag whether the navigation bar size should
   26434          * always be consumed, so the app is treated like there is no virtual navigation bar at all.
   26435          */
   26436         boolean mAlwaysConsumeNavBar;
   26437 
   26438         /**
   26439          * The internal insets given by this window.  This value is
   26440          * supplied by the client (through
   26441          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
   26442          * be given to the window manager when changed to be used in laying
   26443          * out windows behind it.
   26444          */
   26445         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
   26446                 = new ViewTreeObserver.InternalInsetsInfo();
   26447 
   26448         /**
   26449          * Set to true when mGivenInternalInsets is non-empty.
   26450          */
   26451         boolean mHasNonEmptyGivenInternalInsets;
   26452 
   26453         /**
   26454          * All views in the window's hierarchy that serve as scroll containers,
   26455          * used to determine if the window can be resized or must be panned
   26456          * to adjust for a soft input area.
   26457          */
   26458         final ArrayList<View> mScrollContainers = new ArrayList<View>();
   26459 
   26460         final KeyEvent.DispatcherState mKeyDispatchState
   26461                 = new KeyEvent.DispatcherState();
   26462 
   26463         /**
   26464          * Indicates whether the view's window currently has the focus.
   26465          */
   26466         boolean mHasWindowFocus;
   26467 
   26468         /**
   26469          * The current visibility of the window.
   26470          */
   26471         int mWindowVisibility;
   26472 
   26473         /**
   26474          * Indicates the time at which drawing started to occur.
   26475          */
   26476         long mDrawingTime;
   26477 
   26478         /**
   26479          * Indicates whether or not ignoring the DIRTY_MASK flags.
   26480          */
   26481         boolean mIgnoreDirtyState;
   26482 
   26483         /**
   26484          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
   26485          * to avoid clearing that flag prematurely.
   26486          */
   26487         boolean mSetIgnoreDirtyState = false;
   26488 
   26489         /**
   26490          * Indicates whether the view's window is currently in touch mode.
   26491          */
   26492         boolean mInTouchMode;
   26493 
   26494         /**
   26495          * Indicates whether the view has requested unbuffered input dispatching for the current
   26496          * event stream.
   26497          */
   26498         boolean mUnbufferedDispatchRequested;
   26499 
   26500         /**
   26501          * Indicates that ViewAncestor should trigger a global layout change
   26502          * the next time it performs a traversal
   26503          */
   26504         boolean mRecomputeGlobalAttributes;
   26505 
   26506         /**
   26507          * Always report new attributes at next traversal.
   26508          */
   26509         boolean mForceReportNewAttributes;
   26510 
   26511         /**
   26512          * Set during a traveral if any views want to keep the screen on.
   26513          */
   26514         boolean mKeepScreenOn;
   26515 
   26516         /**
   26517          * Set during a traveral if the light center needs to be updated.
   26518          */
   26519         boolean mNeedsUpdateLightCenter;
   26520 
   26521         /**
   26522          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
   26523          */
   26524         int mSystemUiVisibility;
   26525 
   26526         /**
   26527          * Hack to force certain system UI visibility flags to be cleared.
   26528          */
   26529         int mDisabledSystemUiVisibility;
   26530 
   26531         /**
   26532          * Last global system UI visibility reported by the window manager.
   26533          */
   26534         int mGlobalSystemUiVisibility = -1;
   26535 
   26536         /**
   26537          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
   26538          * attached.
   26539          */
   26540         boolean mHasSystemUiListeners;
   26541 
   26542         /**
   26543          * Set if the window has requested to extend into the overscan region
   26544          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
   26545          */
   26546         boolean mOverscanRequested;
   26547 
   26548         /**
   26549          * Set if the visibility of any views has changed.
   26550          */
   26551         boolean mViewVisibilityChanged;
   26552 
   26553         /**
   26554          * Set to true if a view has been scrolled.
   26555          */
   26556         boolean mViewScrollChanged;
   26557 
   26558         /**
   26559          * Set to true if a pointer event is currently being handled.
   26560          */
   26561         boolean mHandlingPointerEvent;
   26562 
   26563         /**
   26564          * Global to the view hierarchy used as a temporary for dealing with
   26565          * x/y points in the transparent region computations.
   26566          */
   26567         final int[] mTransparentLocation = new int[2];
   26568 
   26569         /**
   26570          * Global to the view hierarchy used as a temporary for dealing with
   26571          * x/y points in the ViewGroup.invalidateChild implementation.
   26572          */
   26573         final int[] mInvalidateChildLocation = new int[2];
   26574 
   26575         /**
   26576          * Global to the view hierarchy used as a temporary for dealing with
   26577          * computing absolute on-screen location.
   26578          */
   26579         final int[] mTmpLocation = new int[2];
   26580 
   26581         /**
   26582          * Global to the view hierarchy used as a temporary for dealing with
   26583          * x/y location when view is transformed.
   26584          */
   26585         final float[] mTmpTransformLocation = new float[2];
   26586 
   26587         /**
   26588          * The view tree observer used to dispatch global events like
   26589          * layout, pre-draw, touch mode change, etc.
   26590          */
   26591         final ViewTreeObserver mTreeObserver;
   26592 
   26593         /**
   26594          * A Canvas used by the view hierarchy to perform bitmap caching.
   26595          */
   26596         Canvas mCanvas;
   26597 
   26598         /**
   26599          * The view root impl.
   26600          */
   26601         final ViewRootImpl mViewRootImpl;
   26602 
   26603         /**
   26604          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
   26605          * handler can be used to pump events in the UI events queue.
   26606          */
   26607         final Handler mHandler;
   26608 
   26609         /**
   26610          * Temporary for use in computing invalidate rectangles while
   26611          * calling up the hierarchy.
   26612          */
   26613         final Rect mTmpInvalRect = new Rect();
   26614 
   26615         /**
   26616          * Temporary for use in computing hit areas with transformed views
   26617          */
   26618         final RectF mTmpTransformRect = new RectF();
   26619 
   26620         /**
   26621          * Temporary for use in computing hit areas with transformed views
   26622          */
   26623         final RectF mTmpTransformRect1 = new RectF();
   26624 
   26625         /**
   26626          * Temporary list of rectanges.
   26627          */
   26628         final List<RectF> mTmpRectList = new ArrayList<>();
   26629 
   26630         /**
   26631          * Temporary for use in transforming invalidation rect
   26632          */
   26633         final Matrix mTmpMatrix = new Matrix();
   26634 
   26635         /**
   26636          * Temporary for use in transforming invalidation rect
   26637          */
   26638         final Transformation mTmpTransformation = new Transformation();
   26639 
   26640         /**
   26641          * Temporary for use in querying outlines from OutlineProviders
   26642          */
   26643         final Outline mTmpOutline = new Outline();
   26644 
   26645         /**
   26646          * Temporary list for use in collecting focusable descendents of a view.
   26647          */
   26648         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
   26649 
   26650         /**
   26651          * The id of the window for accessibility purposes.
   26652          */
   26653         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
   26654 
   26655         /**
   26656          * Flags related to accessibility processing.
   26657          *
   26658          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   26659          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
   26660          */
   26661         int mAccessibilityFetchFlags;
   26662 
   26663         /**
   26664          * The drawable for highlighting accessibility focus.
   26665          */
   26666         Drawable mAccessibilityFocusDrawable;
   26667 
   26668         /**
   26669          * The drawable for highlighting autofilled views.
   26670          *
   26671          * @see #isAutofilled()
   26672          */
   26673         Drawable mAutofilledDrawable;
   26674 
   26675         /**
   26676          * Show where the margins, bounds and layout bounds are for each view.
   26677          */
   26678         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
   26679 
   26680         /**
   26681          * Point used to compute visible regions.
   26682          */
   26683         final Point mPoint = new Point();
   26684 
   26685         /**
   26686          * Used to track which View originated a requestLayout() call, used when
   26687          * requestLayout() is called during layout.
   26688          */
   26689         View mViewRequestingLayout;
   26690 
   26691         /**
   26692          * Used to track views that need (at least) a partial relayout at their current size
   26693          * during the next traversal.
   26694          */
   26695         List<View> mPartialLayoutViews = new ArrayList<>();
   26696 
   26697         /**
   26698          * Swapped with mPartialLayoutViews during layout to avoid concurrent
   26699          * modification. Lazily assigned during ViewRootImpl layout.
   26700          */
   26701         List<View> mEmptyPartialLayoutViews;
   26702 
   26703         /**
   26704          * Used to track the identity of the current drag operation.
   26705          */
   26706         IBinder mDragToken;
   26707 
   26708         /**
   26709          * The drag shadow surface for the current drag operation.
   26710          */
   26711         public Surface mDragSurface;
   26712 
   26713 
   26714         /**
   26715          * The view that currently has a tooltip displayed.
   26716          */
   26717         View mTooltipHost;
   26718 
   26719         /**
   26720          * Creates a new set of attachment information with the specified
   26721          * events handler and thread.
   26722          *
   26723          * @param handler the events handler the view must use
   26724          */
   26725         AttachInfo(IWindowSession session, IWindow window, Display display,
   26726                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
   26727                 Context context) {
   26728             mSession = session;
   26729             mWindow = window;
   26730             mWindowToken = window.asBinder();
   26731             mDisplay = display;
   26732             mViewRootImpl = viewRootImpl;
   26733             mHandler = handler;
   26734             mRootCallbacks = effectPlayer;
   26735             mTreeObserver = new ViewTreeObserver(context);
   26736         }
   26737     }
   26738 
   26739     /**
   26740      * <p>ScrollabilityCache holds various fields used by a View when scrolling
   26741      * is supported. This avoids keeping too many unused fields in most
   26742      * instances of View.</p>
   26743      */
   26744     private static class ScrollabilityCache implements Runnable {
   26745 
   26746         /**
   26747          * Scrollbars are not visible
   26748          */
   26749         public static final int OFF = 0;
   26750 
   26751         /**
   26752          * Scrollbars are visible
   26753          */
   26754         public static final int ON = 1;
   26755 
   26756         /**
   26757          * Scrollbars are fading away
   26758          */
   26759         public static final int FADING = 2;
   26760 
   26761         public boolean fadeScrollBars;
   26762 
   26763         public int fadingEdgeLength;
   26764         public int scrollBarDefaultDelayBeforeFade;
   26765         public int scrollBarFadeDuration;
   26766 
   26767         public int scrollBarSize;
   26768         public int scrollBarMinTouchTarget;
   26769         public ScrollBarDrawable scrollBar;
   26770         public float[] interpolatorValues;
   26771         public View host;
   26772 
   26773         public final Paint paint;
   26774         public final Matrix matrix;
   26775         public Shader shader;
   26776 
   26777         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
   26778 
   26779         private static final float[] OPAQUE = { 255 };
   26780         private static final float[] TRANSPARENT = { 0.0f };
   26781 
   26782         /**
   26783          * When fading should start. This time moves into the future every time
   26784          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
   26785          */
   26786         public long fadeStartTime;
   26787 
   26788 
   26789         /**
   26790          * The current state of the scrollbars: ON, OFF, or FADING
   26791          */
   26792         public int state = OFF;
   26793 
   26794         private int mLastColor;
   26795 
   26796         public final Rect mScrollBarBounds = new Rect();
   26797         public final Rect mScrollBarTouchBounds = new Rect();
   26798 
   26799         public static final int NOT_DRAGGING = 0;
   26800         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
   26801         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
   26802         public int mScrollBarDraggingState = NOT_DRAGGING;
   26803 
   26804         public float mScrollBarDraggingPos = 0;
   26805 
   26806         public ScrollabilityCache(ViewConfiguration configuration, View host) {
   26807             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
   26808             scrollBarSize = configuration.getScaledScrollBarSize();
   26809             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
   26810             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
   26811             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
   26812 
   26813             paint = new Paint();
   26814             matrix = new Matrix();
   26815             // use use a height of 1, and then wack the matrix each time we
   26816             // actually use it.
   26817             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   26818             paint.setShader(shader);
   26819             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   26820 
   26821             this.host = host;
   26822         }
   26823 
   26824         public void setFadeColor(int color) {
   26825             if (color != mLastColor) {
   26826                 mLastColor = color;
   26827 
   26828                 if (color != 0) {
   26829                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
   26830                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
   26831                     paint.setShader(shader);
   26832                     // Restore the default transfer mode (src_over)
   26833                     paint.setXfermode(null);
   26834                 } else {
   26835                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   26836                     paint.setShader(shader);
   26837                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   26838                 }
   26839             }
   26840         }
   26841 
   26842         public void run() {
   26843             long now = AnimationUtils.currentAnimationTimeMillis();
   26844             if (now >= fadeStartTime) {
   26845 
   26846                 // the animation fades the scrollbars out by changing
   26847                 // the opacity (alpha) from fully opaque to fully
   26848                 // transparent
   26849                 int nextFrame = (int) now;
   26850                 int framesCount = 0;
   26851 
   26852                 Interpolator interpolator = scrollBarInterpolator;
   26853 
   26854                 // Start opaque
   26855                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
   26856 
   26857                 // End transparent
   26858                 nextFrame += scrollBarFadeDuration;
   26859                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
   26860 
   26861                 state = FADING;
   26862 
   26863                 // Kick off the fade animation
   26864                 host.invalidate(true);
   26865             }
   26866         }
   26867     }
   26868 
   26869     /**
   26870      * Resuable callback for sending
   26871      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   26872      */
   26873     private class SendViewScrolledAccessibilityEvent implements Runnable {
   26874         public volatile boolean mIsPending;
   26875         public int mDeltaX;
   26876         public int mDeltaY;
   26877 
   26878         public void post(int dx, int dy) {
   26879             mDeltaX += dx;
   26880             mDeltaY += dy;
   26881             if (!mIsPending) {
   26882                 mIsPending = true;
   26883                 postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
   26884             }
   26885         }
   26886 
   26887         @Override
   26888         public void run() {
   26889             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   26890                 AccessibilityEvent event = AccessibilityEvent.obtain(
   26891                         AccessibilityEvent.TYPE_VIEW_SCROLLED);
   26892                 event.setScrollDeltaX(mDeltaX);
   26893                 event.setScrollDeltaY(mDeltaY);
   26894                 sendAccessibilityEventUnchecked(event);
   26895             }
   26896             reset();
   26897         }
   26898 
   26899         private void reset() {
   26900             mIsPending = false;
   26901             mDeltaX = 0;
   26902             mDeltaY = 0;
   26903         }
   26904     }
   26905 
   26906     /**
   26907      * Remove the pending callback for sending a
   26908      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   26909      */
   26910     private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) {
   26911         if (callback == null || !callback.mIsPending) return;
   26912         removeCallbacks(callback);
   26913         callback.reset();
   26914     }
   26915 
   26916     /**
   26917      * <p>
   26918      * This class represents a delegate that can be registered in a {@link View}
   26919      * to enhance accessibility support via composition rather via inheritance.
   26920      * It is specifically targeted to widget developers that extend basic View
   26921      * classes i.e. classes in package android.view, that would like their
   26922      * applications to be backwards compatible.
   26923      * </p>
   26924      * <div class="special reference">
   26925      * <h3>Developer Guides</h3>
   26926      * <p>For more information about making applications accessible, read the
   26927      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
   26928      * developer guide.</p>
   26929      * </div>
   26930      * <p>
   26931      * A scenario in which a developer would like to use an accessibility delegate
   26932      * is overriding a method introduced in a later API version than the minimal API
   26933      * version supported by the application. For example, the method
   26934      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
   26935      * in API version 4 when the accessibility APIs were first introduced. If a
   26936      * developer would like their application to run on API version 4 devices (assuming
   26937      * all other APIs used by the application are version 4 or lower) and take advantage
   26938      * of this method, instead of overriding the method which would break the application's
   26939      * backwards compatibility, they can override the corresponding method in this
   26940      * delegate and register the delegate in the target View if the API version of
   26941      * the system is high enough, i.e. the API version is the same as or higher than the API
   26942      * version that introduced
   26943      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
   26944      * </p>
   26945      * <p>
   26946      * Here is an example implementation:
   26947      * </p>
   26948      * <code><pre><p>
   26949      * if (Build.VERSION.SDK_INT >= 14) {
   26950      *     // If the API version is equal of higher than the version in
   26951      *     // which onInitializeAccessibilityNodeInfo was introduced we
   26952      *     // register a delegate with a customized implementation.
   26953      *     View view = findViewById(R.id.view_id);
   26954      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
   26955      *         public void onInitializeAccessibilityNodeInfo(View host,
   26956      *                 AccessibilityNodeInfo info) {
   26957      *             // Let the default implementation populate the info.
   26958      *             super.onInitializeAccessibilityNodeInfo(host, info);
   26959      *             // Set some other information.
   26960      *             info.setEnabled(host.isEnabled());
   26961      *         }
   26962      *     });
   26963      * }
   26964      * </code></pre></p>
   26965      * <p>
   26966      * This delegate contains methods that correspond to the accessibility methods
   26967      * in View. If a delegate has been specified the implementation in View hands
   26968      * off handling to the corresponding method in this delegate. The default
   26969      * implementation the delegate methods behaves exactly as the corresponding
   26970      * method in View for the case of no accessibility delegate been set. Hence,
   26971      * to customize the behavior of a View method, clients can override only the
   26972      * corresponding delegate method without altering the behavior of the rest
   26973      * accessibility related methods of the host view.
   26974      * </p>
   26975      * <p>
   26976      * <strong>Note:</strong> On platform versions prior to
   26977      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
   26978      * views in the {@code android.widget.*} package are called <i>before</i>
   26979      * host methods. This prevents certain properties such as class name from
   26980      * being modified by overriding
   26981      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
   26982      * as any changes will be overwritten by the host class.
   26983      * <p>
   26984      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
   26985      * methods are called <i>after</i> host methods, which all properties to be
   26986      * modified without being overwritten by the host class.
   26987      */
   26988     public static class AccessibilityDelegate {
   26989 
   26990         /**
   26991          * Sends an accessibility event of the given type. If accessibility is not
   26992          * enabled this method has no effect.
   26993          * <p>
   26994          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
   26995          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
   26996          * been set.
   26997          * </p>
   26998          *
   26999          * @param host The View hosting the delegate.
   27000          * @param eventType The type of the event to send.
   27001          *
   27002          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
   27003          */
   27004         public void sendAccessibilityEvent(View host, int eventType) {
   27005             host.sendAccessibilityEventInternal(eventType);
   27006         }
   27007 
   27008         /**
   27009          * Performs the specified accessibility action on the view. For
   27010          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   27011          * <p>
   27012          * The default implementation behaves as
   27013          * {@link View#performAccessibilityAction(int, Bundle)
   27014          *  View#performAccessibilityAction(int, Bundle)} for the case of
   27015          *  no accessibility delegate been set.
   27016          * </p>
   27017          *
   27018          * @param action The action to perform.
   27019          * @return Whether the action was performed.
   27020          *
   27021          * @see View#performAccessibilityAction(int, Bundle)
   27022          *      View#performAccessibilityAction(int, Bundle)
   27023          */
   27024         public boolean performAccessibilityAction(View host, int action, Bundle args) {
   27025             return host.performAccessibilityActionInternal(action, args);
   27026         }
   27027 
   27028         /**
   27029          * Sends an accessibility event. This method behaves exactly as
   27030          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
   27031          * empty {@link AccessibilityEvent} and does not perform a check whether
   27032          * accessibility is enabled.
   27033          * <p>
   27034          * The default implementation behaves as
   27035          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   27036          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
   27037          * the case of no accessibility delegate been set.
   27038          * </p>
   27039          *
   27040          * @param host The View hosting the delegate.
   27041          * @param event The event to send.
   27042          *
   27043          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   27044          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   27045          */
   27046         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
   27047             host.sendAccessibilityEventUncheckedInternal(event);
   27048         }
   27049 
   27050         /**
   27051          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
   27052          * to its children for adding their text content to the event.
   27053          * <p>
   27054          * The default implementation behaves as
   27055          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   27056          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
   27057          * the case of no accessibility delegate been set.
   27058          * </p>
   27059          *
   27060          * @param host The View hosting the delegate.
   27061          * @param event The event.
   27062          * @return True if the event population was completed.
   27063          *
   27064          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   27065          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   27066          */
   27067         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   27068             return host.dispatchPopulateAccessibilityEventInternal(event);
   27069         }
   27070 
   27071         /**
   27072          * Gives a chance to the host View to populate the accessibility event with its
   27073          * text content.
   27074          * <p>
   27075          * The default implementation behaves as
   27076          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
   27077          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
   27078          * the case of no accessibility delegate been set.
   27079          * </p>
   27080          *
   27081          * @param host The View hosting the delegate.
   27082          * @param event The accessibility event which to populate.
   27083          *
   27084          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
   27085          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
   27086          */
   27087         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   27088             host.onPopulateAccessibilityEventInternal(event);
   27089         }
   27090 
   27091         /**
   27092          * Initializes an {@link AccessibilityEvent} with information about the
   27093          * the host View which is the event source.
   27094          * <p>
   27095          * The default implementation behaves as
   27096          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
   27097          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
   27098          * the case of no accessibility delegate been set.
   27099          * </p>
   27100          *
   27101          * @param host The View hosting the delegate.
   27102          * @param event The event to initialize.
   27103          *
   27104          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
   27105          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
   27106          */
   27107         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
   27108             host.onInitializeAccessibilityEventInternal(event);
   27109         }
   27110 
   27111         /**
   27112          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
   27113          * <p>
   27114          * The default implementation behaves as
   27115          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   27116          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
   27117          * the case of no accessibility delegate been set.
   27118          * </p>
   27119          *
   27120          * @param host The View hosting the delegate.
   27121          * @param info The instance to initialize.
   27122          *
   27123          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   27124          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   27125          */
   27126         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
   27127             host.onInitializeAccessibilityNodeInfoInternal(info);
   27128         }
   27129 
   27130         /**
   27131          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
   27132          * additional data.
   27133          * <p>
   27134          * This method only needs to be implemented if the View offers to provide additional data.
   27135          * </p>
   27136          * <p>
   27137          * The default implementation behaves as
   27138          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
   27139          * for the case where no accessibility delegate is set.
   27140          * </p>
   27141          *
   27142          * @param host The View hosting the delegate. Never {@code null}.
   27143          * @param info The info to which to add the extra data. Never {@code null}.
   27144          * @param extraDataKey A key specifying the type of extra data to add to the info. The
   27145          *                     extra data should be added to the {@link Bundle} returned by
   27146          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
   27147          *                     {@code null}.
   27148          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
   27149          *                  May be {@code null} if the if the service provided no arguments.
   27150          *
   27151          * @see AccessibilityNodeInfo#setExtraAvailableData
   27152          */
   27153         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
   27154                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
   27155                 @Nullable Bundle arguments) {
   27156             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
   27157         }
   27158 
   27159         /**
   27160          * Called when a child of the host View has requested sending an
   27161          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
   27162          * to augment the event.
   27163          * <p>
   27164          * The default implementation behaves as
   27165          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   27166          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
   27167          * the case of no accessibility delegate been set.
   27168          * </p>
   27169          *
   27170          * @param host The View hosting the delegate.
   27171          * @param child The child which requests sending the event.
   27172          * @param event The event to be sent.
   27173          * @return True if the event should be sent
   27174          *
   27175          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   27176          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   27177          */
   27178         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
   27179                 AccessibilityEvent event) {
   27180             return host.onRequestSendAccessibilityEventInternal(child, event);
   27181         }
   27182 
   27183         /**
   27184          * Gets the provider for managing a virtual view hierarchy rooted at this View
   27185          * and reported to {@link android.accessibilityservice.AccessibilityService}s
   27186          * that explore the window content.
   27187          * <p>
   27188          * The default implementation behaves as
   27189          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
   27190          * the case of no accessibility delegate been set.
   27191          * </p>
   27192          *
   27193          * @return The provider.
   27194          *
   27195          * @see AccessibilityNodeProvider
   27196          */
   27197         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
   27198             return null;
   27199         }
   27200 
   27201         /**
   27202          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
   27203          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   27204          * This method is responsible for obtaining an accessibility node info from a
   27205          * pool of reusable instances and calling
   27206          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
   27207          * view to initialize the former.
   27208          * <p>
   27209          * <strong>Note:</strong> The client is responsible for recycling the obtained
   27210          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
   27211          * creation.
   27212          * </p>
   27213          * <p>
   27214          * The default implementation behaves as
   27215          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
   27216          * the case of no accessibility delegate been set.
   27217          * </p>
   27218          * @return A populated {@link AccessibilityNodeInfo}.
   27219          *
   27220          * @see AccessibilityNodeInfo
   27221          *
   27222          * @hide
   27223          */
   27224         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
   27225             return host.createAccessibilityNodeInfoInternal();
   27226         }
   27227     }
   27228 
   27229     private static class MatchIdPredicate implements Predicate<View> {
   27230         public int mId;
   27231 
   27232         @Override
   27233         public boolean test(View view) {
   27234             return (view.mID == mId);
   27235         }
   27236     }
   27237 
   27238     private static class MatchLabelForPredicate implements Predicate<View> {
   27239         private int mLabeledId;
   27240 
   27241         @Override
   27242         public boolean test(View view) {
   27243             return (view.mLabelForId == mLabeledId);
   27244         }
   27245     }
   27246 
   27247     /**
   27248      * Dump all private flags in readable format, useful for documentation and
   27249      * sanity checking.
   27250      */
   27251     private static void dumpFlags() {
   27252         final HashMap<String, String> found = Maps.newHashMap();
   27253         try {
   27254             for (Field field : View.class.getDeclaredFields()) {
   27255                 final int modifiers = field.getModifiers();
   27256                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
   27257                     if (field.getType().equals(int.class)) {
   27258                         final int value = field.getInt(null);
   27259                         dumpFlag(found, field.getName(), value);
   27260                     } else if (field.getType().equals(int[].class)) {
   27261                         final int[] values = (int[]) field.get(null);
   27262                         for (int i = 0; i < values.length; i++) {
   27263                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
   27264                         }
   27265                     }
   27266                 }
   27267             }
   27268         } catch (IllegalAccessException e) {
   27269             throw new RuntimeException(e);
   27270         }
   27271 
   27272         final ArrayList<String> keys = Lists.newArrayList();
   27273         keys.addAll(found.keySet());
   27274         Collections.sort(keys);
   27275         for (String key : keys) {
   27276             Log.d(VIEW_LOG_TAG, found.get(key));
   27277         }
   27278     }
   27279 
   27280     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
   27281         // Sort flags by prefix, then by bits, always keeping unique keys
   27282         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
   27283         final int prefix = name.indexOf('_');
   27284         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
   27285         final String output = bits + " " + name;
   27286         found.put(key, output);
   27287     }
   27288 
   27289     /** {@hide} */
   27290     public void encode(@NonNull ViewHierarchyEncoder stream) {
   27291         stream.beginObject(this);
   27292         encodeProperties(stream);
   27293         stream.endObject();
   27294     }
   27295 
   27296     /** {@hide} */
   27297     @CallSuper
   27298     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
   27299         Object resolveId = ViewDebug.resolveId(getContext(), mID);
   27300         if (resolveId instanceof String) {
   27301             stream.addProperty("id", (String) resolveId);
   27302         } else {
   27303             stream.addProperty("id", mID);
   27304         }
   27305 
   27306         stream.addProperty("misc:transformation.alpha",
   27307                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
   27308         stream.addProperty("misc:transitionName", getTransitionName());
   27309 
   27310         // layout
   27311         stream.addProperty("layout:left", mLeft);
   27312         stream.addProperty("layout:right", mRight);
   27313         stream.addProperty("layout:top", mTop);
   27314         stream.addProperty("layout:bottom", mBottom);
   27315         stream.addProperty("layout:width", getWidth());
   27316         stream.addProperty("layout:height", getHeight());
   27317         stream.addProperty("layout:layoutDirection", getLayoutDirection());
   27318         stream.addProperty("layout:layoutRtl", isLayoutRtl());
   27319         stream.addProperty("layout:hasTransientState", hasTransientState());
   27320         stream.addProperty("layout:baseline", getBaseline());
   27321 
   27322         // layout params
   27323         ViewGroup.LayoutParams layoutParams = getLayoutParams();
   27324         if (layoutParams != null) {
   27325             stream.addPropertyKey("layoutParams");
   27326             layoutParams.encode(stream);
   27327         }
   27328 
   27329         // scrolling
   27330         stream.addProperty("scrolling:scrollX", mScrollX);
   27331         stream.addProperty("scrolling:scrollY", mScrollY);
   27332 
   27333         // padding
   27334         stream.addProperty("padding:paddingLeft", mPaddingLeft);
   27335         stream.addProperty("padding:paddingRight", mPaddingRight);
   27336         stream.addProperty("padding:paddingTop", mPaddingTop);
   27337         stream.addProperty("padding:paddingBottom", mPaddingBottom);
   27338         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
   27339         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
   27340         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
   27341         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
   27342         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
   27343 
   27344         // measurement
   27345         stream.addProperty("measurement:minHeight", mMinHeight);
   27346         stream.addProperty("measurement:minWidth", mMinWidth);
   27347         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
   27348         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
   27349 
   27350         // drawing
   27351         stream.addProperty("drawing:elevation", getElevation());
   27352         stream.addProperty("drawing:translationX", getTranslationX());
   27353         stream.addProperty("drawing:translationY", getTranslationY());
   27354         stream.addProperty("drawing:translationZ", getTranslationZ());
   27355         stream.addProperty("drawing:rotation", getRotation());
   27356         stream.addProperty("drawing:rotationX", getRotationX());
   27357         stream.addProperty("drawing:rotationY", getRotationY());
   27358         stream.addProperty("drawing:scaleX", getScaleX());
   27359         stream.addProperty("drawing:scaleY", getScaleY());
   27360         stream.addProperty("drawing:pivotX", getPivotX());
   27361         stream.addProperty("drawing:pivotY", getPivotY());
   27362         stream.addProperty("drawing:clipBounds",
   27363                 mClipBounds == null ? null : mClipBounds.toString());
   27364         stream.addProperty("drawing:opaque", isOpaque());
   27365         stream.addProperty("drawing:alpha", getAlpha());
   27366         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
   27367         stream.addProperty("drawing:shadow", hasShadow());
   27368         stream.addProperty("drawing:solidColor", getSolidColor());
   27369         stream.addProperty("drawing:layerType", mLayerType);
   27370         stream.addProperty("drawing:willNotDraw", willNotDraw());
   27371         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
   27372         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
   27373         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
   27374         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
   27375         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
   27376         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
   27377 
   27378         // focus
   27379         stream.addProperty("focus:hasFocus", hasFocus());
   27380         stream.addProperty("focus:isFocused", isFocused());
   27381         stream.addProperty("focus:focusable", getFocusable());
   27382         stream.addProperty("focus:isFocusable", isFocusable());
   27383         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
   27384 
   27385         stream.addProperty("misc:clickable", isClickable());
   27386         stream.addProperty("misc:pressed", isPressed());
   27387         stream.addProperty("misc:selected", isSelected());
   27388         stream.addProperty("misc:touchMode", isInTouchMode());
   27389         stream.addProperty("misc:hovered", isHovered());
   27390         stream.addProperty("misc:activated", isActivated());
   27391 
   27392         stream.addProperty("misc:visibility", getVisibility());
   27393         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
   27394         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
   27395 
   27396         stream.addProperty("misc:enabled", isEnabled());
   27397         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
   27398         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
   27399 
   27400         // theme attributes
   27401         Resources.Theme theme = getContext().getTheme();
   27402         if (theme != null) {
   27403             stream.addPropertyKey("theme");
   27404             theme.encode(stream);
   27405         }
   27406 
   27407         // view attribute information
   27408         int n = mAttributes != null ? mAttributes.length : 0;
   27409         stream.addProperty("meta:__attrCount__", n/2);
   27410         for (int i = 0; i < n; i += 2) {
   27411             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
   27412         }
   27413 
   27414         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
   27415 
   27416         // text
   27417         stream.addProperty("text:textDirection", getTextDirection());
   27418         stream.addProperty("text:textAlignment", getTextAlignment());
   27419 
   27420         // accessibility
   27421         CharSequence contentDescription = getContentDescription();
   27422         stream.addProperty("accessibility:contentDescription",
   27423                 contentDescription == null ? "" : contentDescription.toString());
   27424         stream.addProperty("accessibility:labelFor", getLabelFor());
   27425         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
   27426     }
   27427 
   27428     /**
   27429      * Determine if this view is rendered on a round wearable device and is the main view
   27430      * on the screen.
   27431      */
   27432     boolean shouldDrawRoundScrollbar() {
   27433         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
   27434             return false;
   27435         }
   27436 
   27437         final View rootView = getRootView();
   27438         final WindowInsets insets = getRootWindowInsets();
   27439 
   27440         int height = getHeight();
   27441         int width = getWidth();
   27442         int displayHeight = rootView.getHeight();
   27443         int displayWidth = rootView.getWidth();
   27444 
   27445         if (height != displayHeight || width != displayWidth) {
   27446             return false;
   27447         }
   27448 
   27449         getLocationInWindow(mAttachInfo.mTmpLocation);
   27450         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
   27451                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
   27452     }
   27453 
   27454     /**
   27455      * Sets the tooltip text which will be displayed in a small popup next to the view.
   27456      * <p>
   27457      * The tooltip will be displayed:
   27458      * <ul>
   27459      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
   27460      * menu). </li>
   27461      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
   27462      * </ul>
   27463      * <p>
   27464      * <strong>Note:</strong> Do not override this method, as it will have no
   27465      * effect on the text displayed in the tooltip.
   27466      *
   27467      * @param tooltipText the tooltip text, or null if no tooltip is required
   27468      * @see #getTooltipText()
   27469      * @attr ref android.R.styleable#View_tooltipText
   27470      */
   27471     public void setTooltipText(@Nullable CharSequence tooltipText) {
   27472         if (TextUtils.isEmpty(tooltipText)) {
   27473             setFlags(0, TOOLTIP);
   27474             hideTooltip();
   27475             mTooltipInfo = null;
   27476         } else {
   27477             setFlags(TOOLTIP, TOOLTIP);
   27478             if (mTooltipInfo == null) {
   27479                 mTooltipInfo = new TooltipInfo();
   27480                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
   27481                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
   27482                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
   27483                 mTooltipInfo.clearAnchorPos();
   27484             }
   27485             mTooltipInfo.mTooltipText = tooltipText;
   27486         }
   27487     }
   27488 
   27489     /**
   27490      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
   27491      */
   27492     public void setTooltip(@Nullable CharSequence tooltipText) {
   27493         setTooltipText(tooltipText);
   27494     }
   27495 
   27496     /**
   27497      * Returns the view's tooltip text.
   27498      *
   27499      * <strong>Note:</strong> Do not override this method, as it will have no
   27500      * effect on the text displayed in the tooltip. You must call
   27501      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
   27502      *
   27503      * @return the tooltip text
   27504      * @see #setTooltipText(CharSequence)
   27505      * @attr ref android.R.styleable#View_tooltipText
   27506      */
   27507     @Nullable
   27508     public CharSequence getTooltipText() {
   27509         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
   27510     }
   27511 
   27512     /**
   27513      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
   27514      */
   27515     @Nullable
   27516     public CharSequence getTooltip() {
   27517         return getTooltipText();
   27518     }
   27519 
   27520     private boolean showTooltip(int x, int y, boolean fromLongClick) {
   27521         if (mAttachInfo == null || mTooltipInfo == null) {
   27522             return false;
   27523         }
   27524         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
   27525             return false;
   27526         }
   27527         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
   27528             return false;
   27529         }
   27530         hideTooltip();
   27531         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
   27532         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
   27533         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
   27534         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
   27535         mAttachInfo.mTooltipHost = this;
   27536         // The available accessibility actions have changed
   27537         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
   27538         return true;
   27539     }
   27540 
   27541     void hideTooltip() {
   27542         if (mTooltipInfo == null) {
   27543             return;
   27544         }
   27545         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
   27546         if (mTooltipInfo.mTooltipPopup == null) {
   27547             return;
   27548         }
   27549         mTooltipInfo.mTooltipPopup.hide();
   27550         mTooltipInfo.mTooltipPopup = null;
   27551         mTooltipInfo.mTooltipFromLongClick = false;
   27552         mTooltipInfo.clearAnchorPos();
   27553         if (mAttachInfo != null) {
   27554             mAttachInfo.mTooltipHost = null;
   27555         }
   27556         // The available accessibility actions have changed
   27557         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
   27558     }
   27559 
   27560     private boolean showLongClickTooltip(int x, int y) {
   27561         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
   27562         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
   27563         return showTooltip(x, y, true);
   27564     }
   27565 
   27566     private boolean showHoverTooltip() {
   27567         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
   27568     }
   27569 
   27570     boolean dispatchTooltipHoverEvent(MotionEvent event) {
   27571         if (mTooltipInfo == null) {
   27572             return false;
   27573         }
   27574         switch(event.getAction()) {
   27575             case MotionEvent.ACTION_HOVER_MOVE:
   27576                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
   27577                     break;
   27578                 }
   27579                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
   27580                     if (mTooltipInfo.mTooltipPopup == null) {
   27581                         // Schedule showing the tooltip after a timeout.
   27582                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
   27583                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
   27584                                 ViewConfiguration.getHoverTooltipShowTimeout());
   27585                     }
   27586 
   27587                     // Hide hover-triggered tooltip after a period of inactivity.
   27588                     // Match the timeout used by NativeInputManager to hide the mouse pointer
   27589                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
   27590                     final int timeout;
   27591                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
   27592                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
   27593                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
   27594                     } else {
   27595                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
   27596                     }
   27597                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
   27598                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
   27599                 }
   27600                 return true;
   27601 
   27602             case MotionEvent.ACTION_HOVER_EXIT:
   27603                 mTooltipInfo.clearAnchorPos();
   27604                 if (!mTooltipInfo.mTooltipFromLongClick) {
   27605                     hideTooltip();
   27606                 }
   27607                 break;
   27608         }
   27609         return false;
   27610     }
   27611 
   27612     void handleTooltipKey(KeyEvent event) {
   27613         switch (event.getAction()) {
   27614             case KeyEvent.ACTION_DOWN:
   27615                 if (event.getRepeatCount() == 0) {
   27616                     hideTooltip();
   27617                 }
   27618                 break;
   27619 
   27620             case KeyEvent.ACTION_UP:
   27621                 handleTooltipUp();
   27622                 break;
   27623         }
   27624     }
   27625 
   27626     private void handleTooltipUp() {
   27627         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
   27628             return;
   27629         }
   27630         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
   27631         postDelayed(mTooltipInfo.mHideTooltipRunnable,
   27632                 ViewConfiguration.getLongPressTooltipHideTimeout());
   27633     }
   27634 
   27635     private int getFocusableAttribute(TypedArray attributes) {
   27636         TypedValue val = new TypedValue();
   27637         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
   27638             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
   27639                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
   27640             } else {
   27641                 return val.data;
   27642             }
   27643         } else {
   27644             return FOCUSABLE_AUTO;
   27645         }
   27646     }
   27647 
   27648     /**
   27649      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
   27650      * is not showing.
   27651      * @hide
   27652      */
   27653     @TestApi
   27654     public View getTooltipView() {
   27655         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
   27656             return null;
   27657         }
   27658         return mTooltipInfo.mTooltipPopup.getContentView();
   27659     }
   27660 
   27661     /**
   27662      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
   27663      * @hide
   27664      */
   27665     @TestApi
   27666     public static boolean isDefaultFocusHighlightEnabled() {
   27667         return sUseDefaultFocusHighlight;
   27668     }
   27669 
   27670     /**
   27671      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
   27672      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
   27673      * (visually on-top views first).
   27674      *
   27675      * @param evt the previously unhandled {@link KeyEvent}.
   27676      * @return the {@link View} which consumed the event or {@code null} if not consumed.
   27677      */
   27678     View dispatchUnhandledKeyEvent(KeyEvent evt) {
   27679         if (onUnhandledKeyEvent(evt)) {
   27680             return this;
   27681         }
   27682         return null;
   27683     }
   27684 
   27685     /**
   27686      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
   27687      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
   27688      * this will dispatch into all the listeners registered via
   27689      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
   27690      * order (most recently added will receive events first).
   27691      *
   27692      * @param event An unhandled event.
   27693      * @return {@code true} if the event was handled, {@code false} otherwise.
   27694      * @see #addOnUnhandledKeyEventListener
   27695      */
   27696     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
   27697         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
   27698             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
   27699                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
   27700                     return true;
   27701                 }
   27702             }
   27703         }
   27704         return false;
   27705     }
   27706 
   27707     boolean hasUnhandledKeyListener() {
   27708         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
   27709                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
   27710     }
   27711 
   27712     /**
   27713      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
   27714      * UI thread.
   27715      *
   27716      * @param listener a receiver of unhandled {@link KeyEvent}s.
   27717      * @see #removeOnUnhandledKeyEventListener
   27718      */
   27719     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
   27720         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
   27721         if (listeners == null) {
   27722             listeners = new ArrayList<>();
   27723             getListenerInfo().mUnhandledKeyListeners = listeners;
   27724         }
   27725         listeners.add(listener);
   27726         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
   27727             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
   27728         }
   27729     }
   27730 
   27731     /**
   27732      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
   27733      * UI thread.
   27734      *
   27735      * @param listener a receiver of unhandled {@link KeyEvent}s.
   27736      * @see #addOnUnhandledKeyEventListener
   27737      */
   27738     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
   27739         if (mListenerInfo != null) {
   27740             if (mListenerInfo.mUnhandledKeyListeners != null
   27741                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
   27742                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
   27743                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
   27744                     mListenerInfo.mUnhandledKeyListeners = null;
   27745                     if (mParent instanceof ViewGroup) {
   27746                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
   27747                     }
   27748                 }
   27749             }
   27750         }
   27751     }
   27752 }
   27753